STM32中uCOS的任务切换讨论

     在STM32平台下,移植了uCOS V291的核。然后在网上下载了一个移植文件:

  • os_cpu_c.c
  • os_cpu_asm.asm

    本人并没有非常详细地去看任务切换过程的具体实现。只是大致有了一个了解。

    当在后台程序中调用OSCtxSw()或OSIntCtxSw()进行任务切换时,其操作都是触发一个软中断PendSV_Handler(),让软中断来进行切换任务栈。如下:

OSCtxSw
    LDR     R0, =NVIC_INT_CTRL      
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR
OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL          
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

PendSV_Handler()中断处理函数如下:

PendSV_Handler
    CPSID   I                              
    MRS     R0, PSP                        
    CBZ     R0, OS_CPU_PendSVHandler_nosave 
    SUBS    R0, R0, #0x20                    
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCur                    ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                         ; R0 is SP of process being switched out

                                             
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]     
    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                    
    CPSIE   I
    BX      LR                   
    END

问题:

    对于一般的小程序这样的任务切换方法简单有效,但最后我在调试一个中断触发频率非常高的设备时,发现PenSV_Handler()没有及时触发,甚至没有触发。这导致任务切换失败。

    但我在调试程序时,单步运行程序至OSCtxSw(),OSCtxSw()执行完成了,并没有直接进入PenSV_Handler()中断进行任务切换操作,而是处理外部触发的中断去了。而在外部触发的中断又要求切换任务。

    总体上讲,外部中断抢占了大部分的执行资源,而PenSV_Handler()得不到执行。所以,任务切换失败。

 

解决方案:

  1. 摒弃软中断任务切换,改用函数任务切换方式。这样可以保证OSCtxSw()或OSIntCtxSw()执行完成了任务一定切换完成。
  2. 将软中断PendSV_Handler(),触发优先级提至最高。

 相对而言,提升PendSV的中断优先级比较容易。

你可能感兴趣的:(OS,任务,平台)