blob: b8b3f032d0b109d14d985abc8e180a9423c53a0d [file] [log] [blame]
/**
* \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