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#

typedef uint32_t

TYPEDEFS ****************************************.

Functions#

void

PROTOTYPES **********************************.

void

Enable interrupts.

void
CORE_ExitCritical(CORE_irqState_t irqState)

Exit a CRITICAL section.

void

Brief interrupt enable/disable sequence to allow handling of pending interrupts.

Enter a CRITICAL section.

void

Disable interrupts.

void

Enable interrupts.

void
CORE_ExitAtomic(CORE_irqState_t irqState)

Exit an ATOMIC section.

void

Brief interrupt enable/disable sequence to allow handling of pending interrupts.

Enter an ATOMIC section.

bool

Check whether the current CPU operation mode is handler mode.

bool

Check if interrupts are disabled.

uint32_t

Returns the max time spent in critical section.

uint32_t

Returns the max time spent in atomic section.

void

Clears the max time spent in atomic section.

void

Clears the max time spent in atomic section.

Macros#

#define

DEFINES *************************************.

#define
CORE_DECLARE_IRQ_STATE CORE_irqState_t irqState

MACRO API ***************************************.

#define

CRITICAL style interrupt disable.

#define

CRITICAL style interrupt enable.

#define

Convenience macro for implementing a CRITICAL section.

#define

Enter CRITICAL section.

#define

Exit CRITICAL section.

#define

CRITICAL style yield.

#define

ATOMIC style interrupt disable.

#define

ATOMIC style interrupt enable.

#define

Convenience macro for implementing an ATOMIC section.

#define

Enter ATOMIC section.

#define

Exit ATOMIC section.

#define

ATOMIC style yield.

#define

Check if IRQ is disabled.

#define

Check if inside an IRQ handler.

Typedef Documentation#

CORE_irqState_t#

typedef uint32_t CORE_irqState_t

TYPEDEFS ****************************************.

Storage for PRIMASK or BASEPRI value.


Definition at line 279 of file platform/common/inc/sl_core.h

Function Documentation#

CORE_CriticalDisableIrq#

void CORE_CriticalDisableIrq (void )

PROTOTYPES **********************************.

Parameters
N/A

Disable interrupts.

Disable all interrupts by setting PRIMASK. (Fault exception handlers will still be enabled).


Definition at line 293 of file platform/common/inc/sl_core.h

CORE_CriticalEnableIrq#

void CORE_CriticalEnableIrq (void )

Enable interrupts.

Parameters
N/A

Enable interrupts by clearing PRIMASK.


Definition at line 302 of file platform/common/inc/sl_core.h

CORE_ExitCritical#

void CORE_ExitCritical (CORE_irqState_t irqState)

Exit a CRITICAL section.

Parameters
[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().


Definition at line 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.

Parameters
N/A

Note

  • Usually used within a CRITICAL section.


Definition at line 325 of file platform/common/inc/sl_core.h

CORE_EnterCritical#

CORE_irqState_t CORE_EnterCritical (void )

Enter a CRITICAL section.

Parameters
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.


Definition at line 338 of file platform/common/inc/sl_core.h

CORE_AtomicDisableIrq#

void CORE_AtomicDisableIrq (void )

Disable interrupts.

Parameters
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


Definition at line 353 of file platform/common/inc/sl_core.h

CORE_AtomicEnableIrq#

void CORE_AtomicEnableIrq (void )

Enable interrupts.

Parameters
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().


Definition at line 371 of file platform/common/inc/sl_core.h

CORE_ExitAtomic#

void CORE_ExitAtomic (CORE_irqState_t irqState)

Exit an ATOMIC section.

Parameters
[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().


Definition at line 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.

Parameters
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().


Definition at line 402 of file platform/common/inc/sl_core.h

CORE_EnterAtomic#

CORE_irqState_t CORE_EnterAtomic (void )

Enter an ATOMIC section.

Parameters
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.


Definition at line 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.

Parameters
N/A

Returns

  • True if the CPU is in handler mode (currently executing an interrupt handler).
    False if the CPU is in thread mode.


Definition at line 430 of file platform/common/inc/sl_core.h

CORE_IrqIsDisabled#

bool CORE_IrqIsDisabled (void )

Check if interrupts are disabled.

Parameters
N/A

Returns

  • True if interrupts are disabled.


Definition at line 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.

Parameters
N/A

Returns

  • The max time spent in critical section.

Note

  • SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.


Definition at line 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.

Parameters
N/A

Returns

  • The max time spent in atomic section.

Note

  • SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.


Definition at line 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.

Parameters
N/A

Note

  • SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.


Definition at line 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.

Parameters
N/A

Note

  • SL_CORE_DEBUG_INTERRUPTS_MASKED_TIMING must be enabled.


Definition at line 482 of file platform/common/inc/sl_core.h

Macro Definition Documentation#

CORE_ATOMIC_BASE_PRIORITY_LEVEL#

#define CORE_ATOMIC_BASE_PRIORITY_LEVEL
Value:
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.


Definition at line 194 of file platform/common/inc/sl_core.h

CORE_DECLARE_IRQ_STATE#

#define CORE_DECLARE_IRQ_STATE
Value:
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.


Definition at line 210 of file platform/common/inc/sl_core.h

CORE_CRITICAL_IRQ_DISABLE#

#define CORE_CRITICAL_IRQ_DISABLE
Value:
()

CRITICAL style interrupt disable.


Definition at line 213 of file platform/common/inc/sl_core.h

CORE_CRITICAL_IRQ_ENABLE#

#define CORE_CRITICAL_IRQ_ENABLE
Value:
()

CRITICAL style interrupt enable.


Definition at line 216 of file platform/common/inc/sl_core.h

CORE_CRITICAL_SECTION#

#define CORE_CRITICAL_SECTION
Value:
{ \
CORE_DECLARE_IRQ_STATE; \
CORE_ENTER_CRITICAL(); \
{ \
yourcode \
} \
CORE_EXIT_CRITICAL(); \
}

Convenience macro for implementing a CRITICAL section.


Definition at line 219 of file platform/common/inc/sl_core.h

CORE_ENTER_CRITICAL#

#define CORE_ENTER_CRITICAL
Value:
()

Enter CRITICAL section.

Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.


Definition at line 231 of file platform/common/inc/sl_core.h

CORE_EXIT_CRITICAL#

#define CORE_EXIT_CRITICAL
Value:
()

Exit CRITICAL section.

Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.


Definition at line 235 of file platform/common/inc/sl_core.h

CORE_YIELD_CRITICAL#

#define CORE_YIELD_CRITICAL
Value:
()

CRITICAL style yield.


Definition at line 238 of file platform/common/inc/sl_core.h

CORE_ATOMIC_IRQ_DISABLE#

#define CORE_ATOMIC_IRQ_DISABLE
Value:
()

ATOMIC style interrupt disable.


Definition at line 241 of file platform/common/inc/sl_core.h

CORE_ATOMIC_IRQ_ENABLE#

#define CORE_ATOMIC_IRQ_ENABLE
Value:
()

ATOMIC style interrupt enable.


Definition at line 244 of file platform/common/inc/sl_core.h

CORE_ATOMIC_SECTION#

#define CORE_ATOMIC_SECTION
Value:
{ \
CORE_DECLARE_IRQ_STATE; \
CORE_ENTER_ATOMIC(); \
{ \
yourcode \
} \
CORE_EXIT_ATOMIC(); \
}

Convenience macro for implementing an ATOMIC section.


Definition at line 247 of file platform/common/inc/sl_core.h

CORE_ENTER_ATOMIC#

#define CORE_ENTER_ATOMIC
Value:
()

Enter ATOMIC section.

Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.


Definition at line 259 of file platform/common/inc/sl_core.h

CORE_EXIT_ATOMIC#

#define CORE_EXIT_ATOMIC
Value:
()

Exit ATOMIC section.

Assumes that a CORE_DECLARE_IRQ_STATE exist in scope.


Definition at line 263 of file platform/common/inc/sl_core.h

CORE_YIELD_ATOMIC#

#define CORE_YIELD_ATOMIC
Value:
()

ATOMIC style yield.


Definition at line 266 of file platform/common/inc/sl_core.h

CORE_IRQ_DISABLED#

#define CORE_IRQ_DISABLED
Value:
()

Check if IRQ is disabled.


Definition at line 269 of file platform/common/inc/sl_core.h

CORE_IN_IRQ_CONTEXT#

#define CORE_IN_IRQ_CONTEXT
Value:
()

Check if inside an IRQ handler.


Definition at line 272 of file platform/common/inc/sl_core.h