cpu/cortexm_common: add irq sub-priorities
This commit enables Cortex-M CPU interrupt sub-priorities and allows the PendSV interrupt to have a priority different from the default one. Together these two preprocessor defines can be used to have PendSV always run as the last interrupt before returning from the interrupt stack back to the user space. Running PendSV as the last interrupt before returning to the user space is recommended by ARM, as it increases efficiency. Furthermore, that change enhances stability a lot with the new nRF52 SoftDevice support, currently being worked in PR #9473. This commit merely enables sub-priorities and a separate PendSV priority to be used without changing the default RIOT behaviour.
This commit is contained in:
parent
3b34768eaf
commit
4534e9b773
@ -33,9 +33,14 @@ extern const void *_isr_vectors;
|
||||
|
||||
CORTEXM_STATIC_INLINE void cortexm_init_isr_priorities(void)
|
||||
{
|
||||
#if CPU_CORTEXM_PRIORITY_GROUPING != 0
|
||||
/* If defined, initialise priority subgrouping, see cpu_conf_common.h */
|
||||
NVIC_SetPriorityGrouping(CPU_CORTEXM_PRIORITY_GROUPING);
|
||||
#endif
|
||||
|
||||
/* initialize the interrupt priorities */
|
||||
/* set pendSV interrupt to same priority as the rest */
|
||||
NVIC_SetPriority(PendSV_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
||||
/* set pendSV interrupt to its own priority */
|
||||
NVIC_SetPriority(PendSV_IRQn, CPU_CORTEXM_PENDSV_IRQ_PRIO);
|
||||
/* set SVC interrupt to same priority as the rest */
|
||||
NVIC_SetPriority(SVCall_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
||||
/* initialize all vendor specific interrupts with the same value */
|
||||
|
||||
@ -68,6 +68,83 @@ extern "C" {
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ARM Cortex-M interrupt sub-priorities and PendSV priority
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable Cortex-M sub-priorities, with the given number of bits
|
||||
*
|
||||
* Cortex-M CPUs allow interrupt priorities to be arranged in subgroups,
|
||||
* meaning that any interrupts on the same subgroup will not
|
||||
* pre-empt each other, but those on a lower sub-priority will run
|
||||
* only once all on the higher sub-priorities have been completed.
|
||||
*
|
||||
* The usual practice on Cortex-M is to run the PendSV interrupt
|
||||
* as the last one, just before returning to the user context,
|
||||
* running the scheduler from PendSV. However, in RIOT we don't want
|
||||
* the scheduler to be interrupted by any "normal" interrupts, which
|
||||
* may change the mutexes or something else that would affect the
|
||||
* scheduler. At the same time, we don't want to explicitly
|
||||
* disable all interrupts while in the scheduler, as that would
|
||||
* increase scheduling latency.
|
||||
*
|
||||
* A currently experimental way to make PendSV on Cortex-M to run
|
||||
* last is to
|
||||
* - make sure @ref CPU_DEFAULT_IRQ_PRIO is even (e.g. `6U`),
|
||||
* - set @ref CPU_CORTEXM_PENDSV_IRQ_PRIO to one higher, and
|
||||
* - set this one
|
||||
*
|
||||
* For example, as follows:
|
||||
* @code{.c}
|
||||
* # define CPU_CORTEXM_PRIORITY_GROUPING (1U)
|
||||
* # define CPU_CORTEXM_PENDSV_IRQ_PRIO (CPU_DEFAULT_IRQ_PRIO + 1U)
|
||||
* @endcode
|
||||
*
|
||||
* See cpu/cortexm_common/cortexm_init.c how these are used.
|
||||
*
|
||||
* If you want to set this, define it in your `cpu_conf.h`.
|
||||
*/
|
||||
#ifndef CPU_CORTEXM_PRIORITY_GROUPING
|
||||
#define CPU_CORTEXM_PRIORITY_GROUPING (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Define a separate priority for the PendSV interrupt
|
||||
*
|
||||
* According to the ARM Cortex-M documentation, the recommended best
|
||||
* practice is to place the PendSV at the lowest interrupt priority.
|
||||
* By default, RIOT runs PendSV on the same interrupt priority with all
|
||||
* other interrupts.
|
||||
*
|
||||
* For efficency (or other reasons), one may want to run the PendSV as
|
||||
* the last one, just before returning to the (next) thread. However,
|
||||
* since PendSV triggers the RIOT scheduler _without_ interrupts being
|
||||
* disabled, any interrupts that pre-empt the scheduler, including the
|
||||
* timer interrupts, must not call anything that may affect the
|
||||
* scheduler, such as mutex or scheduler functions. With the current
|
||||
* design of RIOT, writing interrupt handlers in such a manner is not
|
||||
* exactly trivial.
|
||||
*
|
||||
* An experimental way to to run PendSV as the last thing before
|
||||
* returning to the user thread context is to enable Cortex-M
|
||||
* sub-priorities with @ref CPU_CORTEXM_PRIORITY_GROUPING and then
|
||||
* make the PendSV interrupt sub-priority lower than the default.
|
||||
* (Remember, on Cortex-M lower urgency means higher priority number.)
|
||||
*
|
||||
* For now, by default, we preserve the traditional RIOT behaviour, but
|
||||
* allow specific CPUs, boards, or apps to change this.
|
||||
*
|
||||
* See cpu/cortexm_common/cortexm_init.c how these are used.
|
||||
*
|
||||
* If you want to set this, define it in your `cpu_conf.h`.
|
||||
*/
|
||||
#ifndef CPU_CORTEXM_PENDSV_IRQ_PRIO
|
||||
#define CPU_CORTEXM_PENDSV_IRQ_PRIO (CPU_DEFAULT_IRQ_PRIO)
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Attribute for memory sections required by SRAM PUF
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user