




已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一. UCOSII的中断过程简介 系统接收到中断请求后,如果CPU处于开中断状态,系统就会中止正在运行的当前任务,而按中断向量的指向去运行中断服务子程序,当中断服务子程序运行完成后,系统会根据具体情况返回到被中止的任务继续运行,或转向另一个中断优先级别更高的就绪任务。 由于UCOS II是可剥夺型的内核,所以中断服务程序结束后,系统会根据实际情况进行一次任务调度,如果有优先级更高的任务,就去执行优先级更高的任务,而不一定要返回被中断了的任务。 二UCOSII的中断过程的示意图 三具体中断过程 1中断到来,如果被CPU识别,CPU将查中断向量表,根据中断向量表,获得中断服务子程序的入口地址。 2将CPU寄存器的内容压入当前任务的任务堆栈中(依处理器的而定,也可能压入被压入被中断了的任务堆栈中。 3通知操作系统将进入中断服务子程序。即:调用OSIntEnter()或OSIntNesting直接 加1。 4If(OSIntNesting=1) OSTCBCur-OSTCBStrPtr=SP; /如果是第一层中断,则将堆栈指针保存到被中断任务的任务控制块中 5清中断源,否则在开中断后,这类中断将反复的打入,导致系统崩贵 6执行用户ISR 7中断服务完成后,调用OSIntExit()如果没有高优先级的任务被中断服务子程序激活而进入就绪态,那么就执行被中断了的任务,且只占用很短的时间 8恢复所有CPU寄存器的值 9执行中断返回指令 四相关代码 与编译器相关的数据类型: typedef unsigned char BOOLEAN; typedef unsigned char INT8U; typedef unsigned int OS_STK; /堆栈入口宽度为16 位 (一) void OSIntEnter (void)的理解 uCOS_II.H中定义: #ifdef OS_GLOBALS #define OS_EXT #else #define OS_EXT extern #endif /定义全局宏OS_EXT #ifndef TRUE #define TRUE 1 #endif OS_EXT BOOLEAN OSRunning; /定义外部BOOLEAN类型全局变量,用来指示 /核是否在运行 OS_EXT INT8U OSIntNesting;/定义外部8位无符号整型数全局变量,用来表 /示中断嵌套层数 OS_CORE.C中的OSIntEnter()函数原型: void OSIntEnter (void) if (OSRunning = TRUE) /如果内核正在运行则进入if if (OSIntNesting OSTCBStkPtr = SP; / 如果是第一层中断,则将被中断任务 /的堆栈指针保存在被中断任务的任务 /任务控制块中 关于uCOS-II的中断服务程序(ISR)中必须加“OSIntNesting = 1”的原因 =避免调整堆栈指针.出现这个问题的根源是当低优先级的任务被中断,当中断完成后由于有高优先级的任务就绪,则必须调度高优先级的任务,原来的低优先级任务继续被中断着,但是此时的低优先级任务的堆栈已经被破坏,已不能被调度程序直接调度了,要想被调度而必须调整堆栈指针。如下图所示的场景: 问题分析:要想理解加上上面两句的原因,不妨假设有下面场景出现: void MyTask(void) . 该任务在执行过程中被中断打断,下面是它的服务子程序 void MyISR(void) 保存现场(PUSHA) OSIntEnter(); / 此时的堆栈指针是正确的,再往下就不对了,应该在此处保存用户任务堆栈指针 OSIntExit(); 恢复现场(POPA) 中断返回 OSIntExit(),大体如下: OSIntExit() OS_ENTER_CRITICAL(); if( OSIntNesting=0 & OSLockNesting = 0 ) 找到目前系统中就绪表中优先级最的任务 如果不是当前任务,则调度它执行 OSIntCtxSw(); OS_EXIT_CRITICAL(); 综上所述,任务调用链如下: MyTask - MyISR - OSIntExit - OS_ENTER_CRITICAL(); OSIntCtxSw(); 然而在实际的移植过程中,需要调整的指针偏移量是与编译器相关的,如果想要避免调整,显然一个简单的方法就是在调用OSIntExit之前先把堆栈指针保存下来,以后调度该用户任务时,直接从此恢复堆栈指针,而不再管实际的堆栈内容了(因为下面的内容相对于调度程序来说已经没有用处了) (三) void OSIntExit (void)的理解 OS_CPU.H中的宏定义: typedef unsigned short OS_CPU_SR; /定义OS_CPU_SR为16位的CPU状态寄存器 #if OS_CRITICAL_METHOD = 1 #define OS_ENTER_CRITICAL() asm CLI / OS_ENTER_CRITICAL()即为将处理器标志 /寄存器的中断标志为清0,不允许中断 #define OS_EXIT_CRITICAL() asm STI / OS_ENTER_CRITICAL()即为将处理器标志 /寄存器的中断标志为置1,允许中断 #endif /此一整段代码定义为开关中断的方式一 #if OS_CRITICAL_METHOD = 2 #define OS_ENTER_CRITICAL() asm PUSHF; CLI /将当前任务的CPU的标志寄存器入 /然后再将中断标志位清0 #define OS_EXIT_CRITICAL() asm POPF /将先前压栈的标志寄存器的值出栈,恢复 /到先前的状态,如果先前允许中断则现在 /仍允许,先前不允许现在仍不允许 #endif /此一整段代码定义为开关中断的方式二 #if OS_CRITICAL_METHOD = 3 #define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR() /保存CPU的状态寄存器到 /变量cpu_sr中,cpu_sr /为OS_CPU_SR型变量 #define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)/ 从cpu_sr中恢复状态寄存 /器 #endif /此一整段代码定义为开关中断的方式三, /此段代码只是示意代码,OSCPUSaveSR()及 /OSCPURestoreSR(cpu_sr)具体什么函数由 /用户编译器所提供的函数决定. /以上宏定义非常重要,在使用不同处理器时要使用相应处理器的开关中断指令,在代码移/植时很有用 uCOS_II.H中定义: OS_EXT INT8U OSLockNesting; /8位无符号全局整数,表示锁定嵌套计数器 void OSIntExit (void) #if OS_CRITICAL_METHOD = 3 OS_CPU_SR cpu_sr; #endif /采用开关中断方式三 if (OSRunning = TRUE) /如果内核正在运行,则进入if OS_ENTER_CRITICAL();/进入临界段,关中断 if (OSIntNesting 0) /判断最外层中断任务是否已完成 OSIntNesting-;/由于此层中断任务已完成,中断嵌套计数器减/一 if (OSIntNesting = 0) & (OSLockNesting = 0) / OSIntNesting=0表示程序的最外层中断任务以完成, OSLockNesting = 0 /表示是否存在任务锁定,整句代码的意思是如果全部中断处理完了且没有其他 /任务锁定任务调度则执行下列任务调度代码 OSIntExitY = OSUnMapTblOSRdyGrp; /1 OSPrioHighRdy = (INT8U)(OSIntExitY 3) + OSUnMapTblOSRdyTblOSIntExitY); /2 if (OSPrioHighRdy != OSPrioCur) /3 OSTCBHighRdy = OSTCBPrioTblOSPrioHighRdy; OSCtxSwCtr+; OSIntCtxSw(); OS_EXIT_CRITICAL();/开中断 要理解1,2,3处的代码含义.首先要理解任务是如何调度的,所以先讲一下任务调度的核心算法: a.数据结构: 1.就绪表:就绪表包含两个变量,他们分别是OSRdyGrp(在uCOS_II.H中为OS_EXT INT8U OSRdyGrp;即8位无符号整型的全局变量)和OSRdyTb1(在uCOS_II.H中为OS_EXT INT8U OSRdyTblOS_RDY_TBL_SIZE;) 先分析 OS_EXT INT8U OSRdyTblOS_RDY_TBL_SIZE;是怎么回事 #define OS_LOWEST_PRIO 12 /在OS_CFG.H中 这个宏定义了任务所能具有的最低优先级,那么此处共有从0到12共13个优先级,用户在代码移植时可以修改它,自定义所需要的优先级个数,但max(OS_LOWEST_PRIO)=63 #define OS_RDY_TBL_SIZE (OS_LOWEST_PRIO) / 8 + 1) /在uCOS_II.中 OS_RDY_TBL_SIZE用于确定数组OSRdyTbl的大小,如果OS_LOWEST_PRIO=63,则上述宏实际上为#define OS_RDY_TBL_SIZE 8,由于每个数组元素为8位,如果每一位表示一个优先级,则共有8*8=64个优先级 现在回到就绪表,操作系统将优先级分为8组,优先级从0到7分为第一组,对应于OSRdyGrp的第0位,从8到15分为第二组,对应于OSRdyGrp的第1位,以此类推,64个优先级就有下面的对应关系(OSRdyTb1每组元素的每一位代表一个优先级): OSRdyTb10-优先级从0到7-OSRdyGrp第0位 OSRdyTb11-优先级从8到15-OSRdyGrp第1位 OSRdyTb12-优先级从16到23-OSRdyGrp第2位 OSRdyTb13-优先级从24到31-OSRdyGrp第3位 OSRdyTb14-优先级从32到39-OSRdyGrp第4位 OSRdyTb15-优先级从40到47-OSRdyGrp第5位 OSRdyTb16-优先级从48到55-OSRdyGrp第6位 OSRdyTb17-优先级从55到63-OSRdyGrp第7位 现在再做如下对应: 当OSRdyTbl0中的任何一位是1时,OSRdyGrp的第0位置1, 当OSRdyTbl1中的任何一位是1时,OSRdyGrp的第1位置1, 当OSRdyTbl2中的任何一位是1时,OSRdyGrp的第2位置1, 当OSRdyTbl3中的任何一位是1时,OSRdyGrp的第3位置1, 当OSRdyTbl4中的任何一位是1时,OSRdyGrp的第4位置1, 当OSRdyTbl5中的任何一位是1时,OSRdyGrp的第5位置1, 当OSRdyTbl6中的任何一位是1时,OSRdyGrp的第6位置1, 当OSRdyTbl7中的任何一位是1时,OSRdyGrp的第7位置1, 如果置1表示有任务进入就绪态,那么上面的表可以理解为:OSRdyGrp的第N位(0=N1;/将二进制数右移一位 pos+;/进行一次移位,则pos加一 最后得到的pos就是所有位中为1的最低位的偏移量,但这样计算需要时间,尽管最多右移7次。为了节省时间,使用的方法是“空间换时间”的办法,即把8位无符号数,所有可能的情况的都列了出来,共有256个数字,把每个数字的最低为1位的位置都预先计算好。比如4对应二进制数为100,最低为1位相对第0位偏移量为2,则查表时,以4为索引,马上就得到2这个数字。(即:OSUnMapTb14=2) b.构建OSRdyGrp和OSRdyTb1算法: 代码原型在OS_CORE.C中,实际代码大致如下:(prio为任务优先级) INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt) ptcb-OSTCBY = prio 3; ptcb-OSTCBBitY = OSMapTblptcb-OSTCBY; ptcb-OSTCBX = prio & 0x07; ptcb-OSTCBBitX = OSMapTblptcb-OSTCBX; . OSRdyGrp |= ptcb-OSTCBBitY; OSRdyTblptcb-OSTCBY |= ptcb-OSTCBBitX; . /此函数在创建任务时被调用,即OSTaskCreate(.)中,用于初始化任务控制块 以上代码可以等效于: OSRdyGrp |= OSMapTblprio3; OSRdyTb1prio3 |= OSMapTblprio&0x07; 此处 prio 3 是右移3位,就相当于连续除以3个2,因此相当于:prio / 8 ; prio & 0x07 是求低3位的值,而由高5位构成的值正好是8的整数倍,因此是取余运算, 即:prio % 8 因此又可将算法等效为: OSRdyGrp |= OSMapTblprio / 8; OSRdyTb1prio / 8 |= OSMapTblprio % 8; 算法的作用相当于如下流程:(假定prio=28) 就这样把任务的优先级放入了就绪表.在此我产生一个疑问,”prio3与prio&0x07并不直观,为什么不用prio/8与prio%8呢?”我做如下解释: 处理器一般具有如下结构 累加器是具有移位功能的,prio3可以在累加器中完成而不必进入ALU,而prio/8则不同,要进入ALU,ALU处理速度不如累加器,如果采用prio/8将降低操作系统的实时性,同样prio&0x07只是一个间单的位与操作,而prio%8则还要经过ALU,如采用prio%8也将降低实时性 现在回到OSIntExit()处,看1,2,3处的代码: OSIntExitY = OSUnMapTblOSRdyGrp; /1 OSPrioHighRdy = (INT8U)(OSIntExitY 3) + OSUnMapTblOSRdyTblOSIntExitY);/2 if (OSPrioHighRdy != OSPrioCur) /3 OSTCBHighRdy = OSTCBP
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 现代中式园林景观设计
- 2025届攀枝花市盐边县三年级数学第一学期期末监测模拟试题含解析
- 酒店大厅设计方案
- 2022 年中级会计师考试《中级会计实务》真题及解析(9 月 4 日)
- 系统复习市政工程试题及答案
- 2025年市政工程管理体系试题及答案
- 土地买卖居间合同买方
- 水利水电工程考试重要知识点试题及答案
- 美术绘画技巧知识考点梳理与练习设计
- 法律职业道德与职业素养考试点
- 监狱围栏施工组织设计方案范本
- 《口语交际:我是小小讲解员》示范课教学课件【部编人教版五年级语文下册】(定稿)
- SB/T 10029-2012新鲜蔬菜分类与代码
- GB/T 6075.3-2001在非旋转部件上测量和评价机器的机械振动第3部分:额定功率大于15kW额定转速在120r/min至15000r/min之间的在现场测量的工业机器
- GB/T 2410-2008透明塑料透光率和雾度的测定
- GB/T 21739-2008家用电梯制造与安装规范
- GB 21670-2008乘用车制动系统技术要求及试验方法
- GA/T 1275-2015石油储罐火灾扑救行动指南
- 家务服务员理论考试试题题库及答案
- 中央空调的PLC控制
- 公立医院内部控制管理办法课件
评论
0/150
提交评论