μC/OS-II在80x86上的移植
1)]。此后,用户必须调用OSIntEnter()或着把全局变量OSIntNesting加1。
此时,被中断任务的堆栈中保存了任务的全部运行环境。在中断服务程序中,有可能引起任务
就绪状态的改变而需要任务切换,例如调用了OSMboxPost(),OSQPostFront(),OSQPost(),或试
图唤醒一个优先级更高的任务(调用OSTaskResume()),还可能调用OSTimeTick(),
OSTimeDlyResume()等等。
μC/OS-II要求用户在中断服务程序的末尾调用OSInt Exit(),以检查任务就绪状态。在调用
OSInt Exit()后,返回地址会压入堆栈中[图F9.5(2)]。
进入OSIntExit()后,由于要访问临界代码区,首先关闭中断。由于OS_ENTER_CRITICAL()可
能有不同的操作(见9.03.02节),状态寄存器SW的内容有可能被压入堆栈[图F9.5(3)]。如果
确实要进行任务切换,指针OSTCBHighRdy将指向新的就绪任务的OS_TCB,OSIntExit()会调用
OSIntCtxSw()完成任务切换。注意,调用OSIntCtxSw()会在再一次在堆栈中保存返回地址[图
F9.5(4)]。在进行任务切换的时候,我们希望堆栈中只保留一次中断发生的任务环境(如图
F9.5(1)),而忽略掉由于函数嵌套调用而压入的一系列返回地址(图F9.5(2),(3),(4))。忽
略的方法也很简单,只要把堆栈指针加一个固定的值就可以了[图F9.5(5)/程序清单L9.5(1)]。
如果用方法2实现OS_ENTER_CRITICAL(),这个固定值是10;如果用方法1,则是8。实际操作中
还与编译器以及编译模式有关。例如,有些编译器会为OSIntExit()在堆栈中分配临时变量,这
都会影响具体占用堆栈的大小,这一点需要提醒用户注意。
一但堆栈指针重新定位后,就被保存到将要被挂起的任务OS_TCB中[图F9.5(6)/程序清单
L9.5(2)]。在μC/OS-II中(包括μC/OS),OSIntCtxSw()是唯一一个与编译器相关的函数,也是
用户问的最多的。如果您的系统移植后运行一段时间后就会死机,就应该怀疑是OSIntCtxSw()
中堆栈指针重新定位的问题。
当当前任务的现场保存完毕后,用户定义的对外接口函数OSTaskSwHook()会被调用[程序清
单L9.5(3)]。注意到OSTCBCur指向当前任务的OS_TCB,OSTCBHighRdy指向新任务的OS_TCB。在
函数OSTaskSwHook()中用户可以访问这两个任务的OS_TCB。如果不用对外接口函数,请在头文
件中关闭相应的开关选项,提高任务切换的速度。
从对外接口函数OSTaskSwHook()返回后,由于任务的更替,变量OSTCBHighRdy被拷贝到
OSTCBCur中[程序清单L9.5(4)],同样,OSPrioHighRdy被拷贝到OSPrioCur中[程序清单
L9.5(5)]。此时,OSIntCtxSw()将载入新任务的CPU环境,首先从新任务OS_TCB中取出SS和SP寄
存器的值[图F9.5(7)/程序清单L9.5(6)],然后运行POPDS[图F9.5(8)/程序清单L9.5(7)],
POPES[图F9.5(9)/程序清单L9.5(8)],POPA[图F9.5(10)/程序清单L9.5(9)]取出其他寄存器
的值,最后用中断返回指令IRET[图F9.5(11)/程序清单L9.5(10)]完成任务切换。
需要注意的是在运行OSIntCtxSw()和用户定义的OSTaskSwHook()函数期间,中断是禁止的。
9.04.04 OSTickISR()
在9.03.05节中,我们已经提到过实时系统中时钟节拍发生频率的问题,应该在10到100Hz
之间。但由于PC环境的特殊性,时钟节拍由硬件产生,间隔54.93ms(18.20648Hz)。我们将时
钟节拍频率设为200Hz。PC时钟节拍的中断向量为0x08,μC/OS-II将此向量截取,指向了μC/OS
的中断服务函数OSTickISR(),而原先的中断向量保存在中断129(0x81)中。为满足DOS的需要,
原先的中断服务还是每隔54.93ms(实际上还要短些)调用一次。图F9.6为安装μC/OS-II前后的
中断向量表。
在μC/OS-II中, 当调用OSStart()启动多任务环境后, 时钟中断的作用是非常重要的。 但在PC
环境下,启动μC/OS-II之前就已经有时钟中断发生了,实际上我们希望在μC/OS-II初始化完成之后再发生时钟中断,调用OSTickISR()。与此相关的有下述过程:
PC_DOSSaveReturn()函数(参看PC.C):该函数由main()调用,任务是取得DOS下时钟中断向量,并将其保存在0x81中。
main()函数:
设定中断向量0x80指向任务切换函数OSCtxSw()
至少创立一个任务
当初始化工作完成后调用OSStart()启动多任务环境
第一个运行的任务:
设定中断向量0x08指向函数OSTickISR()
将时钟节拍频率从18.20648改为200Hz
图F9.6 PC 中断向量表(IVT).

在程序清单L9.6给出了函数OSTickISR()的伪码。和μC/OS-II中的其他中断服务程序一样,OSTickISR()首先在被中断任务堆栈中保存CPU寄存器的值,然后调用OSIntEnter()。
μC/OS-II要求在中断服务程序开头调用OSIntEnter(), 其作用是将记录中断嵌
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
