0519

OSTickISR()

  1. 在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前后的中断向量表。  
  2. 在µC/OS-II中,当调用OSStart()启动多任务环境后,时钟中断的作用是非常重要的。但在PC环境下,启动µC/OS-II之前就已经有时钟中断发生了,实际上我们希望在µC/OS-II初始化完成之后再发生时钟中断,调用OSTickISR()。与此相关的有下述过程:  
  3.   
  4. PC_DOSSaveReturn() 函数(参看PC.C):该函数由main()调用,任务是取得DOS下时钟中断向量,并将其保存在0x81中。  
  5.   
  6. main() 函数:  
  7.     设定中断向量0x80指向任务切换函数OSCtxSw()  
  8.     至少创立一个任务  
  9.     当初始化工作完成后调用OSStart()启动多任务环境  
  10.   
  11. 第一个运行的任务:  
  12. 设定中断向量0x08指向函数OSTickISR()  
  13. 将时钟节拍频率从18.20648改为200Hz  

  1. 在程序清单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()返回被中断的任务。  
  2. 程序清单L9.7给出了OSTickISR()的完整代码。  
  3.   
  4. 程序清单L 9.6   OSTickISR()伪码.  
  5. void OSTickISR (void)  
  6. {  
  7.     Save processor registers;   (1)  
  8.     OSIntNesting++; (2)  
  9.     OSTickDOSCtr—-; (3)  
  10.     if (OSTickDOSCtr == 0) {  
  11.         Chain into DOS by executing an 'INT 81H' instruction;   (4)  
  12.     } else {  
  13.         Send EOI command to PIC (Priority Interrupt Controller);    (5)  
  14.     }  
  15.     OSTimeTick();   (6)  
  16.     OSIntExit();    (7)  
  17.     Restore processor registers;    (8)  
  18.     Execute a return from interrupt instruction (IRET); (9)  
  19. }  
  20.   
  21. 程序清单L9.7    OSTickISR().  
  22. _OSTickISR  PROC   FAR  
  23. ;  
  24.     PUSHA                          ; 保存被中断任务的CPU环境  
  25.     PUSH ES  
  26.     PUSH DS  
  27. ;  
  28.     MOV  AX, SEG _OSTickDOSCtr     ; 载入 DS   
  29.     MOV  DS, AX  
  30. ;  
  31.     INC  BYTE PTR _OSIntNesting    ; 标示 uC/OS-II 进入中断  
  32. ;  
  33.     DEC  BYTE PTR DS:_OSTickDOSCtr  
  34.     CMP  BYTE PTR DS:_OSTickDOSCtr, 0  
  35.     JNE  SHORT _OSTickISR1         ; 每11个时钟节拍(18.206 Hz)调用DOS时钟中断  
  36. ;  
  37.     MOV  BYTE PTR DS:_OSTickDOSCtr, 11  
  38.     INT  081H                      ; 调用DOS时钟中断处理过程  
  39.     JMP  SHORT _OSTickISR2  
  40.   
  41. _OSTickISR1:  
  42.     MOV  AL, 20H                   ; 向中断优先级控制器发送命令,清除标志位.  
  43.     MOV  DX, 20H                   ;  
  44.     OUT  DX, AL                    ;   
  45. ;  
  46. _OSTickISR2:  
  47.     CALL FAR PTR _OSTimeTick       ; 调用OSTimeTick()函数  
  48. ;  
  49.     CALL FAR PTR _OSIntExit        ; 标示uC/OS-II退出中断  
  50. ;  
  51.     POP  DS                        ; 恢复被中断任务的CPU环境  
  52.     POP  ES  
  53.     POPA  
  54. ;  
  55.     IRET                           ; 返回被中断任务  
  56. ;  
  57. _OSTickISR  ENDP  
  58.   
  59. 如果不更改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。  
  60. 程序清单L9.9给出了18.2 Hz OSTickISR()的完整代码。  
  61.   
  62. 程序清单L 9.8   18.2Hz OSTickISR()伪码.  
  63. void OSTickISR (void)  
  64. {  
  65.     Save processor registers;   (1)  
  66.     OSIntNesting++; (2)  
  67.     Chain into DOS by executing an 'INT 81H' instruction;   (3)  
  68.     OSTimeTick();   (4)  
  69.     OSIntExit();    (5)  
  70.     Restore processor registers;    (6)  
  71.     Execute a return from interrupt instruction (IRET); (7)  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值