MSP430F5xxx RTOS 恢复上下文汇编器不清楚

MSP430F5xxx RTOS restore context assembler not clear

我正在尝试将 FunkOS RTOS 从 MSP430F2xxx 移植到 MSP430F5529。我将 CCS 10.4 与 TI v20.2.5 LTS 编译器结合使用。我移植了大部分代码,但我对 RTOS 接管控制权有疑问。初始化所有任务后,我调用 Task_StartTasks 函数。 我的问题出在这个函数的汇编程序部分。

void Task_StartTasks(void)
{   
    Task_SetScheduler(TRUE);
    Task_Switch();
    // Restore the context...
    asm(" mov.w  &pstCurrentTask, r12");
    asm(" mov.w  @r12, r1");
    asm(" pop  r15");
    asm(" pop  r14");
    asm(" pop  r13");
    asm(" pop  r12");
    asm(" pop  r11");
    asm(" pop  r10");
    asm(" pop  r9");
    asm(" pop  r8");
    asm(" pop  r7");
    asm(" pop  r6");
    asm(" pop  r5");
    asm(" pop  r4");
    asm(" bic.w  #0x00F0, 0(SP)");
    asm(" reti");
}

pstCurrentTask 是指向以下结构的全局指针:

typedef struct Task_Struct
{
/*! This is the basic task control block in the RTOS.  It contains parameters
    and state information required for a task, including stack, priority, 
    timeouts, entry funcitons, and task pending semaphore.
*/  
    //--[Task Control Block Entries]-----------------------------------------
    WORD *pwTopStack;       //!< Pointer to current stack top 
    WORD *pwStack;          //!< Stack pointer, defined by the task.    
    USHORT usStackSize;     //!< Size of the stack in MAU
    //--[Task Definitions]---------------------------------------------------
    BYTE *pacName;          //!< Pointer to the name of the task (ASCII)
    TASK_FUNC pfTaskFunc;   //!< Pointer to the entry function
    UCHAR ucPriority;       //!< Task priority
    TASK_STATE eState;      //!< Current task state
    USHORT usTimeLeft;      //!< Ticks remaining in blocked/sleep state 
    BOOL bTimeout;          //!< Indicates that an IO operation timed out
    struct Task_Struct *pstNext;        //!< Pointer to the next task (handled by scheduler)
} TASK_STRUCT;

Task_SetScheduler 和 Task_Switch 确保 pstCurrentTask 指向正确的任务结构。据我了解:

    asm(" mov.w  &pstCurrentTask, r12");
    asm(" mov.w  @r12, r1");

将 pstCurrentTask 的值(在这种情况下,这只是结构的地址?)移动到 R1,对于 MSP430,R1 是堆栈指针(为什么?)。然后弹出所有寄存器,魔术就在这里发生了。

我不明白这是怎么回事:

asm(" bic.w  #0x00F0, 0(SP)");

如果有人能在这里解释汇编程序就太好了。

不要错过 @。堆栈指针被(重新)设置为 pstCurrentTask->pwTopStack(因为它是结构中的第一个字段,取消对结构指针的引用就可以做到这一点,而无需任何额外的偏移量),大概是指向原始堆栈的指针被存储了在寄存器被推入并现在放回原位之后。

然后弹出寄存器。在最后 reti 导致另外两个寄存器被弹出:状态寄存器和程序计数器(指令指针),后者导致存储值 jump/return。

但就在这之前,bic.w 清除堆栈中该值的一些位,即通过清除 CPUOFF、OSCOFF、SCG0、SCG1 来关闭低功耗模式。它对当前位于堆栈顶部的值(取消引用偏移量为零的 SP)进行操作,该值是即将成为状态寄存器。这意味着即使存储的状态寄存器设置了这些位,表示低功耗模式,当它作为 reti.

的一部分再次弹出时,它们也不会再被设置。

如果将该行翻译成 C 语言,它会是这样的:

SP[0] &= ~0x00f0;
// 0x00f0 comes from (CPUOFF | OSCOFF | SCG0 | SCG1) 

请注意,0x00f0 不是外围设备或类似的东西。它只是状态寄存器上使用的位掩码。在 manual 中,查看第 40 页的第 2.3.1 章(进入和退出低功耗模式)。那里使用了一个非常相似的命令,但是使用命名常量的总和而不是数值,在我们的例子中是 CPUOFF+OSCOFF+SCG0+SCG1 而不是 0x00f0。如果您查看第 46 页上的第 3.2.3 章(状态寄存器),您就会明白为什么 - 这 4 个标志位于状态寄存器的第 4-7 位,即它们的值分别为 0x0010、0x0020、0x0040 和 0x0080,添加时或 ORed 一起给你 0x00f0.