- 在程序清单L9.6给出了函数OSTickISR()的伪码。和µC/OS-II中的其他中断服务程序一样,OSTickISR()首先在被中断任务堆栈中保存CPU寄存器的值,然后调用OSIntEnter()。µ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()伪码.
- void OSTickISR (void)
- {
- Save processor registers; (1)
- OSIntNesting++; (2)
- OSTickDOSCtr—-; (3)
- if (OSTickDOSCtr == 0) {
- Chain into DOS by executing an 'INT 81H' instruction; (4)
- } else {
- Send EOI command to PIC (Priority Interrupt Controller); (5)
- }
- OSTimeTick(); (6)
- OSIntExit(); (7)
- Restore processor registers; (8)
- Execute a return from interrupt instruction (IRET); (9)
- }
- 程序清单L9.7 OSTickISR().
- _OSTickISR PROC FAR
- ;
- PUSHA ; 保存被中断任务的CPU环境
- PUSH ES
- PUSH DS
- ;
- MOV AX, SEG _OSTickDOSCtr ; 载入 DS
- MOV DS, AX
- ;
- INC BYTE PTR _OSIntNesting ; 标示 uC/OS-II 进入中断
- ;
- DEC BYTE PTR DS:_OSTickDOSCtr
- CMP BYTE PTR DS:_OSTickDOSCtr, 0
- JNE SHORT _OSTickISR1 ; 每11个时钟节拍(18.206 Hz)调用DOS时钟中断
- ;
- MOV BYTE PTR DS:_OSTickDOSCtr, 11
- INT 081H ; 调用DOS时钟中断处理过程
- JMP SHORT _OSTickISR2
- _OSTickISR1:
- MOV AL, 20H ; 向中断优先级控制器发送命令,清除标志位.
- MOV DX, 20H ;
- OUT DX, AL ;
- ;
- _OSTickISR2:
- CALL FAR PTR _OSTimeTick ; 调用OSTimeTick()函数
- ;
- CALL FAR PTR _OSIntExit ; 标示uC/OS-II退出中断
- ;
- POP DS ; 恢复被中断任务的CPU环境
- POP ES
- POPA
- ;
- IRET ; 返回被中断任务
- ;
- _OSTickISR ENDP
- 如果不更改DOS下的时钟中断频率(保持18.20648 Hz),OSTickISR()函数还可以简化。程序清单L9.8为18.2 Hz的OSTickISR()函数的伪码。同样,函数开头要保存所有的CPU寄存器[程序清单L9.8(1)],将OSIntNesting加1[程序清单L9.8(2)]。接下来调用DOS的时钟中断处理过程[程序清单L9.8(3)],此处就不需要清除中断优先级控制器的操作了,因为DOS的时钟中断处理中包含了这一过程。然后调用OSTimeTick()检查任务的延时是否结束[程序清单L9.8(4)],最后调用OSIntExit()[程序清单L9.8(5)]。结束部分是恢复CPU寄存器的内容[程序清单L9.8(6)],执行IRET指令返回被中断的任务。如果采用8.2 Hz的OSTickISR()函数,系统初始化过程就不用调用PC_SetTickRate(),同时将文件OS_CFG.H中的常量OS_TICKS_PER_SEC由200改为18。
- 程序清单L9.9给出了18.2 Hz OSTickISR()的完整代码。
- 程序清单L 9.8 18.2Hz OSTickISR()伪码.
- void OSTickISR (void)
- {
- Save processor registers; (1)
- OSIntNesting++; (2)
- Chain into DOS by executing an 'INT 81H' instruction; (3)
- OSTimeTick(); (4)
- OSIntExit(); (5)
- Restore processor registers; (6)
- Execute a return from interrupt instruction (IRET); (7)
- }
相关文章: