MicroC/OS-II在80C196上的移植实现
为80C196定义OS_ENTER_CRITICAL和OS_EXIT_CRITICAL如下:
// 中断禁止函数
#define OS_ENTER_CRITICAL() asm DI
// 中断使能函数
#define OS_EXIT_CRITICAL() asm EI
3.4 其他代码实现
3.4.1 任务堆栈初始化函数
任务堆栈初始化函数代码如下:
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
… …
stk = (OS_STK*)ptos;
*--stk = (OS_STK)task; // 任务开始地址
*--stk = (OS_STK)0x0000|gimask; // PSW IMASK
*--stk = (OS_STK)0x0000|gimask1;// IMASK1 WSR
*--stk = (OS_STK)4; // DX
*--stk = (OS_STK)3; // CX
*--stk = (OS_STK)2; // BX
*--stk = (OS_STK)1; // AX
return ((OS_STK *)stk);
}
3.4.2 开始运行最高优先级就绪任务
系统开始运行时,调用该函数,以开始运行,其实现代码如下:
void OSStartHighRdy(void)
{
OSRunning = TRUE; // 置系统正在运行标志
… …
OSTCBCur = OSTCBHighRdy; // 置当前TCB为最高优先级就绪任务的TCB
psp = OSTCBHighRdy->OSTCBStkPtr; // 取得堆栈指针
asm{ // 恢复现场
pop dx; pop cx; pop bx; pop ax; popa; // 转到新任务
}
}
3.4.3 现场切换函数
OS_Sched函数调用该函数实现真正的任务切换。
void OSCtxSw(void)
{
asm{ // 保存被中断任务的现场
pusha; push ax; push bx; push cx; push dx;
}
OSTCBCur->OSTCBStkPtr = psp; // 存储被中断任务的堆栈指针
OSTCBCur = OSTCBPrioTbl[OSPrioHighRdy]; // 取得最高优先级就绪任务的TCB
OSPrioCur = OSPrioHighRdy; // 设当前任务优先级为最高优先级就绪任务的优先级
psp = OSTCBCur->OSTCBStkPtr; // 取得堆栈指针
asm{ // 现场恢复
pop dx; pop cx; pop bx; pop ax; popa;
}
}
4. 注意事项
在实现过程中的得到如下经验教训:
1) 尽量减少任务的数量,以减少系统额外开销。相对少的任务数,可以减少,系统花在任务切换上的时间。
2) 合理分配各个任务的优先级。
3) 注意开中断、关中断的时机。
4) 注意入栈和出栈要匹配。如果堆栈指针出现错位,将会出现灾难性后果。特别注意中断服务函数的处理,其调用时的入栈内容和退出中断的出栈内容要对应,而中断退出有两种可能:正常退出和任务切换。
5) 合理选择定时器时间周期。
6) 同类型工作,也同样需要有优先级区分。例如:同样是通信任务,接收数据需要较高的优先级,而通信故障处理需要较低的优先级。一般情况下,通信处理都有一定的故障容忍时间,只要在容忍时间内得到处理就可以了。如果发生不可恢复性错误,故障处理将会占用大量的时间,如果在较高优先级,将会影响整个系统的性能。
5. 结论
通过在80C196上移植实现MicroC/OS-II,达到了不改变硬件设计,增加应用功能,提高了应用系统性能的目的。在嵌入式系统中使用嵌入式实时操作系统,不但可以提高系统的实时性、可靠性和稳定性,还可以提高应用软件的可移植性和可维护性,降低开发人员的工作量。因此,只要硬件环境允许,应尽量采用实时操作系统。
参考文献:
1. Jean J.Labrosse 著,邵贝贝等译,《嵌入式实时操作系统 μC/OS-II(第二版)》,北京航空航天大学出版社,2003年5月 第1版
2. 孙涵芳主编,《Intel 16位单片机》,北京航空航天大学出版社,1995年11月 第1版