您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > ucos中断和时钟.
中断和时钟王华斌Wanghuabin-2003@163.com中断是计算机系统处理异常事件的重要机制!uC/OS-II的时钟是通过硬件定时器产生定时中断实现的。任务在运行过程中,应内部或外部异常事件的请求中止当前任务,而去处理异常事件所要求的任务的过程叫做中断。应中断请求而运行的程序叫做中断服务子程序(ISR);中断服务子程序的入口地址叫做中断向量。1、中断μC/OS中,中断服务子程序要用汇编语言来写。然而,如果用户使用的C语言编译器支持在线汇编语言的话,用户可以直接将中断服务子程序代码放在C语言的程序文件中。响应中断过程:系统接收到中断请求后,如果这时CPU处于中断允许状态,系统就会中止正在运行的任务,而按照中断向量的指向转而去运行中断服务子程序;而中断服务子程序的运行结束后,系统将会根据情况返回到被中止的任务继续执行,或者转向运行另一个具有更高优先级别的就绪任务。(任务的调度)总结中断是一种硬件机制,用于通知CPU有个异常事件发生了。中断一旦被识别,CPU保存部分(或全部)现场(Context)即部分或全部寄存器的值,跳转到专门的子程序,称为中断服务子程序(ISR)。中断服务子程序做事件处理,处理完成后,程序回到:(1)在前后台系统中,程序回到后台程序(2)对不可剥夺型内核而言,程序回到被中断了的任务(3)对可剥夺型内核而言,让进入就绪态的优先级最高的任务开始运行中断嵌套UC/OS-II系统运行中断嵌套,即:高优先级别的中断源的中断请求可以中断低优先级别的中断服务程序的运行。为了记录中断嵌套的层数,定义了一个全局变量OSIntNesting。(1)进入中断函数:voidOSIntEnter(void){if(OSRunning==TRUE){if(OSIntNesting255){OSIntNesting++;}//中断嵌套层数计数器加1}}调用情况:此函数在中断服务程序保护断点数据后,运行用户中断服务代码之前来调用,所以通常把它叫做进入中断服务函数。(2)退出中断服务函数中断嵌套层数=0?调度器未被锁任务是被中断的任务入口获得最高优先级别就绪任务的prio获得任务TCB的指针执行中断级任务切换返回中断服务程序NoNoNoYesYesYes说明:这个函数在中断嵌套层数计数器为0、调度器未被锁定、从任务就绪表中查找到的最高级就绪任务不是被中断的任务的条件下将要进行任务切换,否则就返回被中断的服务子程序源代码见下页voidOSIntExit(void){OS_ENTER_CRITICAL();if((--OSIntNesting&&OSLockNesting)==0){OSIntExitY=OSUnMapTbl[OSRdyGrp];OSPrioHighRdy=(INT8U)((OSIntExitY3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);if(OSPrioHighRdy!=OSPrioCur){OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];OSCtxSwCtr++;OSIntCtxSw();}}OS_EXIT_CRITICAL();}用户中断服务子程序流程:1、保存全部CPU寄存器;2、调用OSIntEnter或OSIntNesting直接加13、If(OSIntNesting==1){OSTCBCur-OSTCBStkPtr=SP}//V2.04以上新增4、清中断源5、重新开中断6、执行用户代码做中断服务;7、调用OSIntExit();8、恢复所有CPU寄存器;9、执行中断返回指令;中断级任务切换函数uC/OS-II在运行完中断服务程序之后,并不一定返回到被中断的任务上去,而是要进行一次任务调度来决定是返回被中断的任务还是运行一个具有更高优先级别的任务,因此系统需要一个中断级任务调度器。由函数OSIntExit()的源代码可以知道,通过调用函数OSIntCtxSw()来进行中断级的任务切换。在中断服务程序中调用的负责任务切换的函数OSIntCtxSw()叫做中断级任务切换函数。2、时钟时钟:任何操作系统都要提供一个周期性的信号源,以供系统处理与时间相关的事件,这个周期性的信号源叫做时钟。时钟节拍:UC/OS-II用硬件定时器产生一个周期为毫秒级的周期性中断来实现系统时钟。最小的时钟就是两次中断之间间隔的时间,这个最小时钟单位叫做时钟节拍。OSTickISR():硬件定时器以时钟节拍为周期定时地产生中断,该中断的中断服务程序就是它。中断服务程序OSTickISR()通过调用函数OSTimeTick()来完成系统在每个时钟节拍时需要做的工作。(1)时钟节拍的中断服务程序OSTickISR()用汇编语言来编写:VoidOSTickISR(void){保存CPU寄存器;调用OSIntEnter();//记录中断嵌套层数if(OSIntNesting==1){OSTCBCur-OSTCBStkPtr=SP;//在任务TCB中保存SP}调用OSTimeTick();//时钟节拍服务函数清除中断;开中断;调用OSIntExit();//中断嵌套层数减1恢复CPU寄存器;中断返回;}(2)OSTimeTick()用C编写在时钟中断服务程序中调用OSTimeTick()UC/OS-II在每次响应定时中断时调用OSTimeTick()做了两件事情:一是给计数器OSTime加1;二是遍历任务控制块链表中的所有任务控制块,把各个任务控制块中用来存放任务延时时限的OSTCBDly变量减1,并使该项为0,同时又不使被挂起的任务进入就绪状态。简单地说,函数OSTimeTick的任务就是在每个时钟节拍了解每个任务的延时状态,使其中已经到了延时时限的非挂起任务进入就绪状态。Hook()函数OSTimeTick()是系统调用的函数,为了方便应用程序设计人员能在系统调用的函数中插入一些自己的工作,OS提供了时钟节拍服务函数的钩子函数OSTimeTickHook()。此外,OS还提供了OSStkInitHook()、OSInitHookBegin()、OSInitHookEnd()、OSTaskCreateHook()、OSTaskDelHook()、OSTaskSwHook()、OSTaskStatHook()、OSTCBInitHook()、OSTaskIdleHook()等与OSTimeTickHook()一起共10个钩子函数,以供用户在系统调用函数中书写自己的代码。3、时间管理任务的延时:由于嵌入式系统的任务是一个无限循环,并且UC/OS-II还是一个抢占式内核,所以为了使高优先级别的任务不至于独占CPU,可以给其他优先级别较低的任务获得CPU使用权的机会。UC/OS-II规定:除了空闲任务之外的所有任务必须在任务中合适的位置调用系统提供的函数OSTimeDly(),使当前任务的运行暂停一段时间并进行一次任务调度,以让出CPU的使用权。OSTimeDly()原型:voidOSTimeDly(INT16Uticks)函数的参数ticks是以时钟节拍数为单位的延时时间的。OSTimeDlyHMSM()时、分、秒为参数INT8UOSTimeDlyHMSM(INT8Uhours,//时INT8Uminutes,//分INT8Useconds,//秒INT16Umilli//毫秒)调用了以上这两个函数的任务,当规定的延时时间期满时,或者有其他任务通过调用函数OSTimeDlyResume()取消了延时时,它会立即进入就绪状态。取消任务的延时OSTimeDlyResume()延时的任务可以通过在其他任务中调用函数OSTimeDlyResume()取消延时并进入就绪状态,如果任务比正在运行的任务优先级别高,则立即引发一次任务调度。原型:INT8UOSTimeDlyResume(INT8Uprio)获取和设置系统时间系统定义了一个INT32U类型的全局变量OSTime来记录系统发生的时钟节拍数。OSTime在应用程序调用OSStart()时被初始化为0,以后每发生一个时钟节拍,OSTime的值就被加1。在应用程序中调用函数OSTimeGet()可获得OSTime的值。原型:INT32UOSTimeGet(void);函数的返回值即为OSTime的值。OSTimeSet()设置OSTime的值。voidOSTimeSet(INT32Uticks);函数的参数ticks为OSTime的设置值(节拍数)。举例:设计一个应用程序,在任务中调用函数OSTimeGet()获得并显示系统的时间节拍数OSTime。当任务运行10s时,调用函数OSTimeSet()将OSTime设置为10.
本文标题:ucos中断和时钟.
链接地址:https://www.777doc.com/doc-2864333 .html