1 /**
2 * \file
3 *
4 * \brief Global interrupt management for SAM D20, SAM3 and SAM4 (NVIC based)
5 *
6 * Copyright (c) 2012-2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #ifndef UTILS_INTERRUPT_INTERRUPT_H
48 #define UTILS_INTERRUPT_INTERRUPT_H
49
50 #include <compiler.h>
51 #include <parts.h>
52
53 #ifdef __cplusplus
54 extern "C" {
55 #endif
56
57 /**
58 * \weakgroup interrupt_group
59 *
60 * @{
61 */
62
63 /**
64 * \name Interrupt Service Routine definition
65 *
66 * @{
67 */
68
69 /**
70 * \brief Define service routine
71 *
72 * \note For NVIC devices the interrupt service routines are predefined to
73 * add to vector table in binary generation, so there is no service
74 * register at run time. The routine collections are in exceptions.h.
75 *
76 * Usage:
77 * \code
78 ISR(foo_irq_handler)
79 {
80 // Function definition
81 ...
82 }
83 \endcode
84 *
85 * \param func Name for the function.
86 */
87 # define ISR(func) \
88 void func (void)
89
90 /**
91 * \brief Initialize interrupt vectors
92 *
93 * For NVIC the interrupt vectors are put in vector table. So nothing
94 * to do to initialize them, except defined the vector function with
95 * right name.
96 *
97 * This must be called prior to \ref irq_register_handler.
98 */
99 # define irq_initialize_vectors() \
100 do { \
101 } while(0)
102
103 /**
104 * \brief Register handler for interrupt
105 *
106 * For NVIC the interrupt vectors are put in vector table. So nothing
107 * to do to register them, except defined the vector function with
108 * right name.
109 *
110 * Usage:
111 * \code
112 irq_initialize_vectors();
113 irq_register_handler(foo_irq_handler);
114 \endcode
115 *
116 * \note The function \a func must be defined with the \ref ISR macro.
117 * \note The functions prototypes can be found in the device exception header
118 * files (exceptions.h).
119 */
120 # define irq_register_handler(int_num, int_prio) \
121 NVIC_ClearPendingIRQ( (IRQn_Type)int_num); \
122 NVIC_SetPriority( (IRQn_Type)int_num, int_prio); \
123 NVIC_EnableIRQ( (IRQn_Type)int_num); \
124
125 //@}
126
127 # define cpu_irq_enable() \
128 do { \
129 g_interrupt_enabled = true; \
130 __DMB(); \
131 __enable_irq(); \
132 } while (0)
133 # define cpu_irq_disable() \
134 do { \
135 __disable_irq(); \
136 __DMB(); \
137 g_interrupt_enabled = false; \
138 } while (0)
139
140 typedef uint32_t irqflags_t;
141
142 #if !defined(__DOXYGEN__)
143 extern volatile bool g_interrupt_enabled;
144 #endif
145
146 #define cpu_irq_is_enabled() (__get_PRIMASK() == 0)
147
148 static volatile uint32_t cpu_irq_critical_section_counter;
149 static volatile bool cpu_irq_prev_interrupt_state;
150
cpu_irq_save(void)151 static inline irqflags_t cpu_irq_save(void)
152 {
153 irqflags_t flags = cpu_irq_is_enabled();
154 cpu_irq_disable();
155 return flags;
156 }
157
cpu_irq_is_enabled_flags(irqflags_t flags)158 static inline bool cpu_irq_is_enabled_flags(irqflags_t flags)
159 {
160 return (flags);
161 }
162
cpu_irq_restore(irqflags_t flags)163 static inline void cpu_irq_restore(irqflags_t flags)
164 {
165 if (cpu_irq_is_enabled_flags(flags))
166 cpu_irq_enable();
167 }
168
169 void cpu_irq_enter_critical(void);
170 void cpu_irq_leave_critical(void);
171
172 /**
173 * \weakgroup interrupt_deprecated_group
174 * @{
175 */
176
177 #define Enable_global_interrupt() cpu_irq_enable()
178 #define Disable_global_interrupt() cpu_irq_disable()
179 #define Is_global_interrupt_enabled() cpu_irq_is_enabled()
180
181 //@}
182
183 //@}
184
185 #ifdef __cplusplus
186 }
187 #endif
188
189 #endif /* UTILS_INTERRUPT_INTERRUPT_H */
190