In this lesson, you will learn how to use the PendSV exception as a low-priority, software-triggered mechanism to safely perform operating system context switches.
Why do we need PendSV?
In a multi-tasking system, you often need to switch from one task to another. While you could trigger this switch from any interrupt, doing so inside a high-priority interrupt (like a timer or hardware signal) is dangerous. If you perform a context switch while the processor is already handling a critical hardware event, you risk nesting exceptions incorrectly or delaying the hardware response.
PendSV (Pending System Call) is a special exception designed to be the "bottom" priority in the system. Because it has the lowest possible priority, the processor will only execute the PendSV handler once all other active interrupts have completed. This makes it the perfect "safe zone" to save the registers of the current task and restore the registers of the next task.
Triggering the Context Switch
To initiate a context switch, you don't call the PendSV handler directly. Instead, you "pend" the exception by setting a specific bit in the Interrupt Control and State Register (ICSR). The hardware then waits until no other interrupts are active before firing the handler.
Here is how you trigger it in C:
// Accessing the ICSR register to pend PendSV
#define SCB_ICSR (*(volatile uint32_t*)0xE000ED04)
#define PENDSVSET (1 << 28)
void trigger_context_switch(void) {
// Set the PendSV bit to pending
SCB_ICSR |= PENDSVSET;
}
The PendSV Handler
Inside your PendSV_Handler, you perform the heavy lifting:
- Save context: Manually push the remaining registers (typically
R4-R11) onto the current task's stack. - Update Pointer: Save the current stack pointer value to the task’s control block (TCB).
- Switch Pointer: Load the stack pointer of the next task you want to run.
- Restore context: Pop the saved
R4-R11values from the new task's stack. - Exit: Perform the
BX LRinstruction to return, which triggers the hardware to restore the remaining registers (R0-R3, R12, LR, PC) and start the new task.
Key Takeaway: PendSV acts as a deferred, low-priority request that ensures context switching only happens when the system is ready, preventing interference with higher-priority hardware tasks.