立即注册 找回密码

微雪课堂

搜索
微雪课堂 操作系统 μC/OS-II卧槽宝典 查看内容

《μC/OS-II卧槽宝典(上)》【连载 第五章 核武器一】

2016-9-26 15:22| 发布者: waveshare-admin| 查看: 1862| 评论: 0

摘要: μC/OS-II内核有很多重要全局变量,OS的实现离不开它们。鉴于它们在OS核中,我们就称它们为“核武器”。 本章只介绍本册涉及的那部分核武器,并将这部分核武器称为“核武器一”,其余将在中册“核武器二”中介绍。 ...
第五章 核武器一
【传宗接代的废话】
μC/OS-II内核有很多重要全局变量,OS的实现离不开它们。鉴于它们在OS核中,我们就称它们为“核武器”。
本章只介绍本册涉及的那部分核武器,并将这部分核武器称为“核武器一”,其余将在中册“核武器二”中介绍。
(为简单起见,本章所介绍的变量部分基于预编译后)
· 非结构体全局变量及参数
本节介绍的是“轻型核武器” —— 非结构体类全局变量。
#define  OS_TICKS_PER_SEC       1000u   //定义一秒钟为多少TICKS
#define  OS_MAX_TASKS           20u     //定义用户任务最大数
#define  OS_N_SYS_TASKS         2u      //定义系统任务总数
#define  OS_LOWEST_PRIO         63u     //定义最低优先级
#define  OS_TASK_IDLE_STK_SIZE  32u     //定义统计任务堆栈大小
#define  OS_TASK_STAT_PRIO  (OS_LOWEST_PRIO - 1u)   //定义统计任务优先级为次低
#define  OS_TASK_IDLE_PRIO  (OS_LOWEST_PRIO)        //定义空闲任务优先级为最低
#define  OS_RDY_TBL_SIZE    ((OS_LOWEST_PRIO) / 8u + 1u)    //定义就绪表(数组)大小
#define  OS_TCB_RESERVED    ((OS_TCB *)1)   //定义保留的TCB标志为1
#define  OS_EXT    extern      //定义OS_EXT表示在外部使用
typedef  INT8U     OS_PRIO;    //定义OS_PRIO类型为INT8U
typedef  INT32U    OS_STK;     //定义OS_STK类型为INT32U
OS_EXT  INT32U     OSCtxSwCtr;     //定义任务切换计数器。μC/OS-II用“Ctr”后缀表示计数器
OS_EXT  INT8U      OSIntNesting;   //定义中断嵌套数。可作为调度器可否进行调度的标志
//以保证调度器不会在中断服务程序中进行任务调度
OS_EXT  INT8U      OSLockNesting;  //定义锁定嵌套数。可作为调度器可否进行调度的标志
OS_EXT  INT8U      OSPrioCur;      //定义当前任务的优先级
OS_EXT  INT8U      OSPrioHighRdy;  //定义最高就绪任务的优先级
OS_EXT  OS_PRIO    OSRdyGrp;       //定义就绪任务组
//用途:每一位对应的表示每一组OSRdyTbl是否有进入就绪态的任务
OS_EXT  OS_PRIO    OSRdyTbl[OS_RDY_TBL_SIZE];  //定义任务就绪表
//若系统支持64个任务,则把64个任务分为8组,每组8个任务
//每位数据的0、1状态代表64个任务是否处于就绪态
OS_EXT  BOOLEAN     OSRunning;      //定义OS是否运行标志
OS_EXT  INT8U      OSTaskCtr;     //定义任务计数器
OS_EXT  volatile INT32U  OSIdleCtr;    //定义空闲任务计数器
OS_EXT  OS_STK     OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE];  //定义空闲任务堆栈
OS_EXT  OS_STK      OSTaskStatStk[OS_TASK_STAT_STK_SIZE];   //定义统计任务堆栈
-------------------------------------------------------------------------------------------------------------------------------------------
① 从以上代码(“原版”μC/OS代码也同)可以看出,μC/OS开山鼻祖及“引渡者”对变量名的斟酌并没有下太多功夫。
笔者认为μC/OS变量的命名有时不能尽更大程度,让人一目了然,甚至一些变量命名充满矛盾,缺乏规范。
如,本节的OSTaskCtr、OSIdleCtr、OSTaskIdleStk,如果统一,则可以命名为:
OSTaskCtr、OSTaskIdleCtr、OSTaskIdleStk。(对于Task,有时带上,有时省去,对用户来说并不友好。)
-------------------------------------------------------------------------------------------------------------------------------------------

· 结构体全局变量OS_TCB
本节介绍的是“重型核武器” —— 结构体类全局变量。
typedef structos_tcb
{
OS_STK              *OSTCBStkPtr;   //任务堆栈指针(指向任务堆栈栈顶),翻译为英文是TaskSP①
struct os_tcb   *OSTCBNext;     //指向下一个任务控制块(在TCBList中)②
struct os_tcb       *OSTCBPrev;     //指向上一个任务控制块(在TCBList中)②
INT32U          OSTCBDly;      //任务等待的节拍数
INT8U           OSTCBStat;     //任务控制块的状态标志
INT8U           OSTCBStatPend; //任务控制块的等待状态标志
INT8U           OSTCBPrio;     //任务优先级
INT8U            OSTCBX;        //OSTCBX = priority & 0x07;
INT8U           OSTCBY;        //OSTCBY = priority >> 3;
OS_PRIO         OSTCBBitX;     //OSTCBBitX = OSMapTbl[priority & 0x07];
OS_PRIO         OSTCBBitY;     //OSTCBBitY= OSMapTbl[priority >> 3];
                                    //提前做了运算并存储,以上四个变量存在的目的是节约任务调度时间
                                    //相关说明参见【第十二章】
} OS_TCB;           
OS_EXT  OS_TCB     *OSTCBCur;      //定义指向运行任务控制块的指针
OS_EXT  OS_TCB     *OSTCBFreeList; //定义指向空闲任务控制块列表的指针
OS_EXT  OS_TCB     *OSTCBHighRdy;  //定义指向最高就绪任务控制块的指针   
OS_EXT  OS_TCB     *OSTCBList;     //定义指向任务控制块列表的指针
OS_EXT  OS_TCB     *OSTCBPrioTbl[OS_LOWEST_PRIO + 1u];        //定义指向优先级任务控制块表
OS_EXT  OS_TCB     OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];    //定义任务控制块表
                                                                //这货只在OS_InitTCBList()中用到
-------------------------------------------------------------------------------------------------------------------------------------------
① 用“TaskSP”这个命名显然更为合理,那为何“TaskSP”会变成“OSTCBStkPtr”?笔者认为估计是经过了如下演变:
   ·从“TaskSP”到“OSTCBTaskSP”(因为,μC/OS开山鼻祖及“引渡者”将OS_TCB内所有变量都加了前缀“OSTCB”,这个很合理)
   ·从“OSTCBTaskSP”到“OSTCBSP”(因为,μC/OS开山鼻祖及“引渡者”编写的代码有时会省去“Task”)
·从“OSTCBSP”到“OSTCBStkPtr”(可能早期,大家喜欢将“StackPointer”简写为“StkPtr”吧,不过,笔者认为,时至今日,“SP”比“StkPtr”优越)
当然,为了整个OS的代码风格统一,“TaskSP”前面加“OSTCB”是必要的,那样,“OSTCBStkPtr”更合理的命名是“OSTCBTaskSP”
② 这个数组里的元素,以任务优先级为0开始,依次存放各个任务控制块的指针,这个数值存在的目的是:在需要时,快速得到相应TCB。
“快速”是因为,只需要通过以下步骤:
·通过函数:OS_SchedNew(),获取就绪任务最高优先级,并将它存给OSPrioHighRdy。
·通过代码:OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy],将OSTCBHighRdy指向最高就绪任务的TCB。
③ OSTCBList是一个双向链表,双向链表相比单链表的优点是能够通过Prev访问前一个节点,这也是μC/OS-II采用双链表的原因。
   虽然增加任务时,只会将任务TCB从OSTCBList一端插入,那样,将OSTCBList构建为单链表就可以了。
但,删除任务时,删除的TCB节点并不一定在OSTCBList的一端,那样就需要Prev,也就是需用将OSTCBList构建为双链表。
-------------------------------------------------------------------------------------------------------------------------------------------

252

顶一下

刚表态过的朋友 (252 人)

相关阅读

最新评论

μCOS-II

微雪官网|产品资料|手机版|小黑屋|微雪课堂. ( 粤ICP备05067009号 )

GMT+8, 2020-10-30 13:10 , Processed in 0.016934 second(s), 18 queries .

返回顶部