从零开始学习UCOSII操作系统2--UCOSII的内核实现
从零开始学习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 > 0void *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) */
#endifstruct os_tcb *OSTCBNext; /* 任务之间的双向链表的使用 */struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */#if OS_EVENT_ENOS_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 > 0OS_FLAG_NODE *OSTCBFlagNode; /* 指向事件标志组的指针 */
#endifOS_FLAGS OSTCBFlagsRdy; /* 当任务等待事件标志组时候, OSTCBFlagRdy是使任务进入就绪态的事件标志*/
#endifINT16U 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 <= 63INT8U OSTCBBitX; /* Bit mask to access bit position in ready table */INT8U OSTCBBitY; /* Bit mask to access bit position in ready group */
#elseINT16U 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 > 0INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */
#endif#if OS_TASK_PROFILE_EN > 0INT32U 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 > 1INT8U 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];
3、如何通过最高优先级的任务进行任务切换--进入中断,切换任务堆栈实现
(1)首先我们可以通过上面的机制得到当前系统中的最高的优先级任务是什么?
但是我们怎么通过这个最高级的优先级任务,把当前任务切换到最高级的优先级任务呢?
(2)里面涉及到一个重要的概念,每一种CPU中都有一些对应的CPU的寄存器。里面
有一个十分关键的程序指针,是用来跳转到相应的程序里面的。
上节说到每个任务都是一个无类型无返回值的函数,也就是可以通过函数指针的方式
跳转到你想要跳转的任务里面去执行。
(3)要实现上面的过程是通过一个函数来实现的OS_TASK_SW();
(4)下面根据下面的图进行任务切换的分析过程
此过程主要是分析,当程序中遇到更高的优先级的时候,CPU应该是怎么运行的。
(1)假设当前运行的任务是低优先级的任务,CPU程序寄存器中存在的一些寄存器都是低优先级的任务
(2)当程序运行到检测到高优先级的任务进入就绪状态的时候,此时CPU发送一些命令,把CPU当前的一些程序寄存器的内容复制到低优先级任务的堆栈中。也就是1过程。
(3)此时通过刚刚的就绪表的机制,可以从程序中得到最高优先级的任务,也就是2过程
(4)最后的过程3就是把刚刚的高优先级任务的堆栈指针复制到CPU的程序寄存器当中,实现任务的切换。
3、如何实现时间片的轮询的方法?
(1)根据上面的过程是实现可剥夺型内核的基础,但是有些是可以进行时间片轮询的方式的。
UCOSII本身是不支持同优先级有多个任务的,UCOSIII是支持的,所以实现这个机制的方案
就是刚刚上面提到的事件控制块的灵活使用。
(2)刚刚的位图是指向某一个任务的,但是UCOSIII的位图是指向一个队列,在同一个队列中优先级
相同,也就是说,同一优先级的任务应该是按时间片轮询的方式的。
(3)每个处理器中都会有一个时钟节拍,在时钟节拍中调用任务切换的核心函数,
在同一个优先级不断的进行轮询即可实现时间片轮询。
从零开始学习UCOSII操作系统2--UCOSII的内核实现相关推荐
- 从零开始学习UCOSII操作系统13--系统移植理论篇
从零开始学习UCOSII操作系统13--系统移植理论篇 1.什么是系统移植? (1)UCOSII移植到不同的处理器上,所谓的移植就是将一个实时的内核能在其他的微处理器或者微控制器上运行. 为了方便移植 ...
- 手把手以实例教你使用DOSBOX入门UCOS-II操作系统
手把手以实例教你在DOSBOX模拟器上入门UCOS-II操作系统(包含各种DOS命令操作.makefile文件和BAT批处理文件的使用) 目录 前言 一.说明 二.E盘根目录下放置BC31和SOFTW ...
- LINUX内核分析第二周学习总结——操作系统是如何工作的
LINUX内核分析第二周学习总结--操作系统是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...
- 慕课嵌入式系统(第九章.ucos-ii操作系统实验)
慕课电子科技大学.嵌入式系统.第九章.嵌入式实时操作系统实验.ucos-ii操作系统实验 0 目录 9 嵌入式实时操作系统实验 9.1 ucos-ii操作系统实验 9.1.1课堂重点 9.1.2测试与 ...
- Devops系统化,从零开始学习容器技术(更新中)
文章目录 Devops系统化,从零开始学习Docker.K8s 一.容器技术和Docker简介 1.1 Docker导学 1.2 容器技术概述 二.Docker环境的各种搭建方法 2.1 Docker ...
- Linux 从零开始学习笔记
从零开始学习Linux,记录笔记,担心自己以后会忘,也供大家茶余饭后,闲来无事看看,自己的理解只能到这,能力有限.也希望大家可以指出我的错误,让我可以有一点点进步,以后会一直更新,同时也希望大家可以收 ...
- python新手教程 从零开始-Python零基础从零开始学习Python十分钟快速入门
原标题:Python零基础从零开始学习Python十分钟快速入门 学习Python的,都知道Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.Python是一种动态解释型的 ...
- 从零开始学习jQuery (九) jQuery工具函数
本系列文章导航 从零开始学习jQuery (一) 开天辟地入门篇 从零开始学习jQuery (二) 万能的选择器 从零开始学习jQuery (三) 管理jQuery包装集 从零开始学习jQuery ( ...
- 谈谈如何学习Linux操作系统
谈谈如何学习Linux操作系统 献给初学者:为了能把这篇不错的文章分享给大家.所以请允许我暂时用原创的形式展现给大家. @hcy 更多资源:http://blog.sina.com.cn/iihcy ...
最新文章
- pku 3411 Paid Roads DFS+灵活技巧卡节点访问次数
- Hibernate Session的Flush模式
- RedHat 7.2配置本地yum源
- 2016奥运男篮分组
- ENSP如何开启服务器的http_如何使用HTTP模块在Node.js中创建Web服务器(上)
- coco与voc相互转化
- Guns 添加功能实现_入门试炼05
- 电子支付公司Nuvei支持BTC等近40种加密货币
- 浮动特性-脱标(HTML、CSS)
- VMware虚拟机win7安装教程
- 《第一堂棒球课》:王牌左外野·棒球7号位
- 域自适应(Domain Adaptation)简介
- Mysql索引结构全维度比较
- npm run serve stage1@0.1.0 serve vue-cli-service serve node:internal/modules/cjs/loader:936
- Python+Vue计算机毕业设计网上美妆购物商城8k7w5(源码+程序+LW+部署)
- 杭州电子科技大学程序设计竞赛(2016’12)- 网络同步赛
- 【​观察】纺织印花行业转型与升级提速 爱普生蒙娜丽莎掀起技术迭代革命...
- css3 火焰文字,Css3字体做出火焰效果的实现步骤
- 《摄影测量学基础》光束法MATLAB程序
- 有道云笔记无法同步至本地电脑解决方法
热门文章
- 车截导航显示服务器错误怎么办,车载导航常见故障
- UEA数据集和UCR数据集的处理
- python基于pingouin包进行统计分析:使用tost函数执行独立双样本双单侧检验(TOST)、以dataframe的形式输出分析结果(包含p值、自由度、bound等)
- 折半查找法(二分法)流程图
- 关于阿里云服务器ECS与域名的绑定详细过程介绍
- YYModel 简介与使用
- 北邮计算机学院学生会军训,在北京邮电大学2015级本科生军训结训典礼上的讲话...
- 实训...实训...
- 【功能安全】【AutoSAR】安全通信机制:E2E保护
- Amazon DynamoDB