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