COREEMLIB

Detailed Description

Introduction

CORE interrupt API provides a simple and safe means to disable and enable interrupts to protect sections of code.

This is often referred to as "critical sections". This module provides support for three types of critical sections, each with different interrupt blocking capabilities.

CRITICAL section: Inside a critical section, all interrupts are disabled (except for fault handlers). The PRIMASK register is always used for interrupt disable/enable.

ATOMIC section: This type of section is configurable and the default method is to use PRIMASK. With BASEPRI configuration, interrupts with priority equal to or lower than a given configurable level are disabled. The interrupt disable priority level is defined at compile time. The BASEPRI register is not available for all architectures.

If the default values do not support your needs, they can be overridden by supplying -D compiler flags on the compiler command line or by collecting all macro redefinitions in a file named emlib_config.h and then supplying -DEMLIB_USER_CONFIG on a compiler command line.

Due to architectural limitations Cortex-M0+ devices do not support ATOMIC type critical sections using the BASEPRI register. On M0+ devices ATOMIC section helper macros are available but they are implemented as CRITICAL sections using PRIMASK register.

Macro API

The primary em_core API is the macro API. Macro API will map to correct CORE functions according to the selected CORE_ATOMIC_METHOD and similar configurations (the full CORE API is of course also available). The most useful macros are as follows:

Refer to Macros or Macro Definition Documentation below for a full list of macros.

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:

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:

Porting from em_int

Existing code using INT_Enable() and INT_Disable() must be ported to the em_core API. While em_int used, a global counter to store the interrupt state, em_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 other types of sections, such as ATOMIC or NVIC mask, can be used to only disable a subset of the interrupts.

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

Definition at line 646 of file em_core.c.

void CORE_InitNvicVectorTable

(

uint32_t *

sourceTable,

uint32_t

sourceSize,

uint32_t *

targetTable,

uint32_t

targetSize,

void *

defaultHandler,

bool

overwriteActive

)

Initialize an interrupt vector table by copying table entries from a source to a target table.

Note

This function will set a new VTOR register value.

Parameters

[in]

sourceTable

The address of the source vector table.

[in]

sourceSize

A number of entries in the source vector table.

[in]

targetTable

The address of the target (new) vector table.

[in]

targetSize

A number of entries in the target vector table.

[in]

defaultHandler

An address of the interrupt handler used for target entries for which where there is no corresponding source entry (i.e., the target table is larger than the source table).

[in]

overwriteActive

When true, a target table entry is always overwritten with the corresponding source entry. If false, a target table entry is only overwritten if it is zero. This makes it possible for an application to partly initialize a target table before passing it to this function.