收藏 分享(赏)

μCOS-II的中断和时钟.ppt

上传人:dzzj200808 文档编号:3352398 上传时间:2018-10-17 格式:PPT 页数:28 大小:1.11MB
下载 相关 举报
μCOS-II的中断和时钟.ppt_第1页
第1页 / 共28页
μCOS-II的中断和时钟.ppt_第2页
第2页 / 共28页
μCOS-II的中断和时钟.ppt_第3页
第3页 / 共28页
μCOS-II的中断和时钟.ppt_第4页
第4页 / 共28页
μCOS-II的中断和时钟.ppt_第5页
第5页 / 共28页
点击查看更多>>
资源描述

1、,嵌入式实时操作系统 uC/OS-II的原理与应用,东软IT人才实训中心,Copyright 2008 By Neusoft Group. All rights reserved,第三章 uC/OS-II的中断和时钟,目标: 本章旨在向学员介绍uc/osII实时操作系统的中断概念及时间管理,通过本章的学习,学员应该掌握如下知识:uC/OS-II的中断管理和中断服务程序 的结构uC/OS-II的系统时钟及实现方法时间管理服务:延时、取消延时,学时:6.0学时教学方法:讲授ppt上机练习点评案例分析,3.1 uC/OS-II的中断,中断:任务在运行过程中,应内部或外部异步事件的请求中止当前任务,而

2、去处理异步事件所要求的任务的过程叫做中断。 中断服务程序:应中断请求而运行的程序叫中断服务子程序(ISR)。 中断向量:中断服务子程序的入口地址叫中断向量。CPU响应中断的条件: 至少有一个中断源向CPU发出中断信号 系统允许中断,且对此中断信号未予屏蔽,3.1.1 uC/OS-II的中断过程,uC/OS-II中断的响应过程:,中断请求,关闭中断,转到中断向量,保存CPU寄存器,通知内核进入ISR并开中断,通知内核退出ISR,恢复CPU寄存器,中断返回,无新高级任务则返回原任务,有新高级任务则运行高级任务,ISR给任务发信号,通知内核退出ISR,恢复CPU寄存器,中断返回,图3-1 中断的响应

3、过程,中断响应,中断恢复,任务响应时间,中断恢复,任务响应时间,注意:对于可剥夺型内核,中断服务子程序结束后,系统进行一次任务调度去运行优先级最高的就绪任务,而不是一定要接续运行被中断的任务。,void OSIntEnter(void) if (OSRunning = True)if(OSIntNesting 255)OSIntNesting+; ,3.1.2 中断的开始、离开,void OSIntExit(Void) OS_ENTER_CRITICAL();if(OSRunning = TRUE)if(OSIntNesting 0)OSIntNesting-; if (OSLockNesti

4、ng = 0) ,进入,中断嵌套层数=0?,获得任务TCB的指针,YES,NO,NO,返回中断服务程序,未锁定调度器?,NO,获得最高级别就绪任务的prio,任务是被中断的任务?,YES,YES,执行中断级任务切换,图3-2 函数OSIntExit()的流程图,为记录中断嵌套的层数,定义了一个全局变量OSIntNesting。,函数作用就是把全局变量OSIntNesting加1,从而用它来记录中断嵌套的层数,这个函数在中断嵌套层数计数器为0、调度器未被锁定且从任务就绪表中查找到的最高级就绪任务又不是被中断的任务的条件下将要进行任务切换,否则就返回被中断的服务程序,3.1.3 中断服务子程序的流

5、程,中断服务子程序入口,OSTCBCur-OSTCBStkPtr=SP,NO,中断嵌套层OSIntNEsting=1?,YES,清中断源的中断申请标志,图3-3 中断服务子程序的流程图,CPU寄存器内容进栈,调用OSIntEnter()通知系统:进入中断服务程序,重新开放中断,运行中断服务代码,调用OSIntExit()通知系统:退出中断服务程序,恢复CPU寄存器内容,执行中断返回指令,在uC/OS-II中,通常用一个任务来完成异步事件的处理工作,而在中断服务程序中只是向任务发送消息的方法去激活这个任务。,并非为每个任务都定义一个充分大的栈空间,中断嵌套时单独定义一个中断嵌套栈,在发生第1次中

6、断时,中断服务程序将栈空间切换到中断嵌套栈,这样,以后发生的嵌套中断就一直使用这个栈空间。,3.1.4 中断级任务切换,OSIntCtxSw() OSTCBCur = OSTCBHighRdy; / 任务控制块的切换OSPrioCur = OSPrioHighRdy; SP = OSPrioHighRdy-OSTCBStkPtr; / 使SP指向待运行任务堆栈用出栈指令把R1、R2弹入CPU的通用寄存器;RETI; / 中断返回,使PC指向待运行任务 ,与任务级切换函数OSCtxSW()的原因一样,中断级任务切换函数OSIntCtxSw()通常是用汇编语言来编写的:,3.1.5 临界段,在应用

7、程序中经常有一些代码段必须不受任何干扰地连续运行,这样的代码叫做临阶段。怎样保证临界段的安全?系统当有异步事件发生时会引发中断请求,CPU何时响应这个请求?需要的条件和策略?宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。,临界段的概念:,当处理临界段代码时,需要关中断,处理完毕后,再开中断; 关中断时间是实时内核重要的指标之一; 在实际应用中,关中断的时间很大程度中取决于微处理器的结构和编译器生成的代码质量; C/OS-II定义两个宏开关中断:OS_ENTER_CRITICAL(); OS_EXIT_CRITICAL();因为这2个宏的定义取决于所使用的微处理

8、器,因此在OS_CPU.H中可以找到相应的宏定义。 OS_CPU.H是微处理器相关的。,3.1.6 开关中断的宏,OS_CRITICAL_METHOD=1用处理器指令关中断执行OS_ENTER_CRITICAL(),关中断执行OS_EXIT_CRITICAL(),开中断;,方法1的示意性代码#define OS_ENTER_CRITICAL() asm(“DI”)#define OS_EXIT_CRITICAL() asm(“EI”),3.1.6.1开关中断的实现方法1,以上代码所列假定编译器允许直接在C代码行之间插入行汇编语句。,根据微处理器和C编译器的不同,通过在移植文件OS_CPU.H中

9、配置OS_CRITICAL_METHOD来选择开/关中断的方法:,方法2的示意性代码#define OS_ENTER_CRITICAL() asm(“PUSH PSW”) asm(“DI”)#define OS_EXIT_CRITICAL() asm(“POP PSW”),3.1.6.2 开关中断的实现方法2,一些编译器对插入的行汇编代码优化得并不好,上述办法未必可行,尤其是堆栈指针相对寻址模式时。,OS_CRITICAL_METHOD=2实现OS_ENTER_CRITICAL()时,先在堆栈中保存中断的开/关状态,然后再关中断;实现OS_EXIT_CRITICAL()时,从堆栈中弹出原来中断

10、的开/关状态;,第2种方法可使CPU中断允许标志的状态在临界段前和临阶段后不发生改变。,void Some_uCOS_II_Service(arguments) OS_CPU_SR cpu_srcpu_sr = get_processor_psw();disable_interrupts();/* 处理临界代码*/set_processor_psw(cpu_sr); ,方法3的示意性代码 #define OS_ENTER_CRITICAL() cpu_sr = get_processer_psw();disable_interrrupts();#define OS_EXIT_CRITICAL(

11、) set-processer_psw(cpu_sr);,3.1.6.3 开关中断的实现方法3,OS_CRITICAL_METHOD=3把当前处理器的状态字保存在局部变量中(如OS_CPU_SR),关中断时保存,开中断时恢复。这样需要在选择用这种方法进入临界代码的应用程序中定义一个局部变量cpu_sr。,第3种方法的前提条件:用户使用C编译器具有扩展功能,用户可获得程序状态字的值,这样就可以把该值保存在C语言函数的局部变量中,而不必压到堆栈里。,任何操作系统都要提供一个周期性的信号源,以供系统处理诸如延时、超时等与时间有关的事件,这个周期性的信号源叫做时钟。 硬件定时器产生一个周期为毫秒级的周

12、期性中断来实现系统时钟。最小的时钟单位就是两次中断之间间隔的时间,这个最小时钟单位叫做时钟节拍。 硬件定时器以时钟节拍为周期定时的产生中断,该中断的中断服务程序叫做OSTickISR(),中断服务程序通过调用函数OSTimeTick()来完成系统在每个时钟节拍时需要做的工作。,3.2 uC/OS-II的时钟,C/OS节拍率应选在10100次/秒。 必须在多任务系统启动OSStart()以后,再开启时钟节拍器。,3.2.1 时钟节拍中断服务子程序,程序清单 : 时钟节拍中断服务子程序的示意代码,因为使用C语言不便于对CPU的寄存器进行处理,所以这段代码使用汇编语言编写。,3.2.2 启动时钟节拍

13、不正确的做法,这里潜在的危险是,时钟节拍中断有可能在C/OS-启动第一个任务之前发生,此时C/OS-是处在一种不确定的状态之中,用户应用程序有可能会崩溃。,3.2.3 时钟节拍服务函数,void OSTimeTick (void) OS_TCB *ptcb;OSTimeTickHook(); #if OS_TIME_GET_SET_EN 0 OS_ENTER_CRITICAL(); OSTime+; / 记录节拍数OS_EXIT_CRITICAL();#endifif (OSRunning = TRUE) ptcb = OSTCBList; while (ptcb-OSTCBPrio != O

14、S_IDLE_PRIO) OS_ENTER_CRITICAL();if (ptcb-OSTCBDly != 0) if (-ptcb-OSTCBDly = 0) /任务的延时时间减1 if (ptcb-OSTCBStat ,OSTimeTick()做了两件事情: 1.给计数器OSTime加1; 2.遍历任务控制块链表中的所有任务控制块,把各个任务控制块中用来存放任务延时时限的OSTCBDly变量减1,并使该项为0;同时又不是被挂起的任务(即延时时间已到的任务)进入就绪态。,简单地说,函数OSTimeTick()的任务就是在每个时钟节拍了解每个任务的延时状态,使其中已经到了延时时限的非挂起任务进

15、入就绪状态。,例程3-1:,在例2-1应用程序的基础上,在OS_CPU.C文件中按如下代码定义函数OSTimeTickHook(),然后运行并查看运行结果。,INT16U d=0; INT16U d1=0;void OSTimeTickHook (void) char* s0 = “500”; char* s1 = “每”; char* s2 = “次中断的调度次数”;char s8; if(d = 500) PC_DispStr(14,4,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);PC_DispStr(18,4,s0,DISP_BGND_BLACK+DISP_F

16、GND_WHITE);PC_DispStr(24,4,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);sprintf(s,”%d”,OSCtxSwCtr);PC_DispStr(20,d1+5,s,DISP_BGND_BLACK+DISP_FGND_WHITE);d = 0;d1 += 1;d += 1; ,OSTimeTickHook()是系统调用的函数,为了方便应用程序设计人员能在系统调用的函数中插入一些自己的工作。,例程3-2:,设计一个有3个任务的应用程序。这3个任务分别是:MyTask、YouTask、和InterTask。其中任务InterTask是在时钟节

17、拍中断服务程序中用钩子函数OSTimeTickHook()中断了10000次时使用一个信号变量InterKey激活的。运行并分析由中断服务程序激活任务的工作特点。,与时间管理有关的函数除了时钟中断服务子程序和时钟节拍函数外还有5个:OSTimeDLY()OSTimeDLYHMSM()OSTimeDlyResmue() / 由其他任务唤醒延迟未满的任务OStimeGet() / 获得OSTime 的当前值OSTimeSet() / 设置OSTime 的当前值必须通过设置OS_CFG.H中的一些配置常量,才能使它们使用。,3.3 时间管理,3.3.1 任务的延时,由于嵌入式系统的任务是一个无限循环

18、 , 且uC/OS-II是一个抢占式内核。使高优先级的任务不至于独占CPU,uC/OS-II规定:除了空闲任务之外的所有任务必须在任务中延迟并进行一次任务调度,以让出CPU的使用权。,void OSTimeDly (INT16U ticks) if (ticks 0) OS_ENTER_CRITICAL();if (OSRdyTblOSTCBCur-OSTCBY / 调用调度函数 ,INT8U OSTimeDlyHMSM (INT8U hours, / 时INT8U minutes, / 分INT8U seconds, / 秒INT16U milli / 毫秒);,参数ticks是以时钟节拍数

19、为单位的延时时间。,3.3.2 取消任务的延时,延时的任务可通过在其它任务中调用函数OSTimeDlyResume()取消延时而进入就绪状态。如果任务比正在运行的任务优先级高,则立即引发一次任务调度。,INT8U OSTimeDlyResume ( INT8U Prio);,INT8U OSTimeDlyResume (INT8U prio) if (prio = OS_LOWEST_PRIO) return (OS_PRIO_INVALID);OS_ENTER_CRITICAL();ptcb = (OS_TCB *)OSTCBPrioTblprio; if (ptcb != (OS_TCB

20、*)0) if (ptcb-OSTCBDly != 0) ptcb-OSTCBDly = 0; if (ptcb-OSTCBStat ,参数prio为被取消延时任务的优先级别。,例程3-3:,本例应用程序的任务使用了延时函数OSTimeDly()进行延时,在任务MyTask中还调用了函数OSTimeDlyResume()取消了任务YouTask的延时。为了观察任务YouTask的延时时间的变化,在钩子函数OSTimeTickHook()输出了任务YouTask在延时时间到时的时钟节拍数。,3.3.3 获取和设置系统时间,系统定义一个INT32U类型的全局变量OSTime来记录系统发生的时钟节拍

21、数。OSTime在调用OSStart()时被初始化为0,以后每发生1个时钟节拍, OSTime的值就被加1。在应用程序调用OSTimeGet()可获取OSTime的值。如果应用程序调用OSTimeSet(),则可设置OSTime的值。,INT32U OSTimeGet (void);,void OSTimeSet (INT32U ticks);,例程3-4:,设计一个应用程序,在任务中调用函数OSTimeGet()函数获得并显示系统的时钟节拍数OSTime.当任务运行10s时,调用函数OSTimeSet()将OSTime的值设为10。,3.4 小结,1. 在uC/OS-II中,中断服务子程序运

22、行结束之后,系统将会根据情况进行一次中断级的任务调度去运行优先级更高的就绪任务,而不一定要接续运行被中断的任务。 2. uC/OS-II的中断允许嵌套,用全局变量OSIntNesting来记录中断的嵌套数。 3. uC/OS-II的中断服务程序的工作通常是由中断激活的一个任务来完成的。这样的优点是可以使应用程序的设计更为灵活。 4. 在任务中可以用设置临界区的方法来屏蔽中断。设置临界区的宏有3种实现方法。 5. uC/OS-II的时钟通常是一个由硬件计数器定时产生周期性中断信号来实现的,每一次中断叫做一个节拍,其中断服务程序叫做节拍服务程序。 6. uC/OS-II在每一个节拍服务里要遍历系统中的全部任务的任务控制块,把其中记录任务延时时间的成员OSTCBDly减1,并使延时时间到的任务进入就绪态。 7. uC/OS-II有10个函数提供了钩子函数,应用程序设计人员可以在钩子函数中编写一些自己的代码。 8. 在uC/OS-I进行时间管理的函数中,最重要的是延时函数OSTimeDly()和I OSTimeHMSM()。他们的作用不仅仅是使任务的运行停止并等待一段时间,更重要的是,他们都要调用任务调度器进行一次任务调度,这样就使低优先级别的任务有了运行的机会。,术语,Copyright 2008 版权所有 东软集团,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报