微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-II在80x86上的移植

μC/OS-II在80x86上的移植

时间:10-08 来源:互联网 点击:

μC/OS-II要求在中断服务程序开头调用OSIntEnter(), 其作用是将记录中断嵌套层数的全局

变量OSIntNesting加1。如果不调用OSIntEnter(),直接将OSIntNesting加1也是允许的。接下来计数器OSTickDOSCtr减1[程序清单L9.6(3)],每发生11次中断,OSTickDOSCtr减到0,则调用DOS的时钟中断处理函数[程序清单L9.6(4)],调用间隔大约是54.93ms。如果不调用DOS时钟中断函数,则向中断优先级控制器(PIC)发送命令清除中断标志。如果调用了DOS中断,则此项操作可免,因为在DOS的中断程序中已经完成了。随后,OSTickISR()调用OSTimeTick(),检查所有处于延时等待状态的任务,判断是否有延时结束就绪的任务[程序清单L9.6(6)]。 在OSTickISR()的最后调用OSIntExit(), 如果在中断中 (或其他嵌套的中断)有更高优先级的任务就绪,并且当前中断为中断嵌套的最后一层。OSIntExit()将进行任务调度。注意如果进行了任务调度,OSIntExit()将不再返回调用者,而是用新任务的堆栈中的寄存器数值恢复CPU现场,然后用IRET实现任务切换。如果当前中断不是中断嵌套的最后一层,或中断中没有改变任务的就绪状态,OSIntExit()将返回调用者OSTickISR(),最后OSTickISR()返回被中断的任务。

程序清单L9.7给出了OSTickISR()的完整代码。

程序清单L 9.6 OSTickISR()伪码.

voidOSTickISR(void)

{

Saveprocessorregisters;(1)

OSIntNesting++;(2)

OSTickDOSCtr—-;(3)

if(OSTickDOSCtr==0){

ChainintoDOSbyexecutingan'INT81H'instruction;(4)

}else{

SendEOIcommandtoPIC(PriorityInterruptController);(5)

}

OSTimeTick();(6)

OSIntExit(); (7)

Restoreprocessorregisters;(8)

Executeareturnfrominterruptinstruction(IRET);(9)

}

程序清单L9.7 OSTickISR().

_OSTickISRPROCFAR

;

PUSHA; 保存被中断任务的CPU环境

PUSHES

PUSHDS

;

MOVAX,SEG_OSTickDOSCtr; 载入 DS

MOVDS,AX

;

INCBYTEPTR_OSIntNesting; 标示 uC/OS-II 进入中断

;

DECBYTEPTRDS:_OSTickDOSCtr

CMPBYTEPTRDS:_OSTickDOSCtr,0

JNESHORT_OSTickISR1; 每11个时钟节拍(18.206Hz)调用DOS时钟中断

;

MOVBYTEPTRDS:_OSTickDOSCtr,11

INT081H; 调用DOS时钟中断处理过程

JMPSHORT_OSTickISR2

_OSTickISR1:

MOVAL,20H; 向中断优先级控制器发送命令,清除标志位.

MOVDX,20H;

OUTDX,AL;

;

_OSTickISR2:

CALLFARPTR_OSTimeTick; 调用OSTimeTick()函数

;

CALLFARPTR_OSIntExit; 标示uC/OS-II退出中断

;

POPDS; 恢复被中断任务的CPU环境

POPES

POPA

;

IRET; 返回被中断任务

;

_OSTickISRENDP

如果不更改DOS下的时钟中断频率(保持18.20648Hz),OSTickISR()函数还可以简化。程序清单L9.8为18.2Hz的OSTickISR()函数的伪码。同样,函数开头要保存所有的CPU寄存器[程序清单L9.8(1)],将OSIntNesting加1[程序清单L9.8(2)]。接下来调用DOS的时钟中断处理过程[程序清单L9.8(3)],此处就不需要清除中断优先级控制器的操作了,因为DOS的时钟中断处理中包含了这一过程。然后调用OSTimeTick()检查任务的延时是否结束[程序清单L9.8(4)], 最后调用OSInt Exit()[程序清单L9.8(5)]。 结束部分是恢复CPU寄存器的内容[程序清单L9.8(6)],执行IRET指令返回被中断的任务。如果采用8.2Hz的OSTickISR()函数,系统初始化过程就不用调用PC_SetTickRate(),同时将文件OS_CFG.H中的常量OS_TICKS_PER_SEC由200改为18。

程序清单L9.9给出了18.2HzOSTickISR()的完整代码。

程序清单L9.818.2Hz OSTickISR()伪码.

voidOSTickISR(void)

{

Saveprocessorregisters;(1)

OSIntNesting++;(2)

ChainintoDOSbyexecutingan'INT81H'instruction;(3)

OSTimeTick();(4)

OSIntExit(); (5)

Restoreprocessorregisters;(6)

Executeareturnfrominterruptinstruction(IRET);(7)

}

9.05 OS_CPU_C.C

μC/OS-II的移植需要用户改写OS_CPU_C.C中的六个函数:

OSTaskStkInit()

OSTaskCreateHook()

OSTaskDelHook()

OSTaskSwHook()

OSTaskStatHook()

OSTimeTickHook()

实际需要修改的只有OSTaskStkInit()函数,其他五个函数需要声明,但不一定有实际内容。这五个函数都是用户定义的,所以OS_CPU_C.C中没有给出代码。如果用户需要使用这些函数,请将文件OS_CFG.H中的#define constant OS_CPU_HOOKS_EN设为1,设为0表示不使用这些函数。

程序清单L 9.9 18.2Hz 的OSTickISR()函数.

_OSTickISRPROCFAR

;

PUSHA; 保存被中断任务的CPU环境

PUSHES

PUSHDS

;

MOVAX,SEG_OSIntNesting;载入 DS

MOVDS,AX

;

INCBYTEPTR_OSIntNesting;标示uC/OS-II进入中断

;

INT081H; 调用DOS的

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top