OSCtxSw()函数把被中止任务的断点指针和CPU的寄存器值保存到该任务的堆栈中,并从待运行任务的堆栈中得到其堆栈指针,把待运行任务堆栈中的存储的CPU通用寄存器的内容恢复到CPU的通用寄存器中,最后使CPU获得待运行任务的断点指针。
任务切换函数OSCtxSw()一般有2种方法实现。一种是软中断,周立功的LPC资料上都是这么用的。一种是用子程序调用,我现在做的这个项目就是这么实现的。
在OS_CPU.H中定义
#define OS_TASK_SW() OSCtxSw()
OSCtxSw()函数在OS_CPU_A.S中:
OSCtxSw
STMFD SP!, {LR} ;PC (1)
STMFD SP!, {R0-R12, LR} ;R0-R12 LR (2)
MRS R4, CPSR ;Push CPSR (3)
STMFD SP!, {R4}
LDR R4, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; (4)
LDR R5, [R4] ;(5)
STR SP, [R5] ;(6)
;BL OSTaskSwHook ; OSTaskSwHook(); (7)
LDR R4, =OSPrioCur ; OSPrioCur = OSPrioHighRdy (8)
LDR R5, =OSPrioHighRdy ;(9)
LDRB R6, [R5] ;(10)
STRB R6, [R4] ;(11)
LDR R4, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; ;(12)
LDR R6, =OSTCBHighRdy ;(13)
LDR R6, [R6] ;(14)
STR R6, [R4] ;(15)
LDR SP, [R6] ; SP = OSTCBHighRdy->OSTCBStkPtr; ;(16)
LDMFD SP!, {R4} ;POP CPSR ;(17)
MSR CPSR_cxsf, R4 ;(18)
LDMFD SP!, {R0-R12, LR, PC} ;(19)
OS_Sched (void)函数在OS_CORE.C中:
void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL();
if (OSIntNesting == 0) {
if (OSLockNesting == 0) {
OS_SchedNew();
if(OSPrioHighRdy!=OSPrioCur) {
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
OSTCBHighRdy->OSTCBCtxSwCtr++;
#endif
OSCtxSwCtr++; OS_TASK_SW();
}
}
}
OS_EXIT_CRITICAL();
}
在ADS中通过汇编语言可以看到,OS_TASK_SW();语句对应的汇编语句是 BL OSCtxSW
继续阅读 →