PRIMASK stands for “Priority Mask” and is a register in ARM Cortex-M processors that is used to disable and enable interrupts globally. Setting PRIMASK to 1 will disable interrupts, while clearing PRIMASK to 0 will enable interrupts.
Purpose of PRIMASK
The main purpose of PRIMASK is to allow critical sections of code to run atomically without being interrupted. This prevents race conditions and guarantees predictable execution. PRIMASK allows developers to disable and enable interrupts very quickly with low overhead.
Some common uses cases for PRIMASK include:
- Disabling interrupts during read-modify-write operations on shared data structures like queues or buffers.
- Preventing preemption during multi-step operations like erasing flash memory.
- Protecting access to shared hardware resources.
- Implementing mutexes or critical sections.
How PRIMASK Works
PRIMASK is a single bit register that is accessed using special register access instructions in the ARM Thumb instruction set. There are two key instructions:
- CPSID i – Set PRIMASK = 1 to disable interrupts.
- CPSIE i – Clear PRIMASK = 0 to enable interrupts.
Setting PRIMASK to 1 prevents all exceptions with configurable priority from activating, including SysTick, PendSV, and external interrupts. However, exceptions like HardFault, NMI, and Reset will still trigger even with PRIMASK = 1.
The PRIMASK bit works together with the FIXED_PRI_THREADS setting in the CORTEX_A and CORTEX_R Application Program Status Register (APSR). This setting reserves the highest priority levels for operating system use. With PRIMASK = 1, even privileged threads are prevented from preempting the current thread.
Using PRIMASK in Firmware
Here is some example firmware code using PRIMASK to implement a critical section:
// Globally accessible data
uint32_t sharedData;
void criticalFunc(void) {
// Disable interrupts
__asm volatile ("cpsid i");
// Access shared data
sharedData++;
// Enable interrupts
__asm volatile ("cpsie i");
}
The inline assembly cpsid i and cpsie i instructions set and clear PRIMASK atomically. This guarantees the code between them will run to completion uninterrupted.
PRIMASK can also be used to implement mutexes:
// Mutex implementation
uint32_t mutex = 0;
void lockMutex(void) {
// Spin until mutex unlocked
while (__LDREXW(&mutex) == 1) {};
// Set mutex
__DMB();
mutex = 1;
}
void unlockMutex(void) {
// Clear mutex
__DMB();
mutex = 0;
}
The LDREX and STREX instructions implement an atomic read-modify-write on the mutex variable. PRIMASK prevents preemption during the lock acquisition spin.
Relationship to BASEPRI
ARM Cortex-M processors also contain a BASEPRI register that allows selective priority based interrupt disabling. BASEPRI prevents exceptions below a configurable priority level, while PRIMASK disables all exceptions.
BASEPRI is generally preferred over PRIMASK:
- BASEPRI disables only lower priority interrupts, PRIMASK disables all interrupts.
- BASEPRI still allows useful interrupts like SysTick during critical sections.
- BASEPRI requires less inline assembly and is easier to read and audit.
However, PRIMASK has lower overhead than BASEPRI, so can be useful in particularly latency sensitive code blocks. PRIMASK also disables all exceptions, including NMI, Reset, and HardFault, which BASEPRI does not.
PRIMASK in Multicore Systems
In multicore Cortex-M systems, PRIMASK is local to each core. So disabling interrupts on one core does not affect other cores. This allows flexibility in managing critical sections across cores.
Typically shared data structures will use spinlocks or mutexes to synchronize access between cores. The spinlock acquire and release routines are good candidates for using PRIMASK to prevent preemption on each core.
Conclusion
In summary, PRIMASK is a simple but powerful register for disabling interrupts globally in Cortex-M processors. It enables low overhead critical sections and atomic read-modify-write operations on shared data structures. While BASEPRI is generally preferred, PRIMASK has its uses in latency sensitive contexts and for disabling all exceptions.