移植是建立在官网的历程,并参照了野火的教程。
野火的教程中没有使用OS_CPU_SysTickHandler(),而调用了stm32库中的systick-handler()。我也赞成这种方法,因为我认为为了统一代码,启动文件startup_stm32f10x_hd.s尽量少该,能不改就不改。
所以基于上述理由,pendsv中断函数,我也没有把启动文件中中断向量表的pendsd_handler改成OS_CPU_PendSVHandler,而是在stm32f10x_it.c作如下调用。
void PendSV_Handler(void)
{
OS_CPU_PendSVHandler();
}
但是发现,ucos无法启动,而是停在了
CPSIE I ; Enable interrupts at processor level
OSStartHang
B OSStartHang
单步调的时候也有些麻烦,我用的是IAR,显示“ARM breakpoints can only be set on even points”, 貌似pendsv的代码在odd point,仿真不能。
我用MDK仿真野火给例程时没有出错,就以为是IAR的问题。纠结了一个晚上,也始终不得其解。后来没办法,开始仔细读《CM3权威指南》。
下面是我对此的解释。
在启动文件startup_stm32f10x_hd.s,跳转到中断服务程序时使用的时 B 指令,如 B PendSV_Handler,而在
void PendSV_Handler(void)
{
OS_CPU_PendSVHandler();
}
汇编出来的代码,disassembly出来的是
PUSH {R7,LR}
BL OS_CPU_PendSVHandler
POP {R0,PC}
在ucos 的 os_cpu_a.asm中OS_CPU_PendSVHandler的汇编代码是
OS_CPU_PendSVHandler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
CBZ R0, OS_CPU_PendSVHandler_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, =OSTCBCur ; 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
OS_CPU_PendSVHandler_nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
BLX R0
POP {R14}
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
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
CPSIE I
BX LR ; Exception return will restore remaining context
其中 ORR LR, LR, #0x04 会改变堆栈,由MSP改成PSP,故如果按我最开始的移植方法,
void PendSV_Handler(void)
{
OS_CPU_PendSVHandler();
}
OS_CPU_PendSVHandler(); 结束时,应该还在中断服务程序中,但ORR LR, LR, #0x04 已经改变了堆栈,不再是MSP,PendSV_Handler()再执行就会出错(因为堆栈指针,保存的寄存器已经被弹出)。
故在移植时不能在 PendSV_Handler() 中调用OS_CPU_PendSVHandler(), 因为OS_CPU_PendSVHandler()本质上已经是个完整的中断handdler。
其实在官网下载的文件包中 AN-1018.pdf 文件中已经说明(23页):
Note that you must place a pointer to OS_CPU_PendSVHandler() in the exception vector table at vector location 14 (based of the vector table +4*14 or, offset 56).
希望我的解释是对的,并对大家有帮助。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
你把ucos的跟stm32启动文件的pendsv中断名字改成一样就可以
一周热门 更多>