Basepri is a register found in ARM Cortex processor cores that controls the priority level of exception handlers. It plays a key role in determining the priority of different exceptions and interrupts in the ARM architecture.
In a nutshell, Basepri allows software to dynamically raise the priority of exception handlers to prevent lower priority exceptions from interrupting higher priority code. By managing Basepri, developers can create critical sections in their code that won’t get interrupted by events like interrupts.
Purpose of Basepri
The main purposes of Basepri are:
- To set a priority threshold below which no exception will be taken, creating a “locked” critical section.
- To disable interrupts and exceptions of a given priority.
- To boost the priority of exception handlers so they can interrupt lower priority code.
By managing the priority threshold in Basepri, developers can protect critical code sections from being interrupted unexpectedly. This helps create robust and predictable software behavior.
How Basepri Works
Basepri works together with the IPSR (Interrupt Program Status Register) and PRIMASK registers to establish priorities for exceptions. Here’s a quick overview:
- IPSR holds the exception number of the currently executing code.
- PRIMASK disables all exceptions when set to 1.
- Basepri sets a priority threshold below which exceptions will not preempt execution.
The effective priority mask is the maximum of Basepri and PRIMASK. Any pending exceptions with a priority lower than this mask will not be taken.
To enable exceptions, Basepri must be lowered and PRIMASK cleared. The next highest priority pending exception will then preempt the current execution.
Setting Basepri to 0 allows all exceptions to potentially interrupt. Setting it to 0xFF completely locks out all preemption of current execution.
Using Basepri for Critical Sections
A common use of Basepri is creating a critical section to protect shared resources or data structures. For example: /* Set Basepri to lock out all interrupts */ basepri = 0xFF /* Critical section */ { Access shared resource Modify shared data } /* Reset Basepri to 0 */ basepri = 0
By setting Basepri to its max value during the critical section, we can prevent all exceptions and interrupts from disrupting the code. This prevents race conditions and inconsistent state changes.
Relationship with Interrupts
Basepri affects the preemption of exceptions based on their priority level. This includes:
- Exceptions (resets, faults, aborts)
- SVC (supervisor call) exceptions
- Debug exceptions (breakpoints, watchpoints)
- Interrupts (external and internal)
So while Basepri controls the priority threshold for exceptions in general, it effectively enables or disables interrupts as well based on their assigned priority levels.
Setting Basepri in Code
There are a few ways to set Basepri in Cortex-M code:
- Direct writes to the BASEPRI register
- Using the __set_BASEPRI and __get_BASEPRI intrinsics
- The __disable_irq()/__enable_irq() intrinsics which modify BASEPRI
For example: /* Disable interrupts below priority 2 */ BASEPRI = 2 << (8 – __NVIC_PRIO_BITS); /* Disable all interrupts */ __disable_irq(); /* Read current value */ curr_basepri = __get_BASEPRI();
The BASEPRI register is generally written using bitband aliases for atomic access without disabling interrupts globally.
Interaction with PRIMASK
Both Basepri and PRIMASK affect interrupt blocking based on priority. A few key points on their interaction:
- PRIMASK disables all exceptions when set to 1
- Basepri only disables lower priority exceptions
- The effective mask is the max of PRIMASK and Basepri
- Setting PRIMASK locks out NMIs which ignore Basepri
Generally, Basepri is used for selective interrupt blocking during critical sections. PRIMASK provides an overall master disable for all exceptions when needed.
Role in ARMv8-M
In ARMv8-M, the BASEPRI register is enhanced to BASEPRI_MAX which allows setting an exception priority ceiling:
- BASEPRI sets the minimum priority threshold
- BASEPRI_MAX sets the maximum/ceiling priority value
This allows even more flexible control over the preemption behavior of exception handling code.
Summary
In summary, Basepri allows assigning priority levels to exceptions and interrupts in Cortex-M processors. By managing Basepri, time-critical code can be shielded from lower priority events that could disrupt program flow or corrupt state.
Used properly, Basepri is a valuable tool for creating robust and deterministic real-time embedded systems using ARM processors.