移植μC/OS-Ⅱ
通过调用OSIntCtxSw()来从ISR中执行切换功能。 因为OSIntCtxSw()是在ISR中被调用的,所以可以断定所有的处理器寄存器都被正确地保存到了被中断的任务的堆栈之中。实际上除了我们需要的东西外,堆栈结构中还有其它的一些东西。OSIntCtxSw()必须要清理堆栈,这样被中断的任务的堆栈结构内容才能满足我们的需要。
要想了解OSIntCtxSw(),用户可以看看μC/OS-Ⅱ调用该函数的过程。用户可以参看图8.2来帮助理解下面的描述。假定中断不能嵌套(即ISR不会被中断),中断是允许的,并且处理器正在执行任务级的代码。当中断来临的时候,处理器会结束当前的指令,识别中断并且初始化中断处理过程, 包括将处理器的状态寄存器和返回被中断的任务的地址保存到堆栈中[F8.2(1)]。至于究竟哪些寄存器保存到了堆栈上,以及保存的顺序是怎样的,并不重要。
图 8.2 在ISR执行过程中的堆栈内容.

接着,CPU会调用正确的ISR。μC/OS-Ⅱ要求用户的ISR在开始时要保存剩下的处理器寄存器[F8.2(2)]。一旦寄存器保存好了,μC/OS-Ⅱ就要求用户或者调用OSIntEnter(),或者将变量OSIntNesting加1。在这个时候,被中断任务的堆栈中只包含了被中断任务的寄存器内容。现在,ISR可以执行中断服务了。并且如果ISR发消息给任务(通过调用OSMboxPost()或OSQPost()), 恢复任务(通过调用OSTaskResume()), 或者调用OSTimeTick()或OSTimeDlyResume()的话,有可能使更高优先级的任务处于就绪状态。
假设有一个更高优先级的任务处于就绪状态。μC/OS-Ⅱ要求用户的ISR在完成中断服务的时候调用OSIntExit()。OSIntExit()会告诉μC/OS-Ⅱ到了返回任务级代码的时间了。
调用OSIntExit()会导致调用者的返回地址被保存到被中断的任务的堆栈中[F8.2(3)]。
OSIntExit()刚开始时会禁止中断,因为它需要执行临界段的代码。根据OS_ENTER_CRITICAL()的不同执行过程(参看8.03.02),处理器的状态寄存器会被保存到被中断的任务的堆栈中[F8.2(4)]。OSIntExit()注意到由于有更高优先级的任务处于就绪状态,被中断的任务已经不再是要继续执行的任务了。在这种情况下,指针OSTCBHighRdy会被指向新任务的OS_TCB,并且OSIntExit()会调用OSIntCtxSw()来执行任务切换。调用OSIntCtxSw()也同样使返回地址被保存到被中断的任务的堆栈中[F8.2(5)]。
在用户切换任务的时候,用户只想将某些项([F8.2(1)]和[F8.2(2)])保留在堆栈中,并忽略其它项(F8.2(3),(4)和(5)) 。这是通过调整堆栈指针(加一个数在堆栈指针上)来完成的[F8.2(6)]。加在堆栈指针上的数必须是明确的,而这个数主要依赖于移植的目标处理器(地址空间可能是16,32或64位),所用的编译器,编译器选项,内存模式等等。另外,处理器状态字可能是8,16,32甚至64位宽,并且OSIntExit()可能会分配局部变量。有些处理器允许用户直接增加常量到堆栈指针中,而有些则不允许。在后一种情况下,可以通过简单的执行一定数量的pop(出栈)指令来实现相同的功能。一旦堆栈指针完成调整,新的堆栈指针会被保存到被切换出去的任务的OS_TCB中[F8.2(7)]。
OSIntCtxSw()的原型如程序清单L8.3所示。这些代码必须写在汇编语言中,因为用户不能直接从C语言中访问CPU寄存器。如果用户的编译器支持插入汇编语言代码的话,用户就可以将OSIntCtxSw()代码放到OS_CPU_C.C文件中,而不放到OS_CPU_A.ASM文件中。正如用户所看到的那样,除了第一行以外,OSIntCtxSw()的代码与OSCtxSw()是一样的。这样在移植实例中,用户可以通过“跳转”到OSCtxSw()中来减少 OSIntCtxSw()代码量。
程序清单 L8.3 OSIntCtxSw()的原型
voidOSIntCtxSw(void)
{
调整堆栈指针来去掉在调用:
OSIntExit(),
OSIntCtxSw()过程中压入堆栈的多余内容;
将当前任务堆栈指针保存到当前任务的OS_TCB中:
OSTCBCur->OSTCBStkPtr= 堆栈指针;
调用用户定义的OSTaskSwHook();
OSTCBCur=OSTCBHighRdy;
OSPrioCur=OSPrioHighRdy;
得到需要恢复的任务的堆栈指针:
堆栈指针 =OSTCBHighRdy->OSTCBStkPtr;
将所有处理器寄存器从新任务的堆栈中恢复出来;
执行中断返回指令;
}
OSIntCtxSw()是μC/OS-Ⅱ(和μC/OS)中唯一的与编译器相关的函数;在我收到的e-mail中,关于该函数的e-mail明显多于关于μC/OS其它方面的。如果在多次任务切换后用户的系统崩溃了,用户应该怀疑堆栈指针在OSIntCtxSw()中是否被正确地调整了。
8.04.04OSTickISR()
μC/OS-Ⅱ要求用户提供一个时钟资源来实现时间的延时和期满功能。时钟节拍应该每秒钟
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
