这个是OS_Sched的反汇编代码, 这个里面调用了OSCtxSw, 在调用之前, 并没有PUSH {R4,R5}, 而且此时R4存放的OS_CPU_SR_Save的值.
void OS_Sched (void) { OS_Sched: 080010E4 B530 PUSH {R4,R5, LR} OS_ENTER_CRITICAL(); 080010E6 F000F917 BL OS_CPU_SR_Save 080010EA 0004 MOVS R4, R0 =================这里, 返回值存放到 R4============= if (OSIntNesting == 0) { /* Schedule only if all ISRs done and ... */ 080010EC 4D88 LDR R5, [PC,#0x220] ; [0x8001310] =OSCPUUsage (0x20001094) 080010EE 78A8 LDRB R0, [R5, #2] 080010F0 2800 CMP R0, #0 080010F2 D114 BNE 0x800111E if (OSLockNesting == 0) { /* ... scheduler is not locked */ 080010F4 78E8 LDRB R0, [R5, #3] 080010F6 2800 CMP R0, #0 080010F8 D111 BNE 0x800111E OS_SchedNew(); 080010FA F000F815 BL OS_SchedNew if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ 080010FE 7968 LDRB R0, [R5, #5] 08001100 7929 LDRB R1, [R5, #4] 08001102 4288 CMP R0, R1 08001104 D00B BEQ 0x800111E OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; 08001106 4983 LDR R1, [PC,#0x20C] ; [0x8001314] =OSTCBPrioTbl (0x20001CCC) 08001108 F8510020 LDR R0,[R1, R0,LSL #2] 0800110C 62A8 STR R0, [R5, #40] OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ 0800110E 6B41 LDR R1, [R0, #52] 08001110 1C49 ADDS R1, R1, #0x1 08001112 6341 STR R1, [R0, #52] OSCtxSwCtr++; /* Increment context switch counter */ 08001114 6928 LDR R0, [R5, #16] 08001116 1C40 ADDS R0, R0, #0x1 08001118 6128 STR R0, [R5, #16] OS_TASK_SW(); /* Perform a context switch */ 0800111A F000F911 BL OSCtxSw =============这里调用================== =============返回时候R4可能已经改变======= OS_EXIT_CRITICAL(); 0800111E 0020 MOVS R0, R4 ==================这里============= 08001120 F000F8FE BL OS_CPU_SR_Restore } 08001124 BD30 POP {R4,R5} 08001126 0000 MOVS R0, R0
刚刚有人提供英贝特的版本, R4,R5入栈了.
;/************************************************************************************** ;* 函数名称: OSCtxSw ;* ;* 功能描述: 任务级上下文切换 ;* ;* 参 数: None ;* ;* 返 回 值: None ;* ;* 作 者: 罗辉联 ;* 日 期: 2007年11月10日 ;*-------------------------------------------------------------------------------------- ;***************************************************************************************/ OSCtxSw PUSH {R4, R5} LDR R4, =NVIC_INT_CTRL ;触发PendSV异常 (causes context switch) LDR R5, =NVIC_PENDSVSET STR R5, [R4] POP {R4, R5} BX LR
;/************************************************************************************** ;* 函数名称: OSIntCtxSw ;* ;* 功能描述: 中断级任务切换 ;* ;* 参 数: None ;* ;* 返 回 值: None ;* ;* 作 者: 罗辉联 ;* 日 期: 2007年11月10日 ;*-------------------------------------------------------------------------------------- ;***************************************************************************************/
OSIntCtxSw PUSH {R4, R5} LDR R4, =NVIC_INT_CTRL ;触发PendSV异常 (causes context switch) LDR R5, =NVIC_PENDSVSET STR R5, [R4] POP {R4, R5} BX LR NOP
我认为这里用R0, R1可以, R0--R3应该是可以安全使用, 不用入栈, 具体的细节还需参考编译器的手册. |