1 /**
2  * \file
3  *
4  * \brief SAM System Interrupt Driver
5  *
6  * Copyright (C) 2012-2016 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 #ifndef SYSTEM_INTERRUPT_H_INCLUDED
47 #define SYSTEM_INTERRUPT_H_INCLUDED
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 /**
54  * \defgroup asfdoc_sam0_system_interrupt_group SAM System Interrupt (SYSTEM INTERRUPT) Driver
55  *
56  * This driver for Atmel&reg; | SMART ARM&reg;-based microcontrollers provides
57  * an interface for the configuration and management of internal software and
58  * hardware interrupts/exceptions.
59  *
60  * The following peripheral is used by this module:
61  *  - NVIC (Nested Vector Interrupt Controller)
62  *
63  * The following devices can use this module:
64  *  - Atmel | SMART SAM D20/D21
65  *  - Atmel | SMART SAM R21
66  *  - Atmel | SMART SAM D09/D10/D11
67  *  - Atmel | SMART SAM L21/L22
68  *  - Atmel | SMART SAM DA1
69  *  - Atmel | SMART SAM C20/C21
70  *  - Atmel | SMART SAM HA1
71  *
72  * The outline of this documentation is as follows:
73  *  - \ref asfdoc_sam0_system_interrupt_prerequisites
74  *  - \ref asfdoc_sam0_system_interrupt_module_overview
75  *  - \ref asfdoc_sam0_system_interrupt_special_considerations
76  *  - \ref asfdoc_sam0_system_interrupt_extra_info
77  *  - \ref asfdoc_sam0_system_interrupt_examples
78  *  - \ref asfdoc_sam0_system_interrupt_api_overview
79  *
80  *
81  * \section asfdoc_sam0_system_interrupt_prerequisites Prerequisites
82  *
83  * There are no prerequisites for this module.
84  *
85  *
86  * \section asfdoc_sam0_system_interrupt_module_overview Module Overview
87  *
88  * The ARM&reg; Cortex&reg; M0+ core contains an interrupt and exception vector table, which
89  * can be used to configure the device's interrupt handlers; individual
90  * interrupts and exceptions can be enabled and disabled, as well as configured
91  * with a variable priority.
92  *
93  * This driver provides a set of wrappers around the core interrupt functions,
94  * to expose a simple API for the management of global and individual interrupts
95  * within the device.
96  *
97  * \subsection asfdoc_sam0_system_interrupt_module_overview_criticalsec Critical Sections
98  * In some applications it is important to ensure that no interrupts may be
99  * executed by the system whilst a critical portion of code is being run; for
100  * example, a buffer may be copied from one context to another - during which
101  * interrupts must be disabled to avoid corruption of the source buffer contents
102  * until the copy has completed. This driver provides a basic API to enter and
103  * exit nested critical sections, so that global interrupts can be kept disabled
104  * for as long as necessary to complete a critical application code section.
105  *
106  * \subsection asfdoc_sam0_system_interrupt_module_overview_softints Software Interrupts
107  * For some applications, it may be desirable to raise a module or core
108  * interrupt via software. For this reason, a set of APIs to set an interrupt or
109  * exception as pending are provided to the user application.
110  *
111  * \section asfdoc_sam0_system_interrupt_special_considerations Special Considerations
112  *
113  * Interrupts from peripherals in the SAM devices are on a per-module basis;
114  * an interrupt raised from any source within a module will cause a single,
115  * module-common handler to execute. It is the user application or driver's
116  * responsibility to de-multiplex the module-common interrupt to determine the
117  * exact interrupt cause.
118  *
119  * \section asfdoc_sam0_system_interrupt_extra_info Extra Information
120  *
121  * For extra information, see \ref asfdoc_sam0_system_interrupt_extra. This includes:
122  *  - \ref asfdoc_sam0_system_interrupt_extra_acronyms
123  *  - \ref asfdoc_sam0_system_interrupt_extra_dependencies
124  *  - \ref asfdoc_sam0_system_interrupt_extra_errata
125  *  - \ref asfdoc_sam0_system_interrupt_extra_history
126  *
127  *
128  * \section asfdoc_sam0_system_interrupt_examples Examples
129  *
130  * For a list of examples related to this driver, see
131  * \ref asfdoc_sam0_system_interrupt_exqsg.
132  *
133  * \section asfdoc_sam0_system_interrupt_api_overview API Overview
134  * @{
135  */
136 
137 #include <compiler.h>
138 #include <core_cm0plus.h>
139 #include "system_interrupt_features.h"
140 
141 /**
142  * \brief Table of possible system interrupt/exception vector priorities.
143  *
144  * Table of all possible interrupt and exception vector priorities within the
145  * device.
146  */
147 enum system_interrupt_priority_level {
148 	/** Priority level 0, the highest possible interrupt priority */
149 	SYSTEM_INTERRUPT_PRIORITY_LEVEL_0  = 0,
150 	/** Priority level 1 */
151 	SYSTEM_INTERRUPT_PRIORITY_LEVEL_1  = 1,
152 	/** Priority level 2 */
153 	SYSTEM_INTERRUPT_PRIORITY_LEVEL_2  = 2,
154 	/** Priority level 3, the lowest possible interrupt priority */
155 	SYSTEM_INTERRUPT_PRIORITY_LEVEL_3  = 3,
156 };
157 
158 /**
159  * \name Critical Section Management
160  * @{
161  */
162 
163 /**
164  * \brief Enters a critical section.
165  *
166  * Disables global interrupts. To support nested critical sections, an internal
167  * count of the critical section nesting will be kept, so that global interrupts
168  * are only re-enabled upon leaving the outermost nested critical section.
169  *
170  */
system_interrupt_enter_critical_section(void)171 static inline void system_interrupt_enter_critical_section(void)
172 {
173 	cpu_irq_enter_critical();
174 }
175 
176 /**
177  * \brief Leaves a critical section.
178  *
179  * Enables global interrupts. To support nested critical sections, an internal
180  * count of the critical section nesting will be kept, so that global interrupts
181  * are only re-enabled upon leaving the outermost nested critical section.
182  *
183  */
system_interrupt_leave_critical_section(void)184 static inline void system_interrupt_leave_critical_section(void)
185 {
186 	cpu_irq_leave_critical();
187 }
188 
189 /** @} */
190 
191 /**
192  * \name Interrupt Enabling/Disabling
193  * @{
194  */
195 
196 /**
197  * \brief Check if global interrupts are enabled.
198  *
199  * Checks if global interrupts are currently enabled.
200  *
201  * \returns A boolean that identifies if the global interrupts are enabled or not.
202  *
203  * \retval true   Global interrupts are currently enabled
204  * \retval false  Global interrupts are currently disabled
205  *
206  */
system_interrupt_is_global_enabled(void)207 static inline bool system_interrupt_is_global_enabled(void)
208 {
209 	return cpu_irq_is_enabled();
210 }
211 
212 /**
213  * \brief Enables global interrupts.
214  *
215  * Enables global interrupts in the device to fire any enabled interrupt handlers.
216  */
system_interrupt_enable_global(void)217 static inline void system_interrupt_enable_global(void)
218 {
219 	cpu_irq_enable();
220 }
221 
222 /**
223  * \brief Disables global interrupts.
224  *
225  * Disabled global interrupts in the device, preventing any enabled interrupt
226  * handlers from executing.
227  */
system_interrupt_disable_global(void)228 static inline void system_interrupt_disable_global(void)
229 {
230 	cpu_irq_disable();
231 }
232 
233 /**
234  * \brief Checks if an interrupt vector is enabled or not.
235  *
236  * Checks if a specific interrupt vector is currently enabled.
237  *
238  * \param[in] vector  Interrupt vector number to check
239  *
240  * \returns A variable identifying if the requested interrupt vector is enabled.
241  *
242  * \retval true   Specified interrupt vector is currently enabled
243  * \retval false  Specified interrupt vector is currently disabled
244  *
245  */
system_interrupt_is_enabled(const enum system_interrupt_vector vector)246 static inline bool system_interrupt_is_enabled(
247 		const enum system_interrupt_vector vector)
248 {
249 	return (bool)((NVIC->ISER[0] >> (uint32_t)vector) & 0x00000001);
250 }
251 
252 /**
253  * \brief Enable interrupt vector.
254  *
255  * Enables execution of the software handler for the requested interrupt vector.
256  *
257  * \param[in] vector Interrupt vector to enable
258  */
system_interrupt_enable(const enum system_interrupt_vector vector)259 static inline void system_interrupt_enable(
260 		const enum system_interrupt_vector vector)
261 {
262 	NVIC->ISER[0] = (uint32_t)(1 << ((uint32_t)vector & 0x0000001f));
263 }
264 
265 /**
266  * \brief Disable interrupt vector.
267  *
268  * Disables execution of the software handler for the requested interrupt vector.
269  *
270  * \param[in] vector  Interrupt vector to disable
271  */
system_interrupt_disable(const enum system_interrupt_vector vector)272 static inline void system_interrupt_disable(
273 		const enum system_interrupt_vector vector)
274 {
275 	NVIC->ICER[0] = (uint32_t)(1 << ((uint32_t)vector & 0x0000001f));
276 }
277 
278 /** @} */
279 
280 /**
281  * \name Interrupt State Management
282  * @{
283  */
284 
285 /**
286  * \brief Get active interrupt (if any).
287  *
288  * Return the vector number for the current executing software handler, if any.
289  *
290  * \return Interrupt number that is currently executing.
291  */
system_interrupt_get_active(void)292 static inline enum system_interrupt_vector system_interrupt_get_active(void)
293 {
294 	uint32_t IPSR = __get_IPSR();
295 	/* The IPSR returns the Exception number, which with an offset 16 to IRQ number. */
296 	return (enum system_interrupt_vector)((IPSR & _SYSTEM_INTERRUPT_IPSR_MASK) - 16);
297 }
298 
299 bool system_interrupt_is_pending(
300 		const enum system_interrupt_vector vector);
301 
302 enum status_code system_interrupt_set_pending(
303 		const enum system_interrupt_vector vector);
304 
305 enum status_code system_interrupt_clear_pending(
306 		const enum system_interrupt_vector vector);
307 
308 /** @} */
309 
310 /**
311  * \name Interrupt Priority Management
312  * @{
313  */
314 
315 enum status_code system_interrupt_set_priority(
316 		const enum system_interrupt_vector vector,
317 		const enum system_interrupt_priority_level priority_level);
318 
319 enum system_interrupt_priority_level system_interrupt_get_priority(
320 		const enum system_interrupt_vector vector);
321 
322 /** @} */
323 
324 /** @} */
325 
326 /**
327  * \page asfdoc_sam0_system_interrupt_extra Extra Information for SYSTEM INTERRUPT Driver
328  *
329  * \section asfdoc_sam0_system_interrupt_extra_acronyms Acronyms
330  * The table below presents the acronyms used in this module:
331  *
332  * <table>
333  *	<tr>
334  *		<th>Acronym</th>
335  *		<th>Description</th>
336  *	</tr>
337  *	<tr>
338  *		<td>ISR</td>
339  *		<td>Interrupt Service Routine</td>
340  *	</tr>
341  *	<tr>
342  *		<td>NMI</td>
343  *		<td>Non-maskable Interrupt</td>
344  *	</tr>
345  *	<tr>
346  *		<td>SERCOM</td>
347  *		<td>Serial Communication Interface</td>
348  *	</tr>
349  * </table>
350  *
351  *
352  * \section asfdoc_sam0_system_interrupt_extra_dependencies Dependencies
353  * This driver has the following dependencies:
354  *
355  *  - None
356  *
357  *
358  * \section asfdoc_sam0_system_interrupt_extra_errata Errata
359  * There are no errata related to this driver.
360  *
361  *
362  * \section asfdoc_sam0_system_interrupt_extra_history Module History
363  * An overview of the module history is presented in the table below, with
364  * details on the enhancements and fixes made to the module since its first
365  * release. The current version of this corresponds to the newest version in
366  * the table.
367  *
368  * <table>
369  *	<tr>
370  *		<th>Changelog</th>
371  *	</tr>
372  *	<tr>
373  *		<td>Initial Release</td>
374  *	</tr>
375  * </table>
376  */
377 
378 /**
379  * \page asfdoc_sam0_system_interrupt_exqsg Examples for SYSTEM INTERRUPT Driver
380  *
381  * This is a list of the available Quick Start guides (QSGs) and example
382  * applications for \ref asfdoc_sam0_system_interrupt_group. QSGs are simple examples with
383  * step-by-step instructions to configure and use this driver in a selection of
384  * use cases. Note that a QSG can be compiled as a standalone application or be
385  * added to the user application.
386  *
387  *  - \subpage asfdoc_sam0_system_interrupt_critsec_use_case
388  *  - \subpage asfdoc_sam0_system_interrupt_enablemodint_use_case
389  *
390  * \page asfdoc_sam0_system_interrupt_document_revision_history Document Revision History
391  *
392  * <table>
393  *	<tr>
394  *		<th>Doc. Rev.</th>
395  *		<th>Date</th>
396  *		<th>Comments</th>
397  *	</tr>
398  *	<tr>
399  *		<td>42122E</td>
400  *		<td>12/2015</td>
401  *		<td>Added support for SAM L21/L22, SAM DA1, SAM D09, and SAM C20/C21</td>
402  *	</tr>
403  *	<tr>
404  *		<td>42122D</td>
405  *		<td>12/2014</td>
406  *		<td>Added support for SAM R21 and SAM D10/D11</td>
407  *	</tr>
408  *	<tr>
409  *		<td>42122C</td>
410  *		<td>01/2014</td>
411  *		<td>Added support for SAM D21</td>
412  *	</tr>
413  *	<tr>
414  *		<td>42122B</td>
415  *		<td>06/2013</td>
416  *		<td>Corrected documentation typos</td>
417  *	</tr>
418  *	<tr>
419  *		<td>42122A</td>
420  *		<td>06/2013</td>
421  *		<td>Initial release</td>
422  *	</tr>
423  * </table>
424  */
425 
426 #ifdef __cplusplus
427 }
428 #endif
429 
430 #endif // #ifndef SYSTEM_INTERRUPT_H_INCLUDED
431