从零开始学习UCOSII操作系统2–UCOSII的内核实现「建议收藏」

从零开始学习UCOSII操作系统2–UCOSII的内核实现「建议收藏」从零开始学习UCOSII操作系统2–UCOSII的内核实现参考书籍:《嵌入式实时操作系统μCOS-II原理及应用》、《嵌入式实时操作系统uCOS-II邵贝贝(第二版)》1、任务的结构–任务控制块首先这个任务控制块是非常的大的,这里面使用很多的宏定义,估计是可以让使用者使用的时候按需配置。所以这里只是整理一些必须要用到的功能,不常用的不讲,讲了就会变成一本书了。(1)任务的关键 OS_ST…

大家好,又见面了,我是你们的朋友全栈君。

从零开始学习UCOSII操作系统2–UCOSII的内核实现


参考书籍:《嵌入式实时操作系统μCOS-II原理及应用》、《嵌入式实时操作系统uCOS-II 邵贝贝(第二版)》


1、任务的结构–任务控制块

首先这个任务控制块是非常的大的,这里面使用很多的宏定义,估计是可以让使用者使用的时候按需配置。

所以这里只是整理一些必须要用到的功能,不常用的不讲,讲了就会变成一本书了。

(1)任务的关键   OS_STK  ==  任务的堆栈,用于保存任务的信息,最主要的是保存在程序的运行的SP指针。

任务切换的实质就是SP指针的变化,通过SP指针的变化,可以跳转到你想要去的任何的一块不受保护的地址去。


(2)任务的链表: struct os_tcb   *OSTCBNext; 指向下一个任务,

此处使用链表是可以通过指针访问下一个任务的内容,可以使用这个双向链表放置到某些队列当中,

实现同优先级的多任务。


(3)事件控制块:OS_EVENT        *OSTCBEventPtr; 

是一个技术组件,用于后面的消息和消息队列,邮箱和信号量等的设计。

typedef struct os_tcb {
    OS_STK          *OSTCBStkPtr;      /* 指向当前任务堆栈栈顶的指针                            */

#if OS_TASK_CREATE_EXT_EN > 0
    void            *OSTCBExtPtr;      /* 指向用户定义的任务控制块扩展,这个数据结构包括了任务的名字   */
    OS_STK          *OSTCBStkBottom;   /* 以跟踪某个任务的执行时间,或者跟踪到某个任务的次                          */
    INT32U           OSTCBStkSize;     /* Size of task stack (in number of stack elements)             */
    INT16U           OSTCBOpt;         /* Task options as passed by OSTaskCreateExt()                  */
    INT16U           OSTCBId;          /* Task ID (0..65535)                                           */
#endif

    struct os_tcb   *OSTCBNext;        /* 任务之间的双向链表的使用    */
    struct os_tcb   *OSTCBPrev;        /* Pointer to previous TCB in the TCB list                      */

#if OS_EVENT_EN
    OS_EVENT        *OSTCBEventPtr;    /* 指向任务的事件控制块                 */
#endif

#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
    void            *OSTCBMsg;         /* 指向传递给任务的消息的指针            */
#endif

#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
    OS_FLAG_NODE    *OSTCBFlagNode;    /* 指向事件标志组的指针                  */
#endif
    OS_FLAGS         OSTCBFlagsRdy;    /* 当任务等待事件标志组时候, OSTCBFlagRdy是使任务进入就绪态的事件标志*/
#endif

    INT16U           OSTCBDly;         /* 当需要把任务延时诺干个节拍时,或者需要把任务挂起一段时间等待某个事件的发生,需要使用这个变量 */
    INT8U            OSTCBStat;        /* 任务的状态                    */
    BOOLEAN          OSTCBPendTO;      /* 等待标志组超时          */
    INT8U            OSTCBPrio;        /* Task priority (0 == highest)                                 */

    INT8U            OSTCBX;           /* Bit position in group  corresponding to task priority        */
    INT8U            OSTCBY;           /* Index into ready table corresponding to task priority        */
#if OS_LOWEST_PRIO <= 63
    INT8U            OSTCBBitX;        /* Bit mask to access bit position in ready table               */
    INT8U            OSTCBBitY;        /* Bit mask to access bit position in ready group               */
#else
    INT16U           OSTCBBitX;        /* Bit mask to access bit position in ready table               */
    INT16U           OSTCBBitY;        /* Bit mask to access bit position in ready group               */
#endif

#if OS_TASK_DEL_EN > 0
    INT8U            OSTCBDelReq;      /* Indicates whether a task needs to delete itself              */
#endif

#if OS_TASK_PROFILE_EN > 0
    INT32U           OSTCBCtxSwCtr;    /* Number of time the task was switched in                      */
    INT32U           OSTCBCyclesTot;   /* Total number of clock cycles the task has been running       */
    INT32U           OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption        */
    OS_STK          *OSTCBStkBase;     /* Pointer to the beginning of the task stack                   */
    INT32U           OSTCBStkUsed;     /* Number of bytes used from the stack                          */
#endif

#if OS_TASK_NAME_SIZE > 1
    INT8U            OSTCBTaskName[OS_TASK_NAME_SIZE];
#endif
} OS_TCB;

2、如何得到最高的优先级的任务—就绪表机制

这个表的原理非常的简单,就是通过查表的原理,不断的从X轴到Y轴的不断的累加来计算的。

让某一个任务进入就绪态的话,仅仅只需要在这份表格中填入1即可。


具体代码:

OSRdyGrp       |=  OSMapTbl[prio >> 3];

OSRdyTbl[prio>>3] |= OSMapTbl[prio & 0x07];


计算实例:假设我们需要让优先级为24的任务置1的话。

任务的优先级组中填入的数是 24 >> 3   也就是24 >> 3 = 3

那么在任务的第3个优先级组中我们应该填入是24 & 0x07 = 0,也就是在第0位上面填入1,即可把优先级为24的任务唤醒。

把相应的任务挂起的计算公式为:

OSRdyGrp &= ~OSMapTbl[prio >> 3];


从零开始学习UCOSII操作系统2--UCOSII的内核实现「建议收藏」



3、如何通过最高优先级的任务进行任务切换–进入中断,切换任务堆栈实现


(1)首先我们可以通过上面的机制得到当前系统中的最高的优先级任务是什么?

但是我们怎么通过这个最高级的优先级任务,把当前任务切换到最高级的优先级任务呢?

(2)里面涉及到一个重要的概念,每一种CPU中都有一些对应的CPU的寄存器。里面

有一个十分关键的程序指针,是用来跳转到相应的程序里面的。

上节说到每个任务都是一个无类型无返回值的函数,也就是可以通过函数指针的方式

跳转到你想要跳转的任务里面去执行。

(3)要实现上面的过程是通过一个函数来实现的OS_TASK_SW();

(4)下面根据下面的图进行任务切换的分析过程从零开始学习UCOSII操作系统2--UCOSII的内核实现「建议收藏」

此过程主要是分析,当程序中遇到更高的优先级的时候,CPU应该是怎么运行的。

(1)假设当前运行的任务是低优先级的任务,CPU程序寄存器中存在的一些寄存器都是低优先级的任务

(2)当程序运行到检测到高优先级的任务进入就绪状态的时候,此时CPU发送一些命令,把CPU当前的一些程序寄存器的内容复制到低优先级任务的堆栈中。也就是1过程。

(3)此时通过刚刚的就绪表的机制,可以从程序中得到最高优先级的任务,也就是2过程

(4)最后的过程3就是把刚刚的高优先级任务的堆栈指针复制到CPU的程序寄存器当中,实现任务的切换。


3、如何实现时间片的轮询的方法?

(1)根据上面的过程是实现可剥夺型内核的基础,但是有些是可以进行时间片轮询的方式的。

UCOSII本身是不支持同优先级有多个任务的,UCOSIII是支持的,所以实现这个机制的方案

就是刚刚上面提到的事件控制块的灵活使用。

(2)刚刚的位图是指向某一个任务的,但是UCOSIII的位图是指向一个队列,在同一个队列中优先级

相同,也就是说,同一优先级的任务应该是按时间片轮询的方式的。

(3)每个处理器中都会有一个时钟节拍,在时钟节拍中调用任务切换的核心函数,

在同一个优先级不断的进行轮询即可实现时间片轮询。




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/135922.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • stm32开发教程_单片机STM32

    stm32开发教程_单片机STM32本博客的编写目的:一、自我总结,记录。二、分享,输出,加深思考。三、不作细致如书本般编排,尽管那样的排版很好看,但是过于耗费时间,还有很多东西没有必要说明,完全可以自己去解决,但还是尽量做好排版,便于阅读。四、尽可能举一反三,做到真正能够处理实际问题。STM32开发实战(1)目录一、概述,目的二、搭建步骤三、时钟部分案例分析四、理论总结一、

    2022年9月7日
  • Latex数学公式-求导、分数的表示

    Latex数学公式-求导、分数的表示表示方法\frac{}{}:分数表示\partial:偏导符号代码效果意义\frac{x}{y}xy\frac{x}{y}yx​分数\partial∂\partial∂偏导符号举例$$\frac{\partialy}{\partialx_1}+\frac{\partialy}{\partialx_2}$$显示效果如下:∂y∂…

    2022年6月23日
  • Python基础语法01:缩进规则

    Python基础语法01:缩进规则Python程序设计第6章:函数和函数式编程6.1函数定义6.1.1函数概述6.1.2函数定义6.1.3形参和实参6.1.4函数的返回值6.2函数分类6.2.1内建函数6.2.2自定义函数6.3函数参数6.3.1参数种类6.3.2位置参数6.3.3默认参数6.3.4不定长参数6.3.5关键字参数6.3.6命名关键字参数6.3.7参数组合6.4函数式编程6.4.1高阶函数6.4.2匿名函数6.5总结6.1函数定义6.1.1函数概述6.1.2函数定义6.1

    2022年10月13日
  • HTML iframe 标签[通俗易懂]

    HTML iframe 标签[通俗易懂]定义和用法iframe元素会创建包含另外一个文档的内联框架(即行内框架)把需要的文本放置在和之间,这样就可以应对无法理解iframe的浏IFrame对象IFrame对象代表一个HTML的内联框架在HTML文档中每出现一次,一个IFrame对象就会被创建。属性frameborder=1或0规定是否显示边框height=pixels或%…

    2022年10月28日
  • 补码的加减法运算_简述补码减法运算的规则

    补码的加减法运算_简述补码减法运算的规则补码的加减法运算本文内容参考自王达老师的《深入理解计算机网络》一书&lt;中国水利水电出版社&gt;一、补码加法:1、补码的加法运算两个机器数相加的补码可以先通过分别对两个机器数求补码,然后再相加得到,在采用补码形式表示时,进行加法运算可以把符号位和数值位一起进行运算(若符号位有进位,导致了益出,则直接舍弃),结果为两数之和的补码形式。示例1:求两个十进制数的和35+18。首先,规…

    2022年9月13日
  • 数学建模-二胎政策对中国人口的影响[通俗易懂]

    数学建模-二胎政策对中国人口的影响[通俗易懂]  研一的数学建模课上的关于“二胎政策对中国人口的影响”。研究中国人口,发现中国人口老龄化非常严重,如今假设不放开全面二胎,那么中国的未来真的非常令人堪忧。事实上,如今的单独二胎对人口的影响不是太多,每年添加100多万的人口,对于中国日益下降的人口增长率影响根本不大。   首先,本文通过搜集第六次人口普查的资料,将中国人口依照年龄组(5岁为一个年龄组)分为21个组,实行单独…

    2022年9月4日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号