第四讲--ucOS-II内核结构-03

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

ucOS-II内核结构临界段(CriticalSections)μC/OS-Ⅱ为了处理临界段代码需要关中断,处理完后再开中断。μC/OS-Ⅱ定义两个宏(macros)OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来关中断和开中断,以便避开不同C编译器厂商选择不同的方法来处理关中断和开中断。这两个宏的定义取决于所用的微处理器,在文件OS_CPU.H中可以找到相应宏定义(每种微处理器都有自己的OS_CPU.H文件)。任务一个任务通常是一个无限的循环,而且一个任务的返回参数必须定义成void。任务完成以后,任务可以调用OSTaskDel()自我删除,μC/OS-Ⅱ不再理会这个任务,任务的代码也不会再运行。一个无限循环任务的程序voidYourTask(void*pdata)(1){for(;;){(2)/*用户代码*/调用uC/OS-II的某种系统服务:OSMboxPend();/任务进入等待状态OSQPend();/任务进入等待状态OSSemPend();/任务进入等待状态OSTaskDel(OS_PRIO_SELF);/任务完成后自我删除OSTaskSuspend(OS_PRIO_SELF);/任务挂起等待OSTimeDly();/延迟一段时间OSTimeDlyHMSM();/延迟一段时间/*用户代码*/}}任务控制块(TaskControlBlocks,OS_TCBs)任务一旦建立,任务控制块OS_TCBs将被赋值。任务控制块是一个数据结构,全部驻留在RAM中。当任务的CPU使用权被剥夺时,μC/OS-Ⅱ用它来保存该任务的状态。当任务重新得到CPU使用权时,任务控制块能确保任务从当时被中断的那一点开始继续向下执行。任务建立的时候,OS_TCBs被初始化。μC/OS-II任务控制块程序typedefstructos_tcb{OS_STK*OSTCBStkPtr;/指向当前任务栈顶的指针,是OS_TCB数据结构中唯一一个能用汇编语言来处置的变量(在任务切换段的代码Context-switchingcode之中)#ifOS_TASK_CREATE_EXT_ENvoid*OSTCBExtPtr;/指向用户定义的任务控制块扩展,只在函数OstaskCreateExt()中使用,故使用时要将OS_TASK_CREAT_EN设为1,以允许建立任务函数的扩展OS_STK*OSTCBStkBottom;/指向任务栈底的指针,通过OSTaskCreateExt()函数建立任务时才能实现OSTaskStkChk()功能,要求是将OS_TASK_CREATE_EXT_EN设为1。INT32UOSTCBStkSize;/存放栈中可容纳的指针数目而不是用字节(Byte)表示的栈容量总数,在函数OSStakChk()中调用,同样要将OS_TASK_CREAT_EXT_EN设为1。INT16UOSTCBOpt;/把OS_TASK_OTP_STK_CHK,OS_TASK_OPT_STK_CLR和OS_TASK_OPT_SAVE_FP三个“选择项”传给OSTaskCreateExt()。INT16UOSTCBId;/存储任务的识别码,现在暂时没有使用#endif/用于任务控制块OS_TCBs的双重链接,该链表在时钟节拍函数OSTimeTick()中使用,用于刷新各个任务的任务延迟变量.OSTCBDly,每个任务的任务控制块OS_TCB在任务建立的时候被链接到链表中,在任务删除的时候从链表中被删除。双重连接的链表使得任一成员都能被快速插入或删除。structos_tcb*OSTCBNext;structos_tcb*OSTCBPrev;#if(OS_Q_EN&&(OS_MAX_QS=2))||OS_MBOX_EN||OS_SEM_ENOS_EVENT*OSTCBEventPtr;/指向事件控制块的指针#endifμC/OS-II任务控制块程序#if(OS_Q_EN&&(OS_MAX_QS=2))||OS_MBOX_ENvoid*OSTCBMsg;/指向传给任务的消息的指针#endifINT16UOSTCBDly;/当需要把任务延时若干时钟节拍时要用到这个变量,或者需要把任务挂起一段时间以等待某事件的发生,这种等待是有超时限制的。如果这个变量为0,表示任务不延时,或者表示等待事件发生的时间没有限制。INT8UOSTCBStat;/任务的状态字,当.OSTCBStat为0,任务进入就绪态。INT8UOSTCBPrio;/任务优先级,高优先级任务的.OSTCBPrio值小。INT8UOSTCBX;INT8UOSTCBY;INT8UOSTCBBitX;INT8UOSTCBBitY;/以上四个变量用于加速任务进入就绪态的过程或进入等待事件发生状态的过程(避免在运行中去计算这些值)。这些值是在任务建立时算好的,或者是在改变任务优先级时算出的。#ifOS_TASK_DEL_ENBOOLEANOSTCBDelReq;/一个布尔量,用于表示该任务是否需要删除#endif}OS_TCB;.OSTCBX,.OSTCBY,.OSTCBBitX和.OSTCBBitY的计算任务控制块OS_TCB中几个成员的算法程序OSTCBY=priority3;OSTCBBitY=OSMapTbl[priority3];OSTCBX=priority&0x07;OSTCBBitX=OSMapTbl[priority&0x07];应用程序中可以有的最多任务数(OS_MAX_TASKS)是在文件OS_CFG.H中定义的。这个最多任务数也是μC/OS-Ⅱ分配给用户程序的最多任务控制块OS_TCBs的数目。将OS_MAX_TASKS的数目设置为用户应用程序实际需要的任务数可以减小RAM的需求量。所有的任务控制块OS_TCBs都是放在任务控制块列表数组OSTCBTbl[]中的。请注意,μC/OS-Ⅱ分配给系统任务OS_N_SYS_TASKS若干个任务控制块,见文件μC/OS-Ⅱ.H,供其内部使用。目前,一个用于空闲任务,另一个用于任务统计(如果OS_TASK_STAT_EN是设为1的)。空任务链表在μC/OS-Ⅱ初始化的时候,所有任务控制块OS_TCBs被链接成单向空任务链表。当任务一旦建立,空任务控制块指针OSTCBFreeList指向的任务控制块便赋给了该任务,然后OSTCBFreeList的值调整为指向下个链表中下一个空的任务控制块。一旦任务被删除,任务控制块就被还给空任务链表。就绪表(ReadyList)μC/OS-Ⅱ初始化的时候,最低优先级OS_LOWEST_PRIO总是被赋给空闲任务idletask。每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量OSRedyGrp和OSRdyTbl[]。在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置位。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PRIO(见文件OS_CFG.H)。OSRdyGrp和OSRdyTbl[]之间的关系图任务进入就绪态程序OSRdyGrp|=OSMapTbl[prio3];OSRdyTbl[prio3]|=OSMapTbl[prio&0x07];OSMapTbl[]的值IndexBitMask(Binary)000000001100000010200000100300001000400010000500100000601000000710000000任务优先级的低三位用于确定任务在总就绪表OSRdyTbl[]中的所在位。接下去的三位用于确定是在OSRdyGrp[]数组的第几个元素。例如:prio=00110001(prio=49)从就绪表中删除一个任务程序if((OSRdyTbl[prio3]&=~OSMapTbl[prio&0x07])==0)OSRdyGrp&=~OSMapTbl[prio3];将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零,而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零。也就是说OSRdyTbl[prio3]所有的位都是零时,OSRdyGrp的相应位才清零。找到进入就绪态的优先级最高的任务不需要从OSRdyTbl[0]开始扫描整个就绪任务表,只需要查另外一张表,即优先级判定表OSUnMapTbl([256])(见文件OS_CORE.C)。OSRdyTbl[]中每个字节的8位代表这一组的8个任务哪些进入就绪态了,低位的优先级高于高位。利用这个字节为下标来查OSUnMapTbl这张表,返回的字节就是该组任务中就绪态任务中优先级最高的那个任务所在的位置。这个返回值在0到7之间。找出进入就绪态的优先级最高的任务程序y=OSUnMapTbl[OSRdyGrp];x=OSUnMapTbl[OSRdyTbl[y]];prio=(y3)+x;例如,如果OSRdyGrp的值为二进制00001010,查OSUnMapTbl[OSRdyGrp]得到的值是1,它相应于OSRdyGrp中的第1位bit1(假设最右边的一位是第0位bit0)。类似地,如果OSRdyTbl[1]的值是二进制00010100,则OSUnMapTbl[OSRdyTbl[1]]的值是2,即第2位。于是任务的优先级Prio就等于10(1*8+2)。INT8UconstOSUnMapTbl[]={0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x00to0x0F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x10to0x1F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x20to0x2F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x30to0x3F*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x40to0x4F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x50to0x5F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x60to0x6F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x70to0x7F*/7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x80to0x8F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x90to0x9F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xA0to0xAF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xB0to0xBF*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xC0to0xCF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xD0to0xDF*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xE0to0xEF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0/*0xF0to0xFF*/};OSUnMapTbl[]任务调度(TaskScheduling)μC/OS-Ⅱ总是运行进入就绪态任务中优先级最高的那一个。确定哪个任务优先级最高,下面该哪个任务运行了,这个工作是由调度器(Scheduler)完成的。任务级的调度是由函数OSSched()完成的。中断级的调度是由另一个函数OSIntExt()完成的,这个函数将在以后描述。任务调度器(theTaskScheduler)程序voidOSSched(void){INT8Uy;OS_ENTER_CR

1 / 54
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功