| /***************************************************************************//** |
| * @file em_core.h |
| * @brief Core interrupt handling API |
| * @version 5.6.0 |
| ******************************************************************************* |
| * # License |
| * <b>Copyright 2016 Silicon Laboratories, Inc. www.silabs.com</b> |
| ******************************************************************************* |
| * |
| * Permission is granted to anyone to use this software for any purpose, |
| * including commercial applications, and to alter it and redistribute it |
| * freely, subject to the following restrictions: |
| * |
| * 1. The origin of this software must not be misrepresented; you must not |
| * claim that you wrote the original software.@n |
| * 2. Altered source versions must be plainly marked as such, and must not be |
| * misrepresented as being the original software.@n |
| * 3. This notice may not be removed or altered from any source distribution. |
| * |
| * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no |
| * obligation to support this Software. Silicon Labs is providing the |
| * Software "AS IS", with no express or implied warranties of any kind, |
| * including, but not limited to, any implied warranties of merchantability |
| * or fitness for any particular purpose or warranties against infringement |
| * of any proprietary rights of a third party. |
| * |
| * Silicon Labs will not be liable for any consequential, incidental, or |
| * special damages, or any other relief, or for any claim by any third party, |
| * arising from your use of this Software. |
| * |
| ******************************************************************************/ |
| #ifndef EM_CORE_H |
| #define EM_CORE_H |
| |
| #include "em_device.h" |
| #include "em_common.h" |
| |
| #include <stdbool.h> |
| |
| /***************************************************************************//** |
| * @addtogroup emlib |
| * @{ |
| ******************************************************************************/ |
| |
| /***************************************************************************//** |
| * @addtogroup CORE |
| * @{ |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| ******************************* DEFINES *********************************** |
| ******************************************************************************/ |
| |
| /** Use PRIMASK register to disable interrupts in ATOMIC sections. */ |
| #define CORE_ATOMIC_METHOD_PRIMASK 0 |
| |
| /** Use BASEPRI register to disable interrupts in ATOMIC sections. */ |
| #define CORE_ATOMIC_METHOD_BASEPRI 1 |
| |
| /** Number of words in a NVIC mask set. */ |
| #define CORE_NVIC_REG_WORDS ((EXT_IRQ_COUNT + 31) / 32) |
| |
| /** Number of entries in a default interrupt vector table. */ |
| #define CORE_DEFAULT_VECTOR_TABLE_ENTRIES (EXT_IRQ_COUNT + 16) |
| |
| // Compile time sanity check. |
| #if (CORE_NVIC_REG_WORDS > 3) |
| #error "em_core: Unexpected NVIC external interrupt count." |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /******************************************************************************* |
| ************************ MACRO API *************************************** |
| ******************************************************************************/ |
| |
| // |
| // CRITICAL section macro API. |
| // |
| |
| /** Allocate storage for PRIMASK or BASEPRI value for use by |
| * CORE_ENTER/EXIT_ATOMIC() and CORE_ENTER/EXIT_CRITICAL() macros. */ |
| #define CORE_DECLARE_IRQ_STATE CORE_irqState_t irqState |
| |
| /** CRITICAL style interrupt disable. */ |
| #define CORE_CRITICAL_IRQ_DISABLE() CORE_CriticalDisableIrq() |
| |
| /** CRITICAL style interrupt enable. */ |
| #define CORE_CRITICAL_IRQ_ENABLE() CORE_CriticalEnableIrq() |
| |
| /** Convenience macro for implementing a CRITICAL section. */ |
| #define CORE_CRITICAL_SECTION(yourcode) \ |
| { \ |
| CORE_DECLARE_IRQ_STATE; \ |
| CORE_ENTER_CRITICAL(); \ |
| { \ |
| yourcode \ |
| } \ |
| CORE_EXIT_CRITICAL(); \ |
| } |
| |
| /** Enter CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in |
| * scope. */ |
| #define CORE_ENTER_CRITICAL() irqState = CORE_EnterCritical() |
| |
| /** Exit CRITICAL section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in |
| * scope. */ |
| #define CORE_EXIT_CRITICAL() CORE_ExitCritical(irqState) |
| |
| /** CRITICAL style yield. */ |
| #define CORE_YIELD_CRITICAL() CORE_YieldCritical() |
| |
| // |
| // ATOMIC section macro API. |
| // |
| |
| /** ATOMIC style interrupt disable. */ |
| #define CORE_ATOMIC_IRQ_DISABLE() CORE_AtomicDisableIrq() |
| |
| /** ATOMIC style interrupt enable. */ |
| #define CORE_ATOMIC_IRQ_ENABLE() CORE_AtomicEnableIrq() |
| |
| /** Convenience macro for implementing an ATOMIC section. */ |
| #define CORE_ATOMIC_SECTION(yourcode) \ |
| { \ |
| CORE_DECLARE_IRQ_STATE; \ |
| CORE_ENTER_ATOMIC(); \ |
| { \ |
| yourcode \ |
| } \ |
| CORE_EXIT_ATOMIC(); \ |
| } |
| |
| /** Enter ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in |
| * scope. */ |
| #define CORE_ENTER_ATOMIC() irqState = CORE_EnterAtomic() |
| |
| /** Exit ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in |
| * scope. */ |
| #define CORE_EXIT_ATOMIC() CORE_ExitAtomic(irqState) |
| |
| /** ATOMIC style yield. */ |
| #define CORE_YIELD_ATOMIC() CORE_YieldAtomic() |
| |
| // |
| // NVIC mask section macro API. |
| // |
| |
| /** Allocate storage for NVIC interrupt masks for use by |
| * CORE_ENTER/EXIT_NVIC() macros. */ |
| #define CORE_DECLARE_NVIC_STATE CORE_nvicMask_t nvicState |
| |
| /** Allocate storage for NVIC interrupt masks. |
| * @param[in] x |
| * The storage variable name to use.*/ |
| #define CORE_DECLARE_NVIC_MASK(x) CORE_nvicMask_t x |
| |
| /** Allocate storage for and zero initialize NVIC interrupt mask. |
| * @param[in] x |
| * The storage variable name to use.*/ |
| #define CORE_DECLARE_NVIC_ZEROMASK(x) CORE_nvicMask_t x = { { 0 } } |
| |
| /** NVIC mask style interrupt disable. |
| * @param[in] mask |
| * Mask specifying which NVIC interrupts to disable. */ |
| #define CORE_NVIC_DISABLE(mask) CORE_NvicDisableMask(mask) |
| |
| /** NVIC mask style interrupt enable. |
| * @param[in] mask |
| * Mask specifying which NVIC interrupts to enable. */ |
| #define CORE_NVIC_ENABLE(mask) CORE_NvicEnableMask(mask) |
| |
| /** Convenience macro for implementing a NVIC mask section. |
| * @param[in] mask |
| * Mask specifying which NVIC interrupts to disable within the section. |
| * @param[in] yourcode |
| * The code for the section. */ |
| #define CORE_NVIC_SECTION(mask, yourcode) \ |
| { \ |
| CORE_DECLARE_NVIC_STATE; \ |
| CORE_ENTER_NVIC(mask); \ |
| { \ |
| yourcode \ |
| } \ |
| CORE_EXIT_NVIC(); \ |
| } |
| |
| /** Enter NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist |
| * in scope. |
| * @param[in] disable |
| * Mask specifying which NVIC interrupts to disable within the section. */ |
| #define CORE_ENTER_NVIC(disable) CORE_EnterNvicMask(&nvicState, disable) |
| |
| /** Exit NVIC mask section. Assumes that a @ref CORE_DECLARE_NVIC_STATE exist |
| * in scope. */ |
| #define CORE_EXIT_NVIC() CORE_NvicEnableMask(&nvicState) |
| |
| /** NVIC maks style yield. |
| * @param[in] enable |
| * Mask specifying which NVIC interrupts to briefly enable. */ |
| #define CORE_YIELD_NVIC(enable) CORE_YieldNvicMask(enable) |
| |
| // |
| // Miscellaneous macros. |
| // |
| |
| /** Check if IRQ is disabled. */ |
| #define CORE_IRQ_DISABLED() CORE_IrqIsDisabled() |
| |
| /** Check if inside an IRQ handler. */ |
| #define CORE_IN_IRQ_CONTEXT() CORE_InIrqContext() |
| |
| /******************************************************************************* |
| ************************* TYPEDEFS **************************************** |
| ******************************************************************************/ |
| |
| /** Storage for PRIMASK or BASEPRI value. */ |
| typedef uint32_t CORE_irqState_t; |
| |
| /** Storage for NVIC interrupt masks. */ |
| typedef struct { |
| uint32_t a[CORE_NVIC_REG_WORDS]; /*!< Array of NVIC mask words. */ |
| } CORE_nvicMask_t; |
| |
| /******************************************************************************* |
| ***************************** PROTOTYPES ********************************** |
| ******************************************************************************/ |
| |
| void CORE_CriticalDisableIrq(void); |
| void CORE_CriticalEnableIrq(void); |
| void CORE_ExitCritical(CORE_irqState_t irqState); |
| void CORE_YieldCritical(void); |
| CORE_irqState_t CORE_EnterCritical(void); |
| |
| void CORE_AtomicDisableIrq(void); |
| void CORE_AtomicEnableIrq(void); |
| void CORE_ExitAtomic(CORE_irqState_t irqState); |
| void CORE_YieldAtomic(void); |
| CORE_irqState_t CORE_EnterAtomic(void); |
| |
| bool CORE_InIrqContext(void); |
| bool CORE_IrqIsBlocked(IRQn_Type irqN); |
| bool CORE_IrqIsDisabled(void); |
| |
| void CORE_GetNvicEnabledMask(CORE_nvicMask_t *mask); |
| bool CORE_GetNvicMaskDisableState(const CORE_nvicMask_t *mask); |
| |
| void CORE_EnterNvicMask(CORE_nvicMask_t *nvicState, |
| const CORE_nvicMask_t *disable); |
| void CORE_NvicDisableMask(const CORE_nvicMask_t *disable); |
| void CORE_NvicEnableMask(const CORE_nvicMask_t *enable); |
| void CORE_YieldNvicMask(const CORE_nvicMask_t *enable); |
| void CORE_NvicMaskSetIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask); |
| void CORE_NvicMaskClearIRQ(IRQn_Type irqN, CORE_nvicMask_t *mask); |
| bool CORE_NvicIRQDisabled(IRQn_Type irqN); |
| |
| void *CORE_GetNvicRamTableHandler(IRQn_Type irqN); |
| void CORE_SetNvicRamTableHandler(IRQn_Type irqN, void *handler); |
| void CORE_InitNvicVectorTable(uint32_t *sourceTable, |
| uint32_t sourceSize, |
| uint32_t *targetTable, |
| uint32_t targetSize, |
| void *defaultHandler, |
| bool overwriteActive); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| /** @} (end addtogroup CORE) */ |
| /** @} (end addtogroup emlib) */ |
| |
| #endif /* EM_CORE_H */ |