Hello,
Recently, I came back to digging into RTOS working principles at the lowest level on Cortex-M family processors. I understand the concept of SysTick (or other time base), SVC and PendSV as RTOS system exceptions. Though, one question is still itching. Many books, docs and other sources say, that PendSV is used for context switching (which is true for many popular RTOSes) because context switch is slow and take relatively long time as for ISR. But does it really take so long to put couple of registers (context) on process stack and change PSP? (Also, one off-topic question: what are other reasons why PendSV is used except slow operations like context switching)
Let me explain.
Since Cortex-M uses EXEC_RETURN, returning after context switch can be left do be done by CPU, NVIC itself. Let's say SysTick IRQ fires, or SVC. Many other interrupts exists on system, but that does not make any difference (or does it?). SysTick or SVC handler itself can push those few registers (context) and change PSP. Only that. Why to bother to pass this job to lowest priority IRQ? When all (nested or not) IRQ are served return to new (to which switched) context would be done by exception return by NVIC because of EXEC_RETURN, which was written at exception entry, would still say to return to thread mode and use PSP (updated by SysTick or SVC handler) for un-stacking.
So why to use PendSV at all?
All book sand docs I find say to use PendSV as lowest priority IRQ. Unfortunately, those sources I found does not mention "why" to use the lowest priority (highest number). As I understand, lowest priority is necessary because of those cases when context switching code in ISR directly writes CPU with EXEC_RETURN value (not by exception return model), which may cause usage fault if nested IRQs if context switch would be done by higher priority ISR. Am I right? What are other reasons to have PendSV with the lowest priority?
I may be wrong somewhere, so please correct me. If this concept would work, I still want to know why PendSV is used in all popular RTOSes, why CPU itself is designed to serve that and why almost all documentation I find is saying the same. Am I missing something?Thank you in advance. Sorry for long post.
Sorry for delay.
Using PendSV at lowest interrupt priority avoids the case that context switching happened at the middle of an ISR execution. Since the PendSV is set to llowest priority, when it is executing, there won't be other ISR running in the background and therefore the context switch will only suspend the current background thread.
Of course, you can also have context switching inside your SysTick handler, but before the context switch, you need to first check if the processor was in handler mode (running an ISR) before SysTick is triggered. This checking can be done by reading the stacked PSR. If the stack PSR showing the processor was in handler mode, you could defer the context switch to next OS tick.
regards,
Joseph
>>All book sand docs I find say to use PendSV as lowest priority IRQ. Unfortunately, those sources I found does not mention "why" to use the lowest priority (highest number).
I agree.
As said by Joseph Yiu:
Using PendSV at lowest interrupt priority avoids the case that context switching happened at the middle of an ISR execution.
Then we may wonder why ?
I think it's because the stack frame of the running task that is automatically saved on the process stack by the core is a partial copy of the registers.
r4-r11 are not automatically saved. So they must be saved during the switch of context that is done by PendSV.
But, if PendSV is called while another interrupt is running, r4-r11 registers may have been scratched by the previous interrupt.
So, PendSV must have the lowest priority in order to be able to save r4-r11 registers.