ucos(一) 任务切换

(1) ucos版本查看 OS_VERSION

 

(2) ARM一般是小端模式,堆栈指针一般位于高地址,向下生长

 

 

OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
    OS_STK *stk;


    opt      = opt;                         /* 'opt' is not used, prevent warning                      */
    stk      = ptos;                        /* Load stack pointer (堆栈栈顶处)                                     */
    *(stk)   = (OS_STK)task;                /* Entry Point  (实际就是函数名)                                           */
    *(--stk) = (INT32U)0x14141414L;         /* R14 (LR)                                                */
    *(--stk) = (INT32U)0x12121212L;         /* R12                                                     */
    *(--stk) = (INT32U)0x11111111L;         /* R11                                                     */
    *(--stk) = (INT32U)0x10101010L;         /* R10                                                     */
    *(--stk) = (INT32U)0x09090909L;         /* R9                                                      */
    *(--stk) = (INT32U)0x08080808L;         /* R8                                                      */
    *(--stk) = (INT32U)0x07070707L;         /* R7                                                      */
    *(--stk) = (INT32U)0x06060606L;         /* R6                                                      */
    *(--stk) = (INT32U)0x05050505L;         /* R5                                                      */
    *(--stk) = (INT32U)0x04040404L;         /* R4                                                      */
    *(--stk) = (INT32U)0x03030303L;         /* R3                                                      */
    *(--stk) = (INT32U)0x02020202L;         /* R2                                                      */
    *(--stk) = (INT32U)0x01010101L;         /* R1                                                      */
    *(--stk) = (INT32U)p_arg;               /* R0 : argument                                           */
    *(--stk) = (INT32U)ARM_SVC_MODE;        /* CPSR  (Enable both IRQ and FIQ interrupts)              */

    return (stk);
}

 

INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
    ...................   

   ptcb->OSTCBStkPtr    = ptos;   //即上面返回的指针保存在任务块中,作为以后SP指针的地址,存取CPU寄存器  

   ....................

 

 

假设定义固定长度堆栈 OS_STK Stack1[STKSIZE]  (OS_STK 32位长度)

 

实际任务(task)堆栈结构

Stack1[STKSIZE-1] = Entry Point  (实际上是任务运行到某处的PC值)

Stack1[STKSIZE-2] = LR 

...........................................

Stack1[STKSIZE-16] = CPSR     

 

Stack1[STKSIZE-17] = DATA1   //作为任务其他需要用到的堆栈空间

............................................

Stack1[STKSIZE-N] = DATAN   //例如任务中的局部变量等

 

void  OS_Sched (void)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3                            /* Allocate storage for CPU status register     */
    OS_CPU_SR  cpu_sr;

 

    cpu_sr = 0;                                        /* Prevent compiler warning                     */
#endif   
    OS_ENTER_CRITICAL();
    if (OSIntNesting == 0) {                           /* Schedule only if all ISRs done and ...       */
        if (OSLockNesting == 0) {                      /* ... scheduler is not locked                  */
            y             = OSUnMapTbl[OSRdyGrp];      /* Get pointer to HPT ready to run              */
            OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
            if (OSPrioHighRdy != OSPrioCur) {          /* 获得最高优先级OSPrioHighRdy*/
                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
                OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task      */
#endif
                OSCtxSwCtr++;                          /* Increment context switch counter             */
                OS_TASK_SW();                          /* Perform a context switch                     */
            }
        }
    }
    OS_EXIT_CRITICAL();
}

 

                                    

 

OSCtxSw   ;任务切换
                                        ; SAVE CURRENT TASK'S CONTEXT


        STMFD   SP!, {LR}               ;     将当前任务下一条PC指令的值推入该任务堆栈中

        STMFD   SP!, {LR}              

    
        STMFD   SP!, {R0-R12}           ;     将其他寄存器依次推入该任务堆栈中

        MRS     R4,  CPSR               ;     Push current CPSR
        TST     LR, #1                  ;     See if called from Thumb mode
        ORRNE   R4,  R4, #0x20          ;     If yes, Set the T-bit
        STMFD   SP!, {R4}
       
        LDR     R4, =OSTCBCur   ; OSTCBCur->OSTCBStkPtr = SP;(将该任务的SP指针保存起来,以备以后存取)
        LDR     R5, [R4]
        STR     SP, [R5]

        LDR     R0, =OSTaskSwHook       ; OSTaskSwHook();
        MOV     LR, PC
        BX      R0           

        LDR     R4, =OSPrioCur          ; OSPrioCur = OSPrioHighRdy (将最高优先级的任务作为当前任务)
        LDR     R5, =OSPrioHighRdy
        LDRB    R6, [R5]
        STRB    R6, [R4]
       
        LDR     R4, =OSTCBCur           ; OSTCBCur  = OSTCBHighRdy;
        LDR     R6, =OSTCBHighRdy
        LDR     R6, [R6]
        STR     R6, [R4]

        LDR     SP, [R6]                ; SP = OSTCBHighRdy->OSTCBStkPtr;(将SP指向新任务的堆栈处)

                                        ; RESTORE NEW TASK'S CONTEXT
        LDMFD   SP!, {R4}               ;    Pop new task's CPSR
        MSR     SPSR_cxsf, R4
       
        LDMFD   SP!, {R0-R12,LR,PC}^    ;    Pop new task's context  (跳转到新任务上一次被中断的PC处)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值