uCOS-II的时钟和中断.ppt_第1页
uCOS-II的时钟和中断.ppt_第2页
uCOS-II的时钟和中断.ppt_第3页
uCOS-II的时钟和中断.ppt_第4页
uCOS-II的时钟和中断.ppt_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

嵌入式操作系统原理,第三章: uC/OS-II的中断和时钟,目标: 本章旨在向学员介绍uc/osII实时操作系统的中断概念及时间管理,通过本章的学习,学员应该掌握如下知识: 1)uC/OSII的中断管理和中断服务程序的 结构 2)uC/OSII的系统时钟及实现方法 3)时间管理服务:延时、取消延时,时间:2.0学时 教学方法:讲授PPT+ 练习,3.1 uC/OS-II的中断,中断:任务在运行过程中,应内部或外部异步事件的请求中止当前任务,而去处理异步事件所要求的任务的过程叫做中断。 中断服务程序:应中断请求而运行的程序叫中断服务子程序(ISR)。 中断向量:中断服务子程序的入口地址叫中断向量。 CPU响应中断的条件: 至少有一个中断源向CPU发出中断信号 系统允许中断,且对此中断信号未予屏蔽,3.1.1 uC/OS-II的中断过程,uC/OS-II中断的响应过程:,中断请求,关闭中断,转到中断向量,保存CPU寄存器,通知内核进入ISR,通知内核退出ISR,恢复CPU寄存器,中断返回,无新高级任务则返回原任务,有新高级任务则运行高级任务,ISR给任务发信号,通知内核退出ISR,恢复CPU寄存器,中断返回,图3-1 中断的响应过程,中断响应,中断恢复,任务响应时间,中断恢复,任务响应时间,注意:对于可剥夺型内核,中断服务子程序结束后,系统进行一次任务调度去运行优先级最高的就绪任务,而不是一定要接续运行被中断的任务。,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 (OSLockNesting = 0) ,进入,中断嵌套层数=0?,获得任务TCB的指针,YES,NO,NO,返回中断服务程序,未锁定调度器?,NO,获得最高级别就绪任务的prio,任务是被中断的任务?,YES,YES,执行中断级任务切换,图3-2 函数OSIntExit()的流程图,为记录中断嵌套的层数,定义了一个全局变量OSIntNesting。,函数作用就是把全局变量OSIntNesting加1,从而用它来记录中断嵌套的层数,这个函数在中断嵌套层数计数器为0、调度器未被锁定且从任务就绪表中查找到的最高级就绪任务又不是被中断的任务的条件下将要进行任务切换,否则就返回被中断的服务程序,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 (OSLockNesting = 0) ,进入,中断嵌套层数=0?,获得任务TCB的指针,YES,NO,NO,返回中断服务程序,未锁定调度器?,NO,获得最高级别就绪任务的prio,任务是被中断的任务?,YES,YES,执行中断级任务切换,图3-2 函数OSIntExit()的流程图,为记录中断嵌套的层数,定义了一个全局变量OSIntNesting。,函数作用就是把全局变量OSIntNesting加1,从而用它来记录中断嵌套的层数,这个函数在中断嵌套层数计数器为0、调度器未被锁定且从任务就绪表中查找到的最高级就绪任务又不是被中断的任务的条件下将要进行任务切换,否则就返回被中断的服务程序,3.1.3 中断服务子程序的流程,中断服务子程序入口,OSTCBCur-OSTCBStkPtr=SP,NO,中断嵌套层OSIntNEsting=1?,YES,清中断源的中断申请标志,图3-3 中断服务子程序的流程图,CPU寄存器内容进栈,调用OSIntEnter()通知系统:进入中断服务程序,重新开放中断,运行中断服务代码,调用OSIntExit()通知系统:推出中断服务程序,恢复CPU寄存器内容,执行中断返回指令,在uC/OS-II中,通常用一个任务来完成异步事件的处理工作,而在中断服务程序中只是向任务发送消息的方法去激活这个任务。,并非为每个任务都定义一个充分大的栈空间,中断嵌套时单独定义一个中断嵌套栈,在发生第1次中断时,中断服务程序将栈空间切换到中断嵌套栈,这样,以后发生的嵌套中断就一直使用这个栈空间。,3.1.4 中断级任务切换,OSIntCtxSw() OSTCBCur = OSTCBHighRdy; / 任务控制块的切换 OSPrioCur = OSPrioHighRdy; SP = OSPrioHighRdy-OSTCBStkPtr; / 使SP指向待运行任务堆栈 用出栈指令把R1、R2弹入CPU的通用寄存器; RETI; / 中断返回,使PC指向待运行任务 ,与任务级切换函数OSCtxSW()的原因一样,中断级任务切换函数OSIntCtxSw()通常是用汇编语言来编写的:,3.1.5 临界段,在应用程序中经常有一些代码段必须不受任何干扰地连续运行,这样的代码叫做临阶段。 怎样保证临阶段的安全? 系统当有异步事件发生时会引发中断请求,CPU何时响应这个请求? 需要的条件和策略? 宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。,临界段的概念:,当处理临界段代码时,需要关中断,处理完毕后,再开中断; 关中断时间是实时内核重要的指标之一; 在实际应用中,关中断的时间很大程度中取决于微处理器的结构和编译器生成的代码质量; C/OS-II定义两个宏开关中断: OS_ENTER_CRITICAL(); OS_EXIT_CRITICAL(); 因为这2个宏的定义取决于所使用的微处理器,因此在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中配置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()时,从堆栈中弹出原来中断的开/关状态;,第2种方法可使CPU中断允许标志的状态在临界段前和临阶段后不发生改变。,void Some_uCOS_II_Service(arguments) OS_CPU_SR cpu_sr cpu_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() set-processer_psw(cpu_sr);,3.1.6.3 开关中断的实现方法3,OS_CRITICAL_METHOD=3 把当前处理器的状态字保存在局部变量中(如OS_CPU_SR),关中断时保存,开中断时恢复。这样需要在选择用这种方法进入临界代码的应用程序中定义一个局部变量cpu_sr。,第3种方法的前提条件:用户使用C编译器具有扩展功能,用户可获得程序状态字的值,这样就可以把该值保存在C语言函数的局部变量中,而不必压到堆栈里。,任何操作系统都要提供一个周期性的信号源,以供系统处理诸如延时、超时等与时间有关的事件,这个周期性的信号源叫做时钟。 硬件定时器产生一个周期为毫秒级的周期性中断来实现系统时钟。最小的时钟单位就是两次中断之间间隔的时间,这个最小时钟单位叫做时钟节拍。 硬件定时器以时钟节拍为周期定时的产生中断,该中断的中断服务程序叫做OSTickISR(),中断服务程序通过调用函数OSTimeTick()来完成系统在每个时钟节拍时需要做的工作。,3.2 uC/OS-II的时钟,C/OS节拍率应选在10100次/秒。 必须在多任务系统启动OSStart()以后,再开启时钟节拍器。,3.2.1 时钟节拍中断服务子程序,程序清单 : 时钟节拍中断服务子程序的示意代码,因为使用C语言不便于对CPU的寄存器进行处理,所以这段代码使用汇编语言编写。,3.2.2 时钟节拍服务函数,void OSTimeTick (void) OS_TCB *ptcb; OSTimeTickHook(); #if OS_TIME_GET_SET_EN 0 OS_ENTER_CRITICAL(); OSTime+; / 记录节拍数 OS_EXIT_CRITICAL(); #endif if (OSRunning = TRUE) ptcb = OSTCBList; while (ptcb-OSTCBPrio != OS_IDLE_PRIO) OS_ENTER_CRITICAL(); if (ptcb-OSTCBDly != 0) if (-ptcb-OSTCBDly = 0) /任务的延时时间减1 if (ptcb-OSTCBStat ,OSTimeTick()做了两件事情: 1.给计数器OSTime加1; 2.遍历任务控制块链表中的所有任务控制块,把各个任务控制块中用来存放任务延时时限的OSTCBDly变量减1,同时又不使被挂起的任务进入就绪态。,简单地说,函数OSTimeTick()的任务就是在每个时钟节拍了解每个任务的延时状态,使其中已经到了延时时限的非挂起任务进入就绪状态。,例程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_FGND_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;,OSTimeTick()是系统调用的函数,为了方便应用程序设计人员能在系统调用的函数中插入一些自己的工作。,例程3-2:,设计一个有3个任务的应用程序。这3个任务分别是:MyTask、YouTask、和InterTask。其中任务InterTask是在时钟节拍中断服务程序中用钩子函数OSTimeTickHook()中断了10000次时使用一个信号变量InterKey激活的。运行并分析由中断服务程序激活任务的工作特点。,3.2.3 启动时钟节拍不正确的做法,这里潜在的危险是,时钟节拍中断有可能在C/OS-启动第一个任务之前发生,此时C/OS-是处在一种不确定的状态之中,用户应用程序有可能会崩溃。,与时间管理有关的函数除了时钟中断服务子程序和时钟节拍函数外还有5个: OSTimeDLY() OSTimeDLYHMSM() OSTimeDlyResmue() / 由其他任务唤醒延迟未满的任务 OStimeGet() / 获得OSTime 的当前值 OSTimeSet() / 设置OSTime 的当前值 必须通过设置OS_CFG.H中的一些配置常量,才能使它们使用。,3.3 时间管理,3.3.1 任务的延时,由于嵌入式系统的任务是一个无限循环 , 且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是以时钟节拍数为单位的延时时间。,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 *)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来记录系统发生的时钟节拍数。 OSTime在调用OSStart()时被初始化为0,以后每发生1个时钟节拍, OSTime的值就被加1。 在应用程序调用OSTimeGet()可获取OSTime的值。 如果应用程序调用OSTimeSet(),则可设置OSTime

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论