| /** | |
| * \file | |
| * | |
| * \brief SAM D20 System Interrupt Driver | |
| * | |
| * Copyright (C) 2013 Atmel Corporation. All rights reserved. | |
| * | |
| * \asf_license_start | |
| * | |
| * \page License | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are met: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright notice, | |
| * this list of conditions and the following disclaimer. | |
| * | |
| * 2. Redistributions in binary form must reproduce the above copyright notice, | |
| * this list of conditions and the following disclaimer in the documentation | |
| * and/or other materials provided with the distribution. | |
| * | |
| * 3. The name of Atmel may not be used to endorse or promote products derived | |
| * from this software without specific prior written permission. | |
| * | |
| * 4. This software may only be redistributed and used in connection with an | |
| * Atmel microcontroller product. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED | |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
| * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR | |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
| * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| * POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * \asf_license_stop | |
| * | |
| */ | |
| #ifndef SYSTEM_INTERRUPT_H_INCLUDED | |
| #define SYSTEM_INTERRUPT_H_INCLUDED | |
| /** | |
| * \defgroup asfdoc_samd20_system_interrupt_group SAM D20 System Interrupt Driver (SYSTEM INTERRUPT) | |
| * | |
| * This driver for SAM D20 devices provides an interface for the configuration | |
| * and management of internal software and hardware interrupts/exceptions. | |
| * | |
| * The following peripherals are used by this module: | |
| * | |
| * - NVIC (Nested Vector Interrupt Controller) | |
| * | |
| * The outline of this documentation is as follows: | |
| * - \ref asfdoc_samd20_system_interrupt_prerequisites | |
| * - \ref asfdoc_samd20_system_interrupt_module_overview | |
| * - \ref asfdoc_samd20_system_interrupt_special_considerations | |
| * - \ref asfdoc_samd20_system_interrupt_extra_info | |
| * - \ref asfdoc_samd20_system_interrupt_examples | |
| * - \ref asfdoc_samd20_system_interrupt_api_overview | |
| * | |
| * | |
| * \section asfdoc_samd20_system_interrupt_prerequisites Prerequisites | |
| * | |
| * There are no prerequisites for this module. | |
| * | |
| * | |
| * \section asfdoc_samd20_system_interrupt_module_overview Module Overview | |
| * | |
| * The Cortex M0+ core contains an interrupt an exception vector table, which | |
| * can be used to configure the device's interrupt handlers; individual | |
| * interrupts and exceptions can be enabled and disabled, as well as configured | |
| * with a variable priority. | |
| * | |
| * This driver provides a set of wrappers around the core interrupt functions, | |
| * to expose a simple API for the management of global and individual interrupts | |
| * within the device. | |
| * | |
| * \subsection asfdoc_samd20_system_interrupt_module_overview_criticalsec Critical Sections | |
| * In some applications it is important to ensure that no interrupts may be | |
| * executed by the system whilst a critical portion of code is being run; for | |
| * example, a buffer may be copied from one context to another - during which | |
| * interrupts must be disabled to avoid corruption of the source buffer contents | |
| * until the copy has completed. This driver provides a basic API to enter and | |
| * exit nested critical sections, so that global interrupts can be kept disabled | |
| * for as long as necessary to complete a critical application code section. | |
| * | |
| * \subsection asfdoc_samd20_system_interrupt_module_overview_softints Software Interrupts | |
| * For some applications, it may be desirable to raise a module or core | |
| * interrupt via software. For this reason, a set of APIs to set an interrupt or | |
| * exception as pending are provided to the user application. | |
| * | |
| * \section asfdoc_samd20_system_interrupt_special_considerations Special Considerations | |
| * | |
| * Interrupts from peripherals in the SAM D20 devices are on a per-module basis; | |
| * an interrupt raised from any source within a module will cause a single, | |
| * module-common handler to execute. It is the user application or driver's | |
| * responsibility to de-multiplex the module-common interrupt to determine the | |
| * exact interrupt cause. | |
| * | |
| * \section asfdoc_samd20_system_interrupt_extra_info Extra Information | |
| * | |
| * For extra information see \ref asfdoc_samd20_system_interrupt_extra. This includes: | |
| * - \ref asfdoc_samd20_system_interrupt_extra_acronyms | |
| * - \ref asfdoc_samd20_system_interrupt_extra_dependencies | |
| * - \ref asfdoc_samd20_system_interrupt_extra_errata | |
| * - \ref asfdoc_samd20_system_interrupt_extra_history | |
| * | |
| * | |
| * \section asfdoc_samd20_system_interrupt_examples Examples | |
| * | |
| * For a list of examples related to this driver, see | |
| * \ref asfdoc_samd20_system_interrupt_exqsg. | |
| * | |
| * \section asfdoc_samd20_system_interrupt_api_overview API Overview | |
| * @{ | |
| */ | |
| #include <compiler.h> | |
| #include <core_cm0plus.h> | |
| #if !defined(__DOXYGEN__) | |
| /* Generates a interrupt vector table enum list entry for a given module type | |
| and index (e.g. "SYSTEM_INTERRUPT_MODULE_TC0 = TC0_IRQn,"). */ | |
| # define _MODULE_IRQn(n, module) \ | |
| SYSTEM_INTERRUPT_MODULE_##module##n = module##n##_IRQn, | |
| /* Generates interrupt vector table enum list entries for all instances of a | |
| given module type on the selected device. */ | |
| # define _SYSTEM_INTERRUPT_MODULES(name) \ | |
| MREPEAT(name##_INST_NUM, _MODULE_IRQn, name) | |
| # define _SYSTEM_INTERRUPT_IPSR_MASK 0x0000003f | |
| # define _SYSTEM_INTERRUPT_PRIORITY_MASK 0x00000007 | |
| # define _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START 0 | |
| # define _SYSTEM_INTERRUPT_SYSTICK_PRI_POS 29 | |
| #endif | |
| /** | |
| * \brief Table of possible system interrupt/exception vector numbers. | |
| * | |
| * Table of all possible interrupt and exception vector indexes within the | |
| * device. | |
| */ | |
| enum system_interrupt_vector { | |
| /** Interrupt vector index for a NMI interrupt. */ | |
| SYSTEM_INTERRUPT_NON_MASKABLE = NonMaskableInt_IRQn, | |
| /** Interrupt vector index for a Hard Fault memory access exception. */ | |
| SYSTEM_INTERRUPT_HARD_FAULT = HardFault_IRQn, | |
| /** Interrupt vector index for a Supervisor Call exception. */ | |
| SYSTEM_INTERRUPT_SV_CALL = SVCall_IRQn, | |
| /** Interrupt vector index for a Pending Supervisor interrupt. */ | |
| SYSTEM_INTERRUPT_PENDING_SV = PendSV_IRQn, | |
| /** Interrupt vector index for a System Tick interrupt. */ | |
| SYSTEM_INTERRUPT_SYSTICK = SysTick_IRQn, | |
| /** Interrupt vector index for a Power Manager peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_PM = PM_IRQn, | |
| /** Interrupt vector index for a System Control peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_SYSCTRL = SYSCTRL_IRQn, | |
| /** Interrupt vector index for a Watch Dog peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_WDT = WDT_IRQn, | |
| /** Interrupt vector index for a Real Time Clock peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_RTC = RTC_IRQn, | |
| /** Interrupt vector index for an External Interrupt peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_EIC = EIC_IRQn, | |
| /** Interrupt vector index for a Non Volatile Memory Controller interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_NVMCTRL = NVMCTRL_IRQn, | |
| /** Interrupt vector index for an Event System interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_EVSYS = EVSYS_IRQn, | |
| #if defined(__DOXYGEN__) | |
| /** Interrupt vector index for a SERCOM peripheral interrupt. | |
| * | |
| * Each specific device may contain several SERCOM peripherals; each module | |
| * instance will have its own entry in the table, with the instance number | |
| * substituted for "n" in the entry name (e.g. | |
| * \c SYSTEM_INTERRUPT_MODULE_SERCOM0). | |
| */ | |
| SYSTEM_INTERRUPT_MODULE_SERCOMn = SERCOMn_IRQn, | |
| /** Interrupt vector index for a Timer/Counter peripheral interrupt. | |
| * | |
| * Each specific device may contain several TC peripherals; each module | |
| * instance will have its own entry in the table, with the instance number | |
| * substituted for "n" in the entry name (e.g. | |
| * \c SYSTEM_INTERRUPT_MODULE_TC0). | |
| */ | |
| SYSTEM_INTERRUPT_MODULE_TCn = TCn_IRQn, | |
| #else | |
| _SYSTEM_INTERRUPT_MODULES(SERCOM) | |
| _SYSTEM_INTERRUPT_MODULES(TC) | |
| #endif | |
| /** Interrupt vector index for an Analog Comparator peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_AC = AC_IRQn, | |
| /** Interrupt vector index for an Analog-to-Digital peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_ADC = ADC_IRQn, | |
| /** Interrupt vector index for a Digital-to-Analog peripheral interrupt. */ | |
| SYSTEM_INTERRUPT_MODULE_DAC = DAC_IRQn, | |
| }; | |
| /** | |
| * \brief Table of possible system interrupt/exception vector priorities. | |
| * | |
| * Table of all possible interrupt and exception vector priorities within the | |
| * device. | |
| */ | |
| enum system_interrupt_priority_level { | |
| /** Priority level 0, the highest possible interrupt priority. */ | |
| SYSTEM_INTERRUPT_PRIORITY_LEVEL_0 = 0, | |
| /** Priority level 1. */ | |
| SYSTEM_INTERRUPT_PRIORITY_LEVEL_1 = 1, | |
| /** Priority level 2. */ | |
| SYSTEM_INTERRUPT_PRIORITY_LEVEL_2 = 2, | |
| /** Priority level 3, the lowest possible interrupt priority. */ | |
| SYSTEM_INTERRUPT_PRIORITY_LEVEL_3 = 3, | |
| }; | |
| /** | |
| * \name Critical Section Management | |
| * @{ | |
| */ | |
| /** | |
| * \brief Enters a critical section | |
| * | |
| * Disables global interrupts. To support nested critical sections, an internal | |
| * count of the critical section nesting will be kept, so that global interrupts | |
| * are only re-enabled upon leaving the outermost nested critical section. | |
| * | |
| */ | |
| static inline void system_interrupt_enter_critical_section(void) | |
| { | |
| cpu_irq_enter_critical(); | |
| } | |
| /** | |
| * \brief Leaves a critical section | |
| * | |
| * Enables global interrupts. To support nested critical sections, an internal | |
| * count of the critical section nesting will be kept, so that global interrupts | |
| * are only re-enabled upon leaving the outermost nested critical section. | |
| * | |
| */ | |
| static inline void system_interrupt_leave_critical_section(void) | |
| { | |
| cpu_irq_leave_critical(); | |
| } | |
| /** @} */ | |
| /** | |
| * \name Interrupt Enabling/Disabling | |
| * @{ | |
| */ | |
| /** | |
| * \brief Check if global interrupts are enabled | |
| * | |
| * Checks if global interrupts are currently enabled. | |
| * | |
| * \returns A boolean that identifies if the global interrupts are enabled or not. | |
| * | |
| * \retval true Global interrupts are currently enabled | |
| * \retval false Global interrupts are currently disabled | |
| * | |
| */ | |
| static inline bool system_interrupt_is_global_enabled(void) | |
| { | |
| return cpu_irq_is_enabled(); | |
| } | |
| /** | |
| * \brief Enables global interrupts | |
| * | |
| * Enables global interrupts in the device to fire any enabled interrupt handlers. | |
| */ | |
| static inline void system_interrupt_enable_global(void) | |
| { | |
| cpu_irq_enable(); | |
| } | |
| /** | |
| * \brief Disables global interrupts | |
| * | |
| * Disabled global interrupts in the device, preventing any enabled interrupt | |
| * handlers from executing. | |
| */ | |
| static inline void system_interrupt_disable_global(void) | |
| { | |
| cpu_irq_disable(); | |
| } | |
| /** | |
| * \brief Checks if an interrupt vector is enabled or not | |
| * | |
| * Checks if a specific interrupt vector is currently enabled. | |
| * | |
| * \param[in] vector Interrupt vector number to check | |
| * | |
| * \returns A variable identifying if the requested interrupt vector is enabled | |
| * | |
| * \retval true Specified interrupt vector is currently enabled | |
| * \retval false Specified interrupt vector is currently disabled | |
| * | |
| */ | |
| static inline bool system_interrupt_is_enabled( | |
| const enum system_interrupt_vector vector) | |
| { | |
| return (bool)((NVIC->ISER[0] >> (uint32_t)vector) & 0x00000001); | |
| } | |
| /** | |
| * \brief Enable interrupt vector | |
| * | |
| * Enables execution of the software handler for the requested interrupt vector. | |
| * | |
| * \param[in] vector Interrupt vector to enable | |
| */ | |
| static inline void system_interrupt_enable( | |
| const enum system_interrupt_vector vector) | |
| { | |
| NVIC->ISER[0] = (uint32_t)(1 << ((uint32_t)vector & 0x0000001f)); | |
| } | |
| /** | |
| * \brief Disable interrupt vector | |
| * | |
| * Disables execution of the software handler for the requested interrupt vector. | |
| * | |
| * \param[in] vector Interrupt vector to disable | |
| */ | |
| static inline void system_interrupt_disable( | |
| const enum system_interrupt_vector vector) | |
| { | |
| NVIC->ICER[0] = (uint32_t)(1 << ((uint32_t)vector & 0x0000001f)); | |
| } | |
| /** @} */ | |
| /** | |
| * \name Interrupt State Management | |
| * @{ | |
| */ | |
| /** | |
| * \brief Get active interrupt (if any) | |
| * | |
| * Return the vector number for the current executing software handler, if any. | |
| * | |
| * \return Interrupt number that is currently executing. | |
| */ | |
| static inline enum system_interrupt_vector system_interrupt_get_active(void) | |
| { | |
| uint32_t IPSR = __get_IPSR(); | |
| return (enum system_interrupt_vector)(IPSR & _SYSTEM_INTERRUPT_IPSR_MASK); | |
| } | |
| bool system_interrupt_is_pending( | |
| const enum system_interrupt_vector vector); | |
| enum status_code system_interrupt_set_pending( | |
| const enum system_interrupt_vector vector); | |
| enum status_code system_interrupt_clear_pending( | |
| const enum system_interrupt_vector vector); | |
| /** @} */ | |
| /** | |
| * \name Interrupt Priority Management | |
| * @{ | |
| */ | |
| enum status_code system_interrupt_set_priority( | |
| const enum system_interrupt_vector vector, | |
| const enum system_interrupt_priority_level priority_level); | |
| enum system_interrupt_priority_level system_interrupt_get_priority( | |
| const enum system_interrupt_vector vector); | |
| /** @} */ | |
| /** @} */ | |
| /** | |
| * \page asfdoc_samd20_system_interrupt_extra Extra Information for SYSTEM INTERRUPT Driver | |
| * | |
| * \section asfdoc_samd20_system_interrupt_extra_acronyms Acronyms | |
| * The table below presents the acronyms used in this module: | |
| * | |
| * <table> | |
| * <tr> | |
| * <th>Acronym</th> | |
| * <th>Description</th> | |
| * </tr> | |
| * <tr> | |
| * <td>ISR</td> | |
| * <td>Interrupt Service Routine</td> | |
| * </tr> | |
| * </table> | |
| * | |
| * | |
| * \section asfdoc_samd20_system_interrupt_extra_dependencies Dependencies | |
| * This driver has the following dependencies: | |
| * | |
| * - None | |
| * | |
| * | |
| * \section asfdoc_samd20_system_interrupt_extra_errata Errata | |
| * There are no errata related to this driver. | |
| * | |
| * | |
| * \section asfdoc_samd20_system_interrupt_extra_history Module History | |
| * An overview of the module history is presented in the table below, with | |
| * details on the enhancements and fixes made to the module since its first | |
| * release. The current version of this corresponds to the newest version in | |
| * the table. | |
| * | |
| * <table> | |
| * <tr> | |
| * <th>Changelog</th> | |
| * </tr> | |
| * <tr> | |
| * <td>Initial Release</td> | |
| * </tr> | |
| * </table> | |
| */ | |
| /** | |
| * \page asfdoc_samd20_system_interrupt_exqsg Examples for SYSTEM INTERRUPT Driver | |
| * | |
| * This is a list of the available Quick Start guides (QSGs) and example | |
| * applications for \ref asfdoc_samd20_system_interrupt_group. QSGs are simple examples with | |
| * step-by-step instructions to configure and use this driver in a selection of | |
| * use cases. Note that QSGs can be compiled as a standalone application or be | |
| * added to the user application. | |
| * | |
| * - \subpage asfdoc_samd20_system_interrupt_critsec_use_case | |
| * - \subpage asfdoc_samd20_system_interrupt_enablemodint_use_case | |
| * | |
| * \page asfdoc_samd20_system_interrupt_document_revision_history Document Revision History | |
| * | |
| * <table> | |
| * <tr> | |
| * <th>Doc. Rev.</td> | |
| * <th>Date</td> | |
| * <th>Comments</td> | |
| * </tr> | |
| * <tr> | |
| * <td>B</td> | |
| * <td>06/2013</td> | |
| * <td>Corrected documentation typos.</td> | |
| * </tr> | |
| * <tr> | |
| * <td>A</td> | |
| * <td>06/2013</td> | |
| * <td>Initial release</td> | |
| * </tr> | |
| * </table> | |
| */ | |
| #endif |