STM32中uCOS的任务切换讨论
- os_cpu_c.c
- os_cpu_asm.asm
本人并没有非常详细地去看任务切换过程的具体实现。只是大致有了一个了解。
本文引用地址:https://www.eepw.com.cn/article/201611/318809.htm当在后台程序中调用OSCtxSw()或OSIntCtxSw()进行任务切换时,其操作都是触发一个软中断PendSV_Handler(),让软中断来进行切换任务栈。如下:
- OSCtxSw
- LDRR0,=NVIC_INT_CTRL
- LDRR1,=NVIC_PENDSVSET
- STRR1,[R0]
- BXLR
- OSIntCtxSw
- LDRR0,=NVIC_INT_CTRL
- LDRR1,=NVIC_PENDSVSET
- STRR1,[R0]
- BXLR
PendSV_Handler()中断处理函数如下:
- PendSV_Handler
- CPSIDI
- MRSR0,PSP
- CBZR0,OS_CPU_PendSVHandler_nosave
- SUBSR0,R0,#0x20
- STMR0,{R4-R11}
- LDRR1,=OSTCBCur;OSTCBCur->OSTCBStkPtr=SP;
- LDRR1,[R1]
- STRR0,[R1];R0isSPofprocessbeingswitchedout
- OS_CPU_PendSVHandler_nosave
- PUSH{R14};SaveLRexc_returnvalue
- LDRR0,=OSTaskSwHook;OSTaskSwHook();
- BLXR0
- POP{R14}
- LDRR0,=OSPrioCur;OSPrioCur=OSPrioHighRdy;
- LDRR1,=OSPrioHighRdy
- LDRBR2,[R1]
- STRBR2,[R0]
- LDRR0,=OSTCBCur;OSTCBCur=OSTCBHighRdy;
- LDRR1,=OSTCBHighRdy
- LDRR2,[R1]
- STRR2,[R0]
- LDRR0,[R2]
- LDMR0,{R4-R11};Restorer4-11fromnewprocessstack
- ADDSR0,R0,#0x20
- MSRPSP,R0;LoadPSPwithnewprocessSP
- ORRLR,LR,#0x04
- CPSIEI
- BXLR
- END
问题:
对于一般的小程序这样的任务切换方法简单有效,但最后我在调试一个中断触发频率非常高的设备时,发现PenSV_Handler()没有及时触发,甚至没有触发。这导致任务切换失败。
但我在调试程序时,单步运行程序至OSCtxSw(),OSCtxSw()执行完成了,并没有直接进入PenSV_Handler()中断进行任务切换操作,而是处理外部触发的中断去了。而在外部触发的中断又要求切换任务。
总体上讲,外部中断抢占了大部分的执行资源,而PenSV_Handler()得不到执行。所以,任务切换失败。
解决方案:
- 摒弃软中断任务切换,改用函数任务切换方式。这样可以保证OSCtxSw()或OSIntCtxSw()执行完成了任务一定切换完成。
- 将软中断PendSV_Handler(),触发优先级提至最高。
相对而言,提升PendSV的中断优先级比较容易。
评论