当前位置:首页 > 嵌入式 > 嵌入式软件
[导读]μC/OS-II 是一个源代码公开、可移植、可裁剪的实时多任务操作系统,具有稳定可靠、实时性好等优点,是专门针对微处理器和微控制器设计的实时内核,它的内核可以做到很小

μC/OS-II 是一个源代码公开、可移植、可裁剪的实时多任务操作系统,具有稳定可靠、实时性好等优点,是专门针对微处理器和微控制器设计的实时内核,它的内核可以做到很小,很适合在单片机系统上移植。移植了μC/OS-II 的嵌入式系统可以使各个任务独立工作,互不干涉,很容易实现准时而且无误执行,使实时应用程序的设计和扩展变得容易,使应用程序的设计过程大为减化。在这个星期内,我通过对禁用了邮箱、队列、文件系统的最简单的μCOS-ii操作系统进行了学习,现将收获分享如下。

μCOS-ii运行过程

μCOS-ii的主函数不到十行代码,但是因为其高度的结构化以及良好的函数封装,对其运行过程的了解对于学习μCOS-ii的编程思想以及设计思路具有重大的意义。

我通过将μCOS-ii代码移植到SST89V564RD单片机中,并且利用TI公司的温度传感器TMP124创建了两个任务:读TMP122数据、向串口发送读取的温度值。要求两个任务轮流执行,读TMP122的优先级高于向串口发送数据的优先级。

1 系统初始化

在μCOS-ii中,系统初始化可以分为全局变量初始化、创建空闲任务任务、堆栈初始化、任务控制块初始化等部分内容。

全局变量初始化。由于μCOS-ii操作系统中定义了众多与系统参数有关的全局变量,因此全局变量的初始化包含众多内容。这些系统参数的初始化大都被封装 在OSInit()函数中。尤其要注意的是,在OSInit函数中,OSRunning变量一定要被定义成FALSE,否则在OSStart函数中,系统 无法启动创建的任务,系统因此变成了一个有始有终的函数,创建的任务永远得不到执行。在实际运行过程中表现为主函数运行一次之后,系统不再运行。另外需要 注意的是OSTCBCur、OSTCBList等这几个变量需要定义为(OS_TCB DT_XDATA *)0的类型。因为这些变量是指向结构体TCB(Task Control Block)的指针,并不是数字〇。

创建空闲任务。创建空闲任务包括进入临界区、任务堆栈初始化、TCB初始化、退出临界区等内容,大部分是一些简单的赋值操作,比较简单,不再赘述。其中OSRdyGrp |= ptcb->OSTCBBitY; OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;这两句话要尽量看懂。因为这两句话牵扯到后面OSUnMapTbl这个矩阵的理解。其含义为一旦任务就绪队列中有"1"(即对应的任务就绪),则相应的任务组OSRdyGrp 相应的位变成1,OSRdyTbl中的相应的位也变成1.

堆栈初始化以及任务控制块初始化。比较容易理解,简单的赋值操作。不过在堆栈初始化中的ppdata = ppdata;opt = opt; 以及任务控制块初始化中的pext= pext; stk_size= stk_size;pbos=pbos;opt=opt; id= id;这些语句刚开始的时候很令人费解。其实这些是防止编译器不断的报warning,以免影响正常的调试的。

2 任务创建

同上述创建空任务大体雷同。需要注意的是此时操作系统的OSRunning变量还是处于FALSE状态,因此创建任务的过程中,操作系统并没有开始运行。 这就是为什么操作系统在开始运行的时候不是选择第一个创建的任务开始运行,而是从所有的任务里面选择优先级最高的运行的原因。

3 任务调度

任务调度是从OSStart函数开始的。具体包括OSStart、OsStartHighRdy、Task1~n、OSTimeDlyHMSM、OSSched等函数,其中任务交换是在汇编语言文件的OS_TASK_SW函数中运行的。

OsStart在整个系统运行的过程中只会运行一次。在系统创建任务之后运行。主要目的是从任务就绪表中挑选出优先级最高的任务,并开始运行优先级最高的任务。

OsStartHighRdy为asm文件中的一部分。主要是堆栈的操作。目的是要把高优先级任务的任务堆栈复制到寄存器中,为即将开始的运行最高优先级的任务做好准备。

Task1~n。Task为一个无限循环函数。虽然是无限循环函数,但是与平常前后台系统中的无限循环具有区别。因为μCOS-ii操作系统并不是一个像 Linux那样的时间片轮流处理的操作系统,它仅仅是一个处理完一部分内容之后再去处理另一部分内容的实时操作系统。这就要求在每一个任务的每一个无限循 环中都要加一个调用OSSched函数的函数。

OSTimeDlyHMSM主要是为用户提供一个良好的借口,将用户输入的时、分、秒、毫秒这四个数据转换成系统的滴答数,然后调用OSTimeDly实 现。在OSTimeDly中调用OSSched,确保系统的实时性。OSSched函数结构也类似于OSStart,主要是计算出任务就绪表中最高优先级 的任务,通过OS_TASK_SW中的堆栈的操作实现任务的交换。

μCOS-ii查找最高优先级算法的实现

指导思想:以空间换时间。

在查看源代码的过程中,最令人费解的或许就是OSUnMapTbl这个矩阵了。现将此矩阵复制如下:

INT8U const DT_XDATA OSUnMapTbl[] = {

0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,

4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0

};

在了解这个矩阵的工作原理之前,我们有必要了解一下几个变量的含义:

OSRdyGrp 是一个8位的unsigned char型数。由于该μCOS-ii系统最多允许prio为63,也就是说最多允许有64个优先级。64个优先级被分成了八组,每组有八个优先级。如果有 任何一组中的任务进入了就绪状态,则该组所对应的位变为1。比如优先级为4,23,56的任务同时进入了就绪态,则对应第0,2,7组中有任务进入了就绪 态,则此时OSRdyGrp 应为 10000101。

OSRdyTbl为一个有8个元素的8位数的数组,分别为OSRdyTbl[0]...OSRdyTbl[7]。从OSRdyTbl[0]到 OSRdyTbl[7]的每一位数对应相应优先级的任务是不是进入了就绪态。还是上面的例子,假如优先级为4,23,56的任务进入了就绪态,则 OSRdyTbl[0]的第4位,OSRdyTbl[2]的第7位,OSRdyTbl[7]的第0位变成1,其他的位仍然保持零。

介绍完两个变量之后,就可以很容易理解这个矩阵的作用了。矩阵的第i个数字表示用二进制表示的i中1所出现的最小位数。比如对于矩阵的第48个数字,48用二进制表示为00110000,在第4位以及第5位中出现了1,故去最小值,则OSUnMapTbl[48]=4 。也就是说,通过查这个矩阵得到的是最小的出现1的位数。假如对于OSRdyGrp 来说,在OSRdyGrp 等于48的情况下,意味着第四组与第五组中有任务处于就绪状态,则通过此表可以得出最高优先级的任务在第四组中。假如对于OSRdyTbl来 说,OSRdyTbl[4]表示第四组中每一个元素是不是处于就绪态。还是拿48来打比方,假如OSRdyTbl[4]等于48,有48用二进制表示为 00110000可得第四位与第五位中有两个任务处于就绪态,此时查询OSUnMapTbl[48]=4可得优先级最高的任务处于第四位上。由此很容易理 解这两行代码:

y= OSUnMapTbl[OSRdyGrp];

x = OSUnMapTbl[OSRdyTbl[y]];

因此得到的y为最高优先级所在的组号。X为最高优先级所在的组中最高优先级所在的组的组号。由于每组有8个成员,对于y组第x个来说,优先级自然是 8*y+x 。由此得到了最高优先级。下面的代码不难理解。

OSPrioHighRdy = (INT8U)((y << 3) + x);

此外,因为这个矩阵无论在何种情况下,都是不变的,因此个人认为原μCOS-ii系统中定义为DT_XDATA完全没有必要,只是增加了系统的开销。因此我尝试将此变量类型改成DT_CODE ,经过运行TMP124的尝试,系统运行几十分钟后仍然正常。因此得出了此处可以改进的建议。而且改进之后系统的占用xdata从600多字节减少到400多字节,系统资源占用减少很明显。

可能编写μCOS-ii的工程师为了提高可移植性,将OSUnMapTbl定义为DT_XDATA吧。仅仅猜测而已。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

  本文主要搭建一个多生理参数测量系统的数据处理平台,在FPGA中嵌入一个32位Nios II软核处理器,用于控制数据的传输、存储及显示。主要完成了此数据处理平台硬件系统的定制及编写相应程序,以控制数

关键字: NIOS ii 生理

据9月9日消息,索尼Xperia 5 Ⅱ将于9月17日正式发布。 该机现已通过FCC认证,FCC文件显示索尼Xperia 5 Ⅱ配备的充电器型号为Sony UCH32,支持18W快充。

关键字: xperia 5 1 ii

7 月 14 日消息 苹果 Apple IIe 电脑在 37 年前的 1983 年问世,但不要以为它不能胜任现代的任务。有 Twitter 用户近日展示了如何让 Apple IIe 实现现代化的的任

关键字: apple ii

华硕在2019年经历了一年的复苏,其坚实的Zenfone 6和强大的ROG Phone II游戏引擎将于今年问世。 尽管Zenfone在11月收购了Android 10,但该公司现在正为ROG Phone II推出稳定的...

关键字: 10 Android ii phone rog 华硕

Linux内核对其驱动程序进行了修改,来支持Macintosh II系统上的Apple Desktop Bus。

关键字: ii Linux macintosh 驱动

在这篇文章中,小编将为大家带来华硕全新ROG Zenith II Extreme的相关报道。如果你对本文即将要讲解的内容存在一定兴趣,不妨继续往下阅读哦。

关键字: extreme ii rog zenith 华硕 tda21490

不考虑这两年来处理器从4核达大幅提升到8核甚至16核的情况,单从CPU性能来看,大家普遍认为过去几年CPU都是在挤牙膏升级,原因都懂得。那问题来了,如果是跨度十年的话,那如今的CPU到底比09年的CP

关键字: 810 ii x86 处理器 挤牙膏 酷睿 phenom

主板产品一直是人们的关注焦点之一,因此在这篇文章中,小编将为大家带来华硕ROG ZENITH II EXTREME。如果你想了解它的详细内容,请继续阅读。

关键字: extreme ii rog zenith 主板 华硕

AMD刚刚发布的第三代线程撕裂者用上了7nm Zen 2,不过接口改为新的sTRX4,必须搭配新的TRX40芯片组主板。 华硕率先发布了三款全新的TRX40主板,分别是玩家国度系列的ROG ZENIT

关键字: extreme ii rog zenith 主板 图赏 三代撕裂者 坐骑

到目前为止,我们已经看过太多关于 iPhone 11 的相机对比评测了,例如此前的 Pixel 4 夜景对比、Mate 30 Pro 相机对比。而最近,国外摄影 UP 主则进行了一项不太一样的相机对比

关键字: 11 ii iPhone mark pro 佳能 实拍 1dx
关闭
关闭