FreeRTOS是如何工作的--上下文切换的完整例子

下面介绍一个完整的上下文切换的例子

连起来(Putting It All Together)

在第2节的最后一部分 展示了这些 积木模块(building blocks)和源代码模块(source code modules)使如何来达到 一个在AVR微控制器上进行RTOS上下文切换的目的的。这个例子分几步演示了从一个低的优先级的任务Task A,切换到高优先级的任务Task B的。

源代码与WinAVR C开发工具兼容。

上下文切换-第1步

在RTOS tick 中断发生之前

这个例子,以TaskA的执行开始。TaskB先前已经被挂起,所以它的上下文已经被保存到TaskB的stack里面。

TaskA的上下文如下图所示:

 在每个寄存器里标上(A),表示,这寄存器含有 任务A的上下文的正确值。

  

上下文切换—第2步

RTOS tick中断 发生了

 当TaskA 将要执行到一个LDI指令的时候,RTOS tick 发生。当中断发生时,AVR微控制器会在跳入到RTOS tickISR之前,自动放置当前的PC到stack里面。

AtoB3.gif

上下文切换-第3步

RTOS tick 中断(服务)执行

ISR源代码如下。为便于阅读,移除注释。

/* Interrupt service routine for the RTOS tick. */
void SIG_OUTPUT_COMPARE1A( void )
{
    vPortYieldFromTick();
    asm volatile ( "reti" );
}
/*--------------------------------------------------*/
void vPortYieldFromTick( void )
{
    portSAVE_CONTEXT();
    vTaskIncrementTick();
    vTaskSwitchContext();
    portRESTORE_CONTEXT();
    asm volatile ( "ret" );
}
/*--------------------------------------------------*/


SIG_OUTPUT_COMPARE1A()是一个naked 函数。所以第一条指令是调用vPortYieldFromTick()..vPortYieldFromTick()也是一个naked 函数,所以AVR执行上下文被portSAVE_CONTEXT().明确保存。

portSAVE_CONTEXT()将整个AVR执行上下文全部压入TaskA的Stack..示意图如下。TaskA的栈顶指针(Stack Pointer)现在指向它自己的上下文的顶部。portSAVE_CONTEXT()通过保存栈顶指针的一份拷贝来完成。在上次TaskB挂起时,实时内核已经复制了TaskB的栈顶指针。

AtoB3.gif

上下文切换-第4步
增加tick count

在TaskA上下文被保存之后 再执行vTaskIncrementTick()。这个例子,假定tick count的增加会引起TaskB 准备运行。TaskB比TaskA有更高的优先级,所以vTaskSwitchContext()在ISR完成后将处理器交给 TaskB.


上下文切换-第5步
TaskB的栈顶指针被取得

TaskB的任务必须被恢复。portRESTORE_CONTEXT要做的第1件事情就是从TaskB被挂起时保存的拷贝里 取得TaskB的栈顶指针。TaskB的栈顶指针 被载入到处理器的stack pointer.所以现在AVR的栈顶指针就是指向TaskB的上下文。

上下文切换-第6步

恢复TaskB的上下文
portRESTORE_CONTEXT()从TaskB的stack中恢复它的上下文到相应的处理器寄存器。

AtoB5.gif

只有PC(program counter)还留在stack中。

 

上下文切换-第7步
RTOS tick退出

vPortYieldFromTick()返回到SIG_OUTPUT_COMPARE1A(),在那里,最后一条指令是从中断返回(RETI).   RETI指令假定stack中的下个值就是中断发生时返回地址。

当RTOS tick 中断发生时,AVR自动放置TaskA的返回地址(在TaskA中的下条指令的地址)到stack.。 ISR修改stack pointer 它指向了TaskB的stack. 从而,RETI指令从stack弹出的返回地址是 TaskB在挂起前 将要立即执行的指令的地址.
AtoB6.gif

RTOS tick,它中断的是 TaskA,然而却返回到了TaskB,这就完成了上下文切换。

 

====The End( 全文完)====

 

作者:Gavin Lee   更新日期:2006-04-24
来源:upsdn.net   浏览次数:

相关文章

相关评论   发表评论