STM32 UCOS移植分析 参考文档
Cortex M3 技术参考手册
STM32F10xxx Cortex-M3 programming manual
1,STM32复位后进入线程模式 Processing and handler模式
主堆栈为MSP,进程堆栈为PSP
所有处理模式使用MSP,线程模式可以是MSP或者PSP
默认状态线程模式使用MSP,可以采用MSR+ISB指令来设置ASPSEL位
__MSR_CONTROL
MSR CONTROL, r0 ISB BX r14
异常优先级处理
Each PRI_N field is 8 bits wide, but the processor implements only bits[7:4] of each field, and bits[3:0] read as zero and ignore writes.
将PENDSV优先级置为0xff,实际上0xF0
ICSR 触发PENDSV
好了,从现在开始
复位后,系统采用MSP,进入main函数,调用BSP_INIT初始时钟外设以及时钟节拍和中断。初始化OS变量,建立任务,任务建立时调用OS_STK *OSTaskStkInit ,将任务堆栈中存入
XPSR =0x01000000
PC=TASK (也就是任务的入口地址) LR=0xFFFFFFFEL R12 R3 R2 R1
R0=p_arg(传递给任务的参数) R11-R4
启动任务 OSStart() 运行OSStartHighRdy
第一步设置OPENSV异常优先级0xFF,为最低,第二步将PSP也就是线程堆栈指针设为0,用于第一次进任务检测,第三步 OSRunning = TRUE,设置运行标志位。
第4步触发一次PENDSV,然后开全局中断,立即进入pendsv异常处理程序完成上下文切换。
OSStartHighRdy
LDR R0, =NVIC_SYSPRI2 ; 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_Running ; OSRunning = TRUE MOVS R1, #1 STRB R1, [R0]
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
OSStartHang
B OSStartHang ; Should never get here
OPENSV 异常服务分析
1,判断PSP值是否为0,为0则是第一次做上下文切换,也就是starthignready触发的,跳过R4-R11压栈处理,直接到OSPendSV_nosave运行,此时处于异常模式,运行的为MSP
运行OSTaskSwHook(); OSPrioCur = OSPrioHighRdy; OSTCBCur = OSTCBHighRdy; 取出最高优先级任务堆栈指针,将R4-R11出栈,出栈了8个32为寄存器,R0地址加上0x20,然后将R0的值给PSP,即用户线程堆栈指针 ORR LR, LR, #0x04
OSPendSV
;MRS R3, PRIMASK ; ;CPSID I ;
MRS R0, PSP ; PSP is process stack pointer
CBZ R0, OSPendSV_nosave ; skip register save the first time
SUBS R0, R0, #0x20 ; save remaining regs r4-11 on process stack STM R0, {R4-R11}
LDR R1, __OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP; LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out
; at this point, entire context of process has been saved
OSPendSV_nosave
PUSH {R14} ; need to save LR exc_return value
LDR R0, __OS_TaskSwHook ;OSTaskSwHook(); BLX R0 POP {R14}
LDR R0, __OS_PrioCur ; OSPrioCur = OSPrioHighRdy; LDR R1, __OS_PrioHighRdy LDRB R2, [R1] STRB R2, [R0]
LDR R0, __OS_TCBCur ; OSTCBCur = OSTCBHighRdy; LDR R1, __OS_TCBHighRdy LDR R2, [R1] STR R2, [R0]
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0, {R4-R11} ; restore r4-11 from new process stack ADDS R0, R0, #0x20
MSR PSP, R0 ; load PSP with new process SP
ORR LR, LR, #0x04 ; ensure exception return uses process stack ;MSR PRIMASK, R3 ;
BX LR ; exception return will restore remaining context