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
在程序清单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)
}


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编辑推荐 本书主要特点: 分为原理篇和应用篇,原理与实践相结合,两篇相对独立,又紧密联系。 原理篇以分析源码为特色,深入浅出地介绍RTOS的基本概念以及Small RTOS51的工作原理。 应用篇以DP-51单片综合仿真实验仪为硬件平台,通过对单片机常用和热门外围器件实用驱动程序的分析,详细介绍基于Small RTOS51的编程方法,以及如何为这些外围器件编写中间件,并给出一个完整的例子,让读者全面掌握基于Small RTOS51的编程方法,体会了RTOS下编程的优点。 内容简介 Small RTOS51是为51系列单片机而编写的。它是完全免费的、源代码公开的多任务实时操作系统。它可在无任何外部数据存储器的单片80C51系统上运行,并且是可移植的。全书分两部分。第一部分为基础篇,介绍Small RTOS51和一些基本概念,并详细分析Small RTOS51的工作原理。第二部分为应用篇,给出部分常用硬件在Small RTOS51下驱动程序的源代码。这些源代码在DP—51单片机仿真实验仪上全部调试通过,且只要经过很少的改动,或是不改动,就可以在其他环境下使用。应用篇还通过对这些源代码的分析,让读者理解基于RTOS的编程方法,并给出完整的例子让读者全面掌握基于RTOS的编程方法。 本书可以作为高等院校相关专业的课程教材、实验参考资料或课外读物,对嵌入工应用开发人员也有重要的参考价值。 目录 第一部分 原理篇 第0章 绪论 第1章 Small RTOS51简介 1.1 Small RTOS51的特点 1.2 Small RTOS51的运行条件 1.3 Small RTOS51的存储器需求 1.4 Small RTOS51的任务堆栈的计算 1.5 关于可重入功能 1.6 关于C51的库函数 1.7 关于51系列单片机派生类型的多数据指针和数学单元 1.8 关于51系列单片机的寄存器段 1.9 关于局部变量 第2章 基本概念 2.1 嵌入式系统 2.2 实时系统 2.3 前、后台系统 2.4 操作系统 2.5 实时操作系统 2.6 代码的临界区 2.7 资源 2.8 共享资源 2.9 任务 2.10 任务切换 2.11 内核 2.12 调度 2.13 非占先式内核 2.14 占先式内核 2.15 可重入性 2.16 任务优先级 2.17 信号量 2.18 死锁 2.19 消息队列 2.20 中断 2.21 时钟节拍 第3章 一个简单的例子 3.1 Small RTOS51的安装及目录结构 3.2 例子简介 3.3 Config、h、Os_cfg、h和Os_cpu.h 3.4 与编程器无关的数据类型 3.5 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL() 3.6 main()函数 3.7 建立任务 3.8 删除任务 3.9 用户任务 3.10 软非屏蔽中断 3.11 中断服务程序的编写 3.12 Os_cpu.h可改变的其他内容 3.13 Small RTOS51的其他注意事项 第4章 任务管理—核心的核心 4.1 临界区 4.2 任务 4.3 任务状态 4.4 与任务相关的数据结构 4.5 任务调度 4.6 Small RTOS51中的中断处理 4.7 时钟节拍 4.8 Small RTOS51初始化和启动 4.9 建立任务 4.10 任务堆栈 4.11 删除任务 4.12 时间服务及任务的挂起和恢复 4.13 获取当前Small RTOS51的版本号 4.14 OSInt…()函数 第5章 如何切换任务 5.1 CPU可以执行多个任务的原因 5.2 CPU怎样运行才能执行多个任务 5.3 何时进行任务切换 5.4 Small RTOS51任务切换时的程序框图 5.5 数组OSTsakStackBotton[]和Small RTOS51的堆栈结构 5.6 变量OSFastSwap 5.7 常量数值OSMapTb[] 5.8 软非屏蔽中断的堆栈SP2[] 5.9 中断切换函数OSIntCtxSw()OSIntCtxSw() 5.10 任务主动放弃CPU-OS_TASK_SW() 5.11 堆栈变换函数C_OSCtxSw() 5.12 恢复新任务环境LoadCtx() 5.13 优先级最低的任务OSIdle() 5.14 Small RTOS51初始化函数OSStart() 5.15 系统时钟节拍中断OSTickISR() 第6章 任务之间的通信和同步之信号量 6.1 概述 6.2 使Keil C51函数具有重入性的特殊方法 6.3 数据结构 6.4 IN_OS_SEM_CHK宏及相关代码 6.5 初始化一个信号量 6.6 等待一个信号量 6.7 发送一个信号量 6.8 无等待地请求一

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值