uc/OS-II 用于任务切换的中断在什么时候恢复?

                OSCtxSwCtr++; /* Increment context switch counter             */
                OS_TASK_SW(); /* Perform a context switch                     */
            }
        }
    }
    OS_EXIT_CRITICAL();
}

OS_TASK_SW(); 之后什么时候恢复 PC 寄存器?如果马上恢复,那就跳转到别的任务了,
OS_EXIT_CRITICAL 不就被忽略了吗?
用的的函数有下面这些

#define  OS_TASK_SW()         OSCtxSw()
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
#define  OS_CRITICAL_METHOD   3 //进入临界段的方法

#if OS_CRITICAL_METHOD == 3
#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}
#endif
OS_CPU_SR_Restore
    MSR     PRIMASK, R0 ;读取R0到PRIMASK中,R0为参数
    BX      LR ;返回

在 PendSV_Handler 结尾有

CPSIE   I ;开中断

还有,OSCtxSw 里面 POP {R4, R5},不是把刚刚 PendSV_Handler 对 R4-R11 的操作覆盖了吗?
谢谢~

在 ARM Cortex-M 架构中,当发生 PendSV 异常时,CPU 会自动将当前任务的寄存器内容保存到任务栈中,并切换到另一个任务的堆栈。在切换到另一个任务之前,CPU 会将任务栈指针保存到 PSP 寄存器中,以便切换回该任务时使用。

在上述代码中,OS_TASK_SW() 宏会调用 OSCtxSw() 函数,在该函数中会触发 PendSV 异常,从而进行任务切换。在 PendSV_Handler 函数中,由于 CPU 已经自动保存了当前任务的寄存器内容,因此可以进行上下文切换操作。在上下文切换完成后,CPU 会自动从 PSP 寄存器中读取新任务的堆栈指针,并更新相关寄存器。

在 PendSV_Handler 函数结尾处开中断是为了允许新任务在退出临界区后能够响应中断。因为在进入临界区时,CPU 会将 PRIMASK 寄存器中断开关位(第0位)设置为 1,从而禁止所有中断的响应。在退出临界区时,需要将 PRIMASK 寄存器恢复为先前的值,以便中断可以继续响应。

至于 OSCtxSw() 函数中的 POP {R4, R5} 操作,其目的是为了恢复任务切换之前的堆栈指针和程序计数器(PC)的值。在触发 PendSV 异常后,CPU 会将 R0-R3、R12、LR 和 PSR 寄存器的值自动保存到当前任务的堆栈中,而 R4-R11 寄存器的值则会被保存到 PSP 寄存器指向的堆栈中。因此,在切换回原任务时,需要将 R4-R11 寄存器的值从任务栈中恢复回来。另外,由于 PC 寄存器的值也需要在任务切换时进行保存和恢复,因此 POP {R4, R5} 操作不会覆盖 PendSV_Handler 对 R4-R11 的操作。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 文章:xos详解5:PendSV_Handler 中也许有你想要的答案,请看下吧
  • 除此之外, 这篇博客: uCOS-II 的任务上下文切换流程中的 OS_CPU_PendSVHandler 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    • 这个是 uCOS-II 的 PendSV 中断处理函数,实现了任务上下文的切换,通过长长的注释,很经典的说明了任务切换的流程,这里做个随笔记录一下
    • 原文注释如下:
    ;********************************************************************************************************
    ;                                       HANDLE PendSV EXCEPTION
    ;                                   void OS_CPU_PendSVHandler(void)
    ;
    ; Note(s) : 1) PendSV is used to cause a context switch.  This is a recommended method for performing
    ;              context switches with Cortex-M.  This is because the Cortex-M auto-saves half of the
    ;              processor context on any exception, and restores same on return from exception.  So only
    ;              saving of R4-R11 & R14 is required and fixing up the stack pointers. Using the PendSV exception
    ;              this way means that context saving and restoring is identical whether it is initiated from
    ;              a thread or occurs due to an interrupt or exception.
    ;
    ;           2) Pseudo-code is:
    ;              a) Get the process SP
    ;              b) Save remaining regs r4-r11 & r14 on process stack;
    ;              c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
    ;              d) Call OSTaskSwHook();
    ;              e) Get current high priority, OSPrioCur = OSPrioHighRdy;
    ;              f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
    ;              g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
    ;              h) Restore R4-R11 and R14 from new process stack;
    ;              i) Perform exception return which will restore remaining context.
    ;
    ;           3) On entry into PendSV handler:
    ;              a) The following have been saved on the process stack (by processor):
    ;                 xPSR, PC, LR, R12, R0-R3
    ;              b) Processor mode is switched to Handler mode (from Thread mode)
    ;              c) Stack is Main stack (switched from Process stack)
    ;              d) OSTCBCur      points to the OS_TCB of the task to suspend
    ;                 OSTCBHighRdy  points to the OS_TCB of the task to resume
    ;
    ;           4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
    ;              know that it will only be run when no other exception or interrupt is active, and
    ;              therefore safe to assume that context being switched out was using the process stack (PSP).
    ;
    ;           5) Increasing priority using a write to BASEPRI does not take effect immediately.
    ;              (a) IMPLICATION  This erratum means that the instruction after an MSR to boost BASEPRI
    ;                  might incorrectly be preempted by an insufficient high priority exception.
    ;
    ;              (b) WORKAROUND  The MSR to boost BASEPRI can be replaced by the following code sequence:
    ;
    ;                  CPSID i
    ;                  MSR to BASEPRI
    ;                  DSB
    ;                  ISB
    ;                  CPSIE i
    ;********************************************************************************************************
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^