在MC68HC908GP32上移植μC/OS-II
OSCtxSw()是一个任务级的任务切换函数(在任务中调用,区别于在中断程序中调用的OSIntCtxSw())。在GP32上实现,可通过执行一条软中断指令SWI来实现任务切换。软中断向量指向OSCtxSw()。在 μC/OS-II中,如果任务调用了某个函数,而该函数的执行结果可能造成系统任务新调度(例如试图唤醒一个优先级更高的任务),则在函数的末尾会调用 OSSched();如果OSSched()将查找当前就绪的优先级最高的任务,若不是当前任务,则判断是否需要进行任务调度,并找到该任务控制块 OS_TCB的地址,将该地址拷贝到变量OSTCBHighRdy中,然后通过宏OS_TASK_SW()执行软中断进行任务切换。在此过程中,变量 OSTCBCur始终包含一个指向当前运行任务OS_TCB的指针。OSCtxSw()的汇编代码如下:
Void OSCtxSw(void)
{asm
{pshh //保存X寄存器
tsx
pshx
pshh
dx OSTCBCur //载入当前任务的TCB指针
pshx
ldx OSTCBCur:1 //载入TCB的第二个字节
pulh
pula
sta 0,x //保存当前堆栈指针
pula
sta 1,x
jsr OSTaskSwHook //调用用户定义的接口函数
lda OSPrioHighRdy //设置OSPrioCur=OSPrioHighRdy
sta OSPrioCur
pshx
ldx OSTCBHighRdy:1
stx OSTCBCur:1
pulh
lda 0,x //载入堆栈指针
psha
ldx,1,x
pulh
txs
pulh //恢复索引寄存器内容
rti //中断返回,切换任务
}}
(4)OSTickISR()函数
在μC/OS-II中,当调用OSStart()启动多任务环境后,时钟中断的使用是非常重要的。在时钟中断程序中负责处理所有与定时相关的工作,如任务的延时、等待操作等等。在时钟中断中将查询处于等待状态的任务,判断是否延时结束,否则将重新进行任务调度。
为GP32编写的函数OSTickISR()的代码如下:
void OSTickISR()void{
asm{
pshh
LDA T1SC
BCLR 7,T1SC //允许中断嵌套
}
OsintEnter(); /*标志进入中断*/
OSTimeTick(); /*调用时钟节拍函数*/
OSlntExit(); /*标志退出中断*/
Asm{
Pulh
Rti
}}
和μC/OS-II中的其他中断服务程序一样,OSTickISR()首先在被中断任务堆栈中保存CPU寄存器的值,然后调用OSIntEnter()。μC/OS-II要求在中断服务程序开头调用OSIntEnter(),其作用是将记录中断嵌套层数的全局变量OSIntNesting加1。如果不调用OSIntEnter(),直接将OSIntNesting加1也是允许的。随后,OSTickISR()调用OSTimeTick(),检查所有处于延时等待状态的任务,判断是否有延时结束就绪的任务。在OSTickISR()的最后调用OSIntExit(),如果在中断中(或其他嵌套的中断)有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层,OSIntExit() 将进行任务调度。注意:如果进行了任务调度,OSIntExit()将不同志返回调用者,而是用新任务的堆栈中的寄存器数值恢复CPU现场,然后用 IRET实现任务切换。如果当有中断不是中断嵌套的最后一层,或中断中没有改变任务的就绪状态,OSIntExit()将返回调用者 OSTickISR(),最后OSTickISR()返回被中断的任务。
4.OS_CPU08.C文件
μC/OS-II的移植需要用户在OS_CPU08.C中定义6个函数:
OSTaskStkInit()
OSTaskCreateHook()
OSTaskDelHook()
OSTaskSwHook()
OSTaskStatHook()
OSTimeTickHook()
实际需要定义的只有OSTaskStkInit()函数,其他5个函数需要声明,但不一定有实际内容。这5个函数都是用户定义,所以OS_CPU08.C中只有定义,没有给出代码。如果用户需要使用这些函数,请将文件OS_CFG.H中的#define constant OS_CPU_HOOKS_EN设为1,设为0表示不使用这些函数。
OSTaskStkInit()函数由任务创建函数 OSTaskCreate()或OSTaskCreateExt()调用,用来初始化任务的堆栈。初始状态的堆栈模拟发生一次中断后的堆栈结构,按照中断后的进栈次序预留各个寄存器存储空间;而中断返回地址指向任务代码的起始地址。当调用OSTaskCreate()或OSTaskCreateExt()创建一个新任务时,需要传递的参数是:任务代码的起始地址、参数指针(pdata)、任务堆栈顶端的地址、任务的优先级。 OSTaskCreateExt()还需要一些其他参数,但与OSTaskStkinit()没有关系。OSTaskStkInit()只需要以上提到的 3个参数(task、pdata和ptos)。堆栈初始化工作结束后,OSTaskStkInit()返回新的堆栈栈顶指针,OSTaskCreate()OSTaskCreateExt()将指针保存在任务的OS_TCB中。
Void*OSTaskStklint(void(*task)(void*pd),void*pdata,void*ptos,INT16U opt)
{
INT16U *stk;
stk=(INT16U*)ptos; /*保存堆栈指针*/
*--stk=(INT16U)(task); /保存程序计数器内容*/
*--stk=(INT16U)(0x00); /初始化X和A寄存器内容*/
--stk=(INT16U)(0x00); /*初始化CCR和H寄存器*/
return((void*)stk);
}
其余的几个函数:OSTas
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
