Recently, I am reading the source code of UCOS-III, and I have an question about UCOS-III's task switching when it running on the Cortex-M3 platform. It use PendSV for task switching by directly writing register SCB_ICSR(Interrupt control and state register), but accessing register SCB_ICSR Requires privilege operation level. This means that the processor is runing in the process mode at privilege operation level without exceptions and interrupts, which I don't think it's safe. Why does UCOS-III not use SVC to perform pendsv? Is it a matter of efficiency? Could somebody please explain this for me? Thanks.
Background: Software:UCOS-III
Hardware:Cortex-M3(STM32F103)
Code:
.thumb_func
OSStartHighRdy:
LDR R0, =NVIC_SYSPRI14 @ Set the PendSV
exception priority
LDR R1, =NVIC_PENDSV_PRI
STRB R1, [R0]
MOVS R0, #0 @ Set the PSP to 0 for initial context switch call
MSR PSP, R0
LDR R0, =OS_CPU_ExceptStkBase @ Initialize the MSP to the OS_CPU_ExceptStkBase
LDR R1, [R0]
MSR MSP, R1
LDR R0, =NVIC_INT_CTRL @ Trigger the PendSV exception (causes context switch)
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
CPSIE I @ Enable interrupts at processor level
I think this method is better: Cortex-M3 task switch using SVC and Pensv
- Task A calls SVC for task switching (for example, waiting for some work to complete).
- The OS receives the request, prepares for context switching, and pends the PendSV exception.
- When the CPU exits SVC, it enters PendSV immediately and does the context switch.
- When PendSV finishes and returns to Thread level, it executes Task B.
- An interrupt occurs and the interrupt handler is entered.
- While running the interrupt handler routine, a SYSTICK exception (for OS tick) takes place.
- The OS carries out the essential operation, then pends the PendSV exception and gets ready for the context switch.
- When the SYSTICK exception exits, it returns to the interrupt service routine.
- When the interrupt service routine completes, the PendSV starts and does the actual context switch operations.
- When PendSV is complete, the program returns to Thread level; this time it returns to Task A and continues the processing.