Core#
Introduction#
The core abstraction API provides high-level, device agnostic, control of core peripherals, most notably the ability to execute code in sections with varying levels of interrupt masking.
This module provides support for two types of critical sections, each with different interrupt masking capabilities.
CRITICAL section: Inside a critical section, all interrupts are masked (except for core exception handlers).
ATOMIC section: Inside an atomic section, interrupts with a priority less than the configurable SL_CORE_BASE_PRIORITY_LEVEL value will be masked.
Compile-time Configuration#
The following #define is used to configure sl_core:
// Enables debug methods to measure the time spent in critical sections.
#define SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING 0
Macro API#
The core abstraction API has macros to facilitate executing code in ATOMIC and CRITICAL sections.
CORE_DECLARE_IRQ_STATE, CORE_ENTER_ATOMIC() and CORE_EXIT_ATOMIC() can be used together to implement an ATOMIC section.
{
CORE_DECLARE_IRQ_STATE; // Storage for saving IRQ state prior to
// atomic section entry.
CORE_ENTER_ATOMIC(); // Enter atomic section.
...
... your code goes here ...
...
CORE_EXIT_ATOMIC(); // Exit atomic section, IRQ state is restored.
}
CORE_ATOMIC_SECTION(yourcode) is aconcatenation of all three of the macros above.
{
CORE_ATOMIC_SECTION(
...
... your code goes here ...
...
)
}
The following macros implement CRITICAL sections in a similar fashion as described above for ATOMIC sections: CORE_DECLARE_IRQ_STATECORE_ENTER_CRITICAL()CORE_EXIT_CRITICAL()CORE_CRITICAL_SECTION(yourcode)
API Reimplementation#
Most of the functions in the API are implemented as weak functions. This means that it is easy to reimplement when special needs arise. Shown below is a reimplementation of CRITICAL sections suitable if FreeRTOS OS is used:
CORE_irqState_t CORE_EnterCritical(void)
{
vPortEnterCritical();
return 0;
}
void CORE_ExitCritical(CORE_irqState_t irqState)
{
(void)irqState;
vPortExitCritical();
}
Also note that CORE_Enter/ExitCritical() are not implemented as inline functions. As a result, reimplementations will be possible even when original implementations are inside a linked library.
Some RTOSes must be notified on interrupt handler entry and exit. Macros CORE_INTERRUPT_ENTRY() and CORE_INTERRUPT_EXIT() are suitable placeholders for inserting such code. Insert these macros in all your interrupt handlers and then override the default macro implementations. This is an example if uC/OS is used:
// In emlib_config.h:
#define CORE_INTERRUPT_ENTRY() OSIntEnter()
#define CORE_INTERRUPT_EXIT() OSIntExit()
Maximum Interrupt Disabled Time#
The maximum time spent (in cycles) in critical and atomic sections can be measured for performance and interrupt latency analysis. To enable the timings, use the SL_CORE_ENABLE_INTERRUPT_DISABLED_TIMING configuration option. When enabled, the functions CORE_get_max_time_critical_section() and CORE_get_max_time_atomic_section() can be used to get the max timings since startup.
Porting from em_int#
Existing code using INT_Enable() and INT_Disable() must be ported to the sl_core API. While em_int used, a global counter to store the interrupt state, sl_core uses a local variable. Any usage of INT_Disable(), therefore, needs to be replaced with a declaration of the interrupt state variable before entering the critical section.
Since the state variable is in local scope, the critical section exit needs to occur within the scope of the variable. If multiple nested critical sections are used, each needs to have its own state variable in its own scope.
In many cases, completely disabling all interrupts using CRITICAL sections might be more heavy-handed than needed. When porting, consider whether an ATOMIC section can be used to only disable a subset of the interrupts.
Replacing em_int calls with sl_core function calls:
void func(void)
{
// INT_Disable();
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_ATOMIC();
.
.
.
// INT_Enable();
CORE_EXIT_ATOMIC();
}
Typedefs#
TYPEDEFS ****************************************.
Functions#
PROTOTYPES **********************************.
Enable interrupts.
Exit a CRITICAL section.
Brief interrupt enable/disable sequence to allow handling of pending interrupts.
Enter a CRITICAL section.
Disable interrupts.
Enable interrupts.
Exit an ATOMIC section.
Brief interrupt enable/disable sequence to allow handling of pending interrupts.
Enter an ATOMIC section.
Check whether the current CPU operation mode is handler mode.
Check if interrupts are disabled.
Returns the max time spent in critical section.
Returns the max time spent in atomic section.
Clears the max time spent in atomic section.
Clears the max time spent in atomic section.
Macros#
DEFINES *************************************.
MACRO API ***************************************.
CRITICAL style interrupt disable.
CRITICAL style interrupt enable.
Convenience macro for implementing a CRITICAL section.
Enter CRITICAL section.
Exit CRITICAL section.
CRITICAL style yield.
ATOMIC style interrupt disable.
ATOMIC style interrupt enable.
Convenience macro for implementing an ATOMIC section.
Enter ATOMIC section.
Exit ATOMIC section.
ATOMIC style yield.
Check if IRQ is disabled.
Check if inside an IRQ handler.
Typedef Documentation#
CORE_irqState_t#
typedef uint32_t CORE_irqState_t
TYPEDEFS ****************************************.
Storage for PRIMASK or BASEPRI value.
279
of file platform/common/inc/sl_core.h
Function Documentation#
CORE_CriticalDisableIrq#
void CORE_CriticalDisableIrq (void )
PROTOTYPES **********************************.
N/A |
Disable interrupts.
Disable all interrupts by setting PRIMASK. (Fault exception handlers will still be enabled).
293
of file platform/common/inc/sl_core.h
CORE_CriticalEnableIrq#
void CORE_CriticalEnableIrq (void )
Enable interrupts.
N/A |
Enable interrupts by clearing PRIMASK.
302
of file platform/common/inc/sl_core.h
CORE_ExitCritical#
void CORE_ExitCritical (CORE_irqState_t irqState)
Exit a CRITICAL section.
[in] | irqState | The interrupt priority blocking level to restore to PRIMASK when exiting the CRITICAL section. This value is usually the one returned by a prior call to CORE_EnterCritical(). |
314
of file platform/common/inc/sl_core.h
CORE_YieldCritical#
void CORE_YieldCritical (void )
Brief interrupt enable/disable sequence to allow handling of pending interrupts.
N/A |
Note
Usually used within a CRITICAL section.
325
of file platform/common/inc/sl_core.h
CORE_EnterCritical#
CORE_irqState_t CORE_EnterCritical (void )
Enter a CRITICAL section.
N/A |
When a CRITICAL section is entered, all interrupts (except fault handlers) are disabled.
Returns
The value of PRIMASK register prior to the CRITICAL section entry.
338
of file platform/common/inc/sl_core.h
CORE_AtomicDisableIrq#
void CORE_AtomicDisableIrq (void )
Disable interrupts.
N/A |
Disable interrupts with a priority lower or equal to CORE_ATOMIC_BASE_PRIORITY_LEVEL. Sets core BASEPRI register to CORE_ATOMIC_BASE_PRIORITY_LEVEL.
Note
If CORE_ATOMIC_METHOD is CORE_ATOMIC_METHOD_PRIMASK, this function is identical to CORE_CriticalDisableIrq().
353
of file platform/common/inc/sl_core.h
CORE_AtomicEnableIrq#
void CORE_AtomicEnableIrq (void )
Enable interrupts.
N/A |
Enable interrupts by setting core BASEPRI register to 0.
Note
If CORE_ATOMIC_METHOD is CORE_ATOMIC_METHOD_BASEPRI and PRIMASK is set (CPU is inside a CRITICAL section), interrupts will still be disabled after calling this function.
If CORE_ATOMIC_METHOD is CORE_ATOMIC_METHOD_PRIMASK, this function is identical to CORE_CriticalEnableIrq().
371
of file platform/common/inc/sl_core.h
CORE_ExitAtomic#
void CORE_ExitAtomic (CORE_irqState_t irqState)
Exit an ATOMIC section.
[in] | irqState | The interrupt priority blocking level to restore to BASEPRI when exiting the ATOMIC section. This value is usually the one returned by a prior call to CORE_EnterAtomic(). |
Note
If CORE_ATOMIC_METHOD is set to CORE_ATOMIC_METHOD_PRIMASK, this function is identical to CORE_ExitCritical().
387
of file platform/common/inc/sl_core.h
CORE_YieldAtomic#
void CORE_YieldAtomic (void )
Brief interrupt enable/disable sequence to allow handling of pending interrupts.
N/A |
Note
Usually used within an ATOMIC section.
If CORE_ATOMIC_METHOD is CORE_ATOMIC_METHOD_PRIMASK, this function is identical to CORE_YieldCritical().
402
of file platform/common/inc/sl_core.h
CORE_EnterAtomic#
CORE_irqState_t CORE_EnterAtomic (void )
Enter an ATOMIC section.
N/A |
When an ATOMIC section is entered, interrupts with priority lower or equal to CORE_ATOMIC_BASE_PRIORITY_LEVEL are disabled.
Note
If CORE_ATOMIC_METHOD is CORE_ATOMIC_METHOD_PRIMASK, this function is identical to CORE_EnterCritical().
Returns
The value of BASEPRI register prior to ATOMIC section entry.
419
of file platform/common/inc/sl_core.h
CORE_InIrqContext#
bool CORE_InIrqContext (void )
Check whether the current CPU operation mode is handler mode.
N/A |
Returns
True if the CPU is in handler mode (currently executing an interrupt handler).
False if the CPU is in thread mode.
430
of file platform/common/inc/sl_core.h
CORE_IrqIsDisabled#
bool CORE_IrqIsDisabled (void )
Check if interrupts are disabled.
N/A |
Returns
True if interrupts are disabled.
440
of file platform/common/inc/sl_core.h
CORE_get_max_time_critical_section#
uint32_t CORE_get_max_time_critical_section (void )
Returns the max time spent in critical section.
N/A |
Returns
The max time spent in critical section.
Note
SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
452
of file platform/common/inc/sl_core.h
CORE_get_max_time_atomic_section#
uint32_t CORE_get_max_time_atomic_section (void )
Returns the max time spent in atomic section.
N/A |
Returns
The max time spent in atomic section.
Note
SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
464
of file platform/common/inc/sl_core.h
CORE_clear_max_time_critical_section#
void CORE_clear_max_time_critical_section (void )
Clears the max time spent in atomic section.
N/A |
Note
SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
473
of file platform/common/inc/sl_core.h
CORE_clear_max_time_atomic_section#
void CORE_clear_max_time_atomic_section (void )
Clears the max time spent in atomic section.
N/A |
Note
SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.
482
of file platform/common/inc/sl_core.h
Macro Definition Documentation#
CORE_ATOMIC_BASE_PRIORITY_LEVEL#
#define CORE_ATOMIC_BASE_PRIORITY_LEVELValue:
3
DEFINES *************************************.
The interrupt priority level disabled within ATOMIC regions. Interrupts with priority level equal to or lower than this definition will be disabled within ATOMIC regions.
194
of file platform/common/inc/sl_core.h
CORE_DECLARE_IRQ_STATE#
#define CORE_DECLARE_IRQ_STATEValue:
CORE_irqState_t irqState
MACRO API ***************************************.
Allocate storage for PRIMASK or BASEPRI value for use by CORE_ENTER/EXIT_ATOMIC() and CORE_ENTER/EXIT_CRITICAL() macros.
210
of file platform/common/inc/sl_core.h
CORE_CRITICAL_IRQ_DISABLE#
#define CORE_CRITICAL_IRQ_DISABLEValue:
()
CRITICAL style interrupt disable.
213
of file platform/common/inc/sl_core.h
CORE_CRITICAL_IRQ_ENABLE#
#define CORE_CRITICAL_IRQ_ENABLEValue:
()
CRITICAL style interrupt enable.
216
of file platform/common/inc/sl_core.h
CORE_CRITICAL_SECTION#
#define CORE_CRITICAL_SECTIONValue:
Convenience macro for implementing a CRITICAL section.
219
of file platform/common/inc/sl_core.h
CORE_ENTER_CRITICAL#
#define CORE_ENTER_CRITICALValue:
()
Enter CRITICAL section.
Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.
231
of file platform/common/inc/sl_core.h
CORE_EXIT_CRITICAL#
#define CORE_EXIT_CRITICALValue:
()
Exit CRITICAL section.
Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.
235
of file platform/common/inc/sl_core.h
CORE_YIELD_CRITICAL#
#define CORE_YIELD_CRITICALValue:
()
CRITICAL style yield.
238
of file platform/common/inc/sl_core.h
CORE_ATOMIC_IRQ_DISABLE#
#define CORE_ATOMIC_IRQ_DISABLEValue:
()
ATOMIC style interrupt disable.
241
of file platform/common/inc/sl_core.h
CORE_ATOMIC_IRQ_ENABLE#
#define CORE_ATOMIC_IRQ_ENABLEValue:
()
ATOMIC style interrupt enable.
244
of file platform/common/inc/sl_core.h
CORE_ATOMIC_SECTION#
#define CORE_ATOMIC_SECTIONValue:
Convenience macro for implementing an ATOMIC section.
247
of file platform/common/inc/sl_core.h
CORE_ENTER_ATOMIC#
#define CORE_ENTER_ATOMICValue:
()
Enter ATOMIC section.
Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.
259
of file platform/common/inc/sl_core.h
CORE_EXIT_ATOMIC#
#define CORE_EXIT_ATOMICValue:
()
Exit ATOMIC section.
Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.
263
of file platform/common/inc/sl_core.h
CORE_YIELD_ATOMIC#
#define CORE_YIELD_ATOMICValue:
()
ATOMIC style yield.
266
of file platform/common/inc/sl_core.h
CORE_IRQ_DISABLED#
#define CORE_IRQ_DISABLEDValue:
()
Check if IRQ is disabled.
269
of file platform/common/inc/sl_core.h
CORE_IN_IRQ_CONTEXT#
#define CORE_IN_IRQ_CONTEXTValue:
()
Check if inside an IRQ handler.
272
of file platform/common/inc/sl_core.h