移植μC/OS-Ⅱ
在μC/OS-Ⅱ中,处于就绪状态的任务的堆栈结构看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。换句话说,μC/OS-Ⅱ要运行处于就绪状态的任务必须要做的事就是将所有处理器寄存器从任务堆栈中恢复出来,并且执行中断的返回。为了切换任务可以通过执行OS_TASK_SW()来产生中断。大部分的处理器会提供软中断或是陷阱(TRAP)指令来完成这个功能。ISR或是陷阱处理函数(也叫做异常处理函数)的向量地址必须指向汇编语言函数OSCtxSw()(参看8.04.02)。
例如,在Intel或者AMD80x86处理器上可以使用INT指令。但是中断处理向量需要指向OSCtxSw()。Motorola68HC11处理器使用的是SWI指令,同样,SWI的向量地址仍是OSCtxSw()。还有,Motorola680x0/CPU32可能会使用16个陷阱指令中的一个。当然,选中的陷阱向量地址还是OSCtxSw()。
一些处理器如ZilogZ80并不提供软中断机制。在这种情况下,用户需要尽自己的所能将堆栈结构设置成与中断堆栈结构一样。OS_TASK_SW()只会简单的调用OSCtxSw()而不是将某个向量指向OSCtxSw()。μC/OS已经被移植到了Z80处理器上,μC/OS-Ⅱ也同样可以。
8.04OS_CPU_A.ASM
μC/OS-Ⅱ的移植实例要求用户编写四个简单的汇编语言函数:
OSStartHighRdy()
OSCtxSw()
OSIntCtxSw()
OSTickISR()
如果用户的编译器支持插入汇编语言代码的话, 用户就可以将所有与处理器相关的代码放到OS_CPU_C.C文件中,而不必再拥有一些分散的汇编语言文件。
8.04.01OSStartHighRdy()
使就绪状态的任务开始运行的函数叫做OSStart(),如下所示。在用户调用OSStart()之前,用户必须至少已经建立了自己的一个任务(参看OSTaskCreate()和OSTaskCteateExt())。OSStartHighRdy()假设OSTCBHighRdy指向的是优先级最高的任务的任务控制块。前面曾提到过,在μC/OS-Ⅱ中处于就绪状态的任务的堆栈结构看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。要想运行最高优先级任务,用户所要做的是将所有处理器寄存器按顺序从任务堆栈中恢复出来,并且执行中断的返回。为了简单一点,堆栈指针总是储存在任务控制块(即它的OS_TCB)的开头。换句话说,也就是要想恢复的任务堆栈指针总是储存在OS_TCB的0偏址内存单元中。
voidOSStartHighRdy(void)
{
CalluserdefinableOSTaskSwHook();
Getthestackpointerofthetasktoresume:
Stackpointer=OSTCBHighRdy->OSTCBStkPtr;
OSRunning=TRUE;
Restoreallprocessorregistersfromthenewtask'sstack;
Executeareturnfrominterruptinstruction;
}
注意,OSStartHighRdy()必须调用OSTaskSwHook(),因为用户正在进行任务切换的部分工作——用户在恢复最高优先级任务的寄存器。而OSTaskSwHook()可以通过检查OSRunning来知道是OSStartHighRdy()在调用它(OSRunning为FALSE)还是正常的任务切换在调用它(OSRunning为TRUE).
OSStartHighRdy()还必须在最高优先级任务恢复之前和调用OSTaskSwHook()之后设置OSRunning为TRUE。
8.04.02OSCtxSw()
如前面所述, 任务级的切换问题是通过发软中断命令或依靠处理器执行陷阱指令来完成的。中断服务例程,陷阱或异常处理例程的向量地址必须指向OSCtxSw()。
如果当前任务调用μC/OS-Ⅱ提供的系统服务,并使得更高优先级任务处于就绪状态,μC/OS-Ⅱ就会借助上面提到的向量地址找到OSCtxSw()。在系统服务调用的最后,μC/OS-Ⅱ会调用OSSched(),并由此来推断当前任务不再是要运行的最重要的任务了。OSSched()先将最高优先级任务的地址装载到OSTCBHighRdy中,再通过调用OS_TASK_SW()来执行软中断或陷阱指令。注意,变量OSTCBCur早就包含了指向当前任务的任务控制块(OS_TCB)的指针。 软中断(或陷阱)指令会强制一些处理器寄存器(比如返回地址和处理器状态字)到当前任务的堆栈中,并使处理器执行OSCtxSw()。OSCtxSw()的原型如程序清单L8.2所示。这些代码必须写在汇编语言中,因为用户不能直接从C中访问CPU寄存器。注意在OSCtxSw()和用户定义的函数OSTaskSwHook()的执行过程中,中断是禁止的。
程序清单 L8.2 OSCtxSw()的原型
voidOSCtxSw(void)
{
保存处理器寄存器;
将当前任务的堆栈指针保存到当前任务的OS_TCB中:
OSTCBCur->OSTCBStkPtr=Stackpointer;
调用用户定义的OSTaskSwHook();
OSTCBCur=OSTCBHighRdy;
OSPrioCur=OSPrioHighRdy;
得到需要恢复的任务的堆栈指针:
Stackpointer=OSTCBHighRdy->OSTCBStkPtr;
将所有处理器寄存器从新任务的堆栈中恢复出来;
执行中断返回指令;
}
8.04.03OSIntCtxSw()
OSIntExit()
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
