ucos-ii是一个多任务的操作系统,其最大优点即为实时性。任务通常是一个无限的循环,其中包括了用户代码,而实时性即指最快的响应优先级最高的任务。

确实,对于一个初步接触ucos-ii的新手来讲,想要完全理解是要花时间的。

我们想用ucos-ii,在移植成功后(以后在写移植方面吧),我们首先就得进行初始化,ucos是用函数OSInit()来完成的。

调用OSInit()的目的是建立一些数据结构,比如初始化OS_MAX_TASK数目的OSTCBFreelist,以及用户定义的各项OSEeventFreelist,OSQFreelist,OSFlagFreelist,OSMemFreelist(将OS_MAX_???设置为实际需求数目可减小内核RAM量,以后在写篇移植方面的文章详谈吧)。以OSTCBFreelist 为例,这可看作一条缓存链表。一开始,列表中指针全部指向NULL,当任务建立时,就从OSTCBFreelist 上取出一块赋予给任务控制块。

显然,这样做的好处在于:缓冲池更快的将事先已初始化的内存空间有序的赋予给任务。这样,我们用OSTaskCreate()或OSTaskCreateExt() 建立任务时,这两个函数会调用底层的OS_TCBInit(),就从OSTCBFreelist中分配了一个任务控制块OS_TCB。

初始化ucos-ii后,我们就该建立任务了。在启动OSStart()之前,一定要建立一个应用任务。假设我们已建立了若干个任务,就可以启动OSStart()了。

OSStart()的作用就是找一个优先级最高的任务的TCB,然后运行。这就有了两个疑惑:

1.       怎样找到优先级最高的任务;

2.       任务控制块TCB有些什么东西。

我们先来解决第一个问题吧。

首先,任务一被建立,它们就会被赋予相应的堆栈,相应的优先级prio等。然后就进入就绪态等待运行。内核根据优先级作了一个就续表。内核只需找出进入就绪表中优先级最高的任务进行运行即可。

非常奇妙的事就是作者构思了一套机理,一方面可由任务优先级推知其在就绪表中的位置,另一方面可由就绪表中的置位推知表中的最高优先级任务。

其原理是这样的:

作者创建了一个8位变量OSRdyGrp 和一个8位变量数组OSRdyTbl[8]; 那么要使一个优先级为prio的任务进入就续表就需要在相应位置置1.

OSRdyGrp  |=  OSMapTbl[prio >> 3];

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

当然,一开始很难让人接受,我们先来讲讲prio。由于prio最高为63,所以其8位Bit中高两位一定为0. 这样的话,prio>>3就为00000YYY,而Y就代表了就绪表中的行数。不过这需要一层转换,即通过OSMapTbl[].(读者可将其看作调制器理解)。

OSMapTbl[0]=00000001

OSMapTbl[1]=00000010

OSMapTbl[2]=00000100

………….

OSMapTbl[7]=10000000

Y即00YYY000,将通过OSMapTbl[]置位OSRdyGrp;同样,prio & 0x07代表了X(00000XXX),将同样置位OSRdyTbl[prio>>3]了。

(读者可能已经看出了,切记这里的置一是置8位Bit中的1位Bit.)

我来举个例子吧,如将prio为8的任务在就绪表中置位。

8 转换成二进制为 00(001)(000) ,则Y = prio>>3=1,那么可查OSMapTbl[]表得出OSMapTbl[prio>>3] = 00000010;所以它通过OSRdyGrp |= OSMapTbl[prio>>3];在OSRdyGrp (_ _ _ _ _ _ A _) 的A位置1,即相当于通知就绪表,在就续表的第二行会有任务就绪;

那么 X= prio & 0x07 = 0,则OSMapTbl[prio & 0x07] = 00000001;所以它通过OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];在OSRdyTbl[1](_ _ _ _ _ _ _ B)中的B位置1。

那么又怎样从就绪表中找出最高优先级的任务呢?

理解了上面所述的置位,那么这个问题也就大致相同了:我们通过借助OSMapTbl[]来编码使其进入就绪态,这儿又将借助OSunMapTbl[](读者可看作解调器)来解码,使系统找出优先级最高的任务。

找出所有就绪表中优先级最高的任务:

Y = OSUnMapTbl[ OSRdyGrp ];

X = OSUnMapTbl[ OSRdyTbl[Y] ];

那么prio =Y *8 + X

OSUnMapTbl[]表如下:

INT8U  const  OSUnMapTbl[256] = {

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

};

在举一个例子来理解吧。比如同时有 6 7 8 9 四个任务就绪。

那么OSRdyGrp = 00000011; 找出最高优先级任务所在行,Y = OSUnMapTbl[ OSRdyGrp ]; 查表会得到0,即Y=0,这里表明优先级最高的任务在就绪表中的第一行。然后再找出其在第一行的位置OSRdyTbl[Y] = OSRdyTbl[0] =11000000;

通过查表可得 X = OSUnMapTbl[ OSRdyTbl[0] = 6

则[prio = Y *8 + X = 6 即就续表中优先级最高的任务为优先级为6的任务。

想想一般的从头到尾的查找,再想想这种方法,真的很值得欣赏。

再回头看看第二个问题吧,来讲讲OS_TCB.

可以这样理解:TCB就是任务的信息,以确保任务在切换时无误差地还原执行任务。TCB这个结构体其下有指向当前任务堆栈栈顶的指针OSTCBStkptr,双向链表指针OSTCBNext和OSTCBPrev,优先级OSTCBPrio等。那么系统找到最高优先级的任务后是怎样通过TCB进行任务切换的呢?

这里还应介绍两个指针,OSTCBCur和OSTCBHighRdy。我们通过任务优先级的值,查找任务控制块优先级表OSTCBPrioTbl[],得到指向相应任务控制块OS_TCB,用OSTCBHighRdy得到了即将执行任务的TCB,然后进行任务切换。

我们来看看系统是怎样保存当前CPU值以及重新装入任务。首先,我们来了解一下OS_TASK_SW()这个函数。这其实就是一个软中断或者陷阱中断,执行切换任务时,中断就将依次保存PSW和PC的当前值,通用寄存器的值,最后将被挂任务的堆栈指针保存在OS_TCB中,这时有OSTCBCur->OSTCBStkPtr指向了SP。当遇到要切换的任务时,将OSTCBCur指向了OSTCBHighRdy(即将执行的任务),由于保存了CPU的值OSTCBCur->OSTCBStkPtr此时指向的就是该任务的SP了。这样,重新装入只需从反方向弹出寄存器值,然后通过中断返回指令把PC和PSW装回到CPU中,任务便重新运行了。

那么任务的调度就应该是这样的:任务以各种方式(得到某资源或延时到达等)进入就绪态,系统根据就续表找到了优先级最高的任务,然后将被挂起于将执行任务的TCB分别保存与载入,达到了任务的切换。

任务切换函数其实就是保存被挂起任务的寄存器值,把被挂起任务的SP保存在被挂起任务TCB的OSTCBStkPtr。然后将TCBCur指向任务栈,依次弹出将执行任务的寄存器值,然后中断返回。

ucos-ii任务切换是模拟的中断,当然也存在用户自定义的中断函数,时钟节拍就是中断。只不过ucos-ii中的中断在退出中断时还需判断是否有优先级更高的任务就绪,如时钟节拍,就像脉搏一样,利用定时的中断来标志或给邮箱等等发消息,以通知延时任务就绪。

PS : ucos-ii的内核而言,还可以写很深,由于时间问题,不在多述了。第一次写博文,感觉很累啊。第一次我坚持写完这篇文章,其实应该分好几篇来讲诉,这样的话,我也可以轻松点,也可以将问题讲述得更彻底点。

ucos-ii操作系统相关推荐

  1. 基于STM32的简易示波器的UCOS II嵌入式实时操作系统实现

    基于STM32的简易示波器的UCOS II嵌入式实时操作系统实现 在基于STM32的示波器的实现的基础上,在STM32上移植UCOS II嵌入式实时操作系统. 在UCOS II操作系统中将各个功能分发 ...

  2. UCOS II移植到STM32F103开发板

    早期嵌入式开发没有嵌入式操作系统的概念 ,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念.通常把程序分为两部分:前台系统和后台系统. 简单的小系统通常是前后台系统,这样的程序包 ...

  3. 51单片机中使用ucos ii的优缺点(好文)

    摘要:近年来,在单片机系统中嵌入操作系统已经成为人们越来越关心的一个话题.本文通过对一种源码公开的嵌入式实时操作系统ucos ii的分析,以51系列单片机为例,阐述了在单片机中使用该嵌入式操作系统的优 ...

  4. lwip协议栈在linux运行,LwIP协议栈在uCOS II下的实现

    1.概述: LwIP协议栈在设计时就考虑到了将来的移植问题,因此把所有与硬件.OS.编译器相关的部份独立出来,放在ucosii&LwIPsource etlwiparch目录下.因此LwIP在 ...

  5. 用C语言写ucos中断服务程序,在ARM处理器上移植uCOS II的中断处理

    uCOS II是一个源码公开.可移植.可固化.可剪裁和抢占式的实时多任务操作系统,其大部分源码是用ANSI C编写,与处理器硬件相关的部分使用汇编语言编写.总量约200行的汇编语言部分被压缩到最低限度 ...

  6. ucos II任务管理之一:挂起任务

    Ucos II 任务管理之一 创建好了任务之后,就已经初步跨进了ucos II 的编程了.随着进一步的编程,发现学会创建了任务还是不够的. 在我的项目里,需要实现485通信功能,我创建了任务1用于串口 ...

  7. ucos II任务管理之三:删除任务

    ucos II任务管理之三:删除任务 有了前面的经历之后,mcu21决定全面地学习了任务的管理.这样在项目编程中才能做到"信手拈来". 在ucos II 里,创建一个任务之后,可以 ...

  8. ucos II 创建第一个任务之一

    Ucos II创建第一个任务 我们已经从远处欣赏过ucos II 的身材,现在可以近距离地欣赏Ucos II性感的局部了. 任务是什么? 有一句话:CPU不同的时刻段总是在执行着优先级最高的任务.所以 ...

  9. ucos ii堆栈大小检测

    在使用ucos ii时经常会有疑问,这个堆栈该给多大,虽然ucos ii 自带了任务堆栈检测,但是我觉得太麻烦了,而且还会占用资源,我投机取巧的使用内存是否为0来判断堆栈是否使用过,进而检测出堆栈的最 ...

  10. IAR中移植UCOS II系统以及sourceInsight 使用

    ucos 学习笔记 1 sourceInsight 使用 CSDN参考链接 新建工程 第一步:project中new project 第二步:在高亮部分输入工程的地址,工程文件夹与IAR工程文件夹放在 ...

最新文章

  1. LNMP安装与启动脚本编写
  2. 前端实习生笔试_2016春网易前端暑期实习生笔试面经(二面已挂)
  3. u2020 华为_华为5G网管U2020常用MML命令(很实用)
  4. 使用入站适配器公开HTTP Restful API。 第1部分(XML)
  5. 最简易上手的numpy学习笔记二
  6. TensorFlow简介:向量对象
  7. 零基础入门Python3-循环详解
  8. 20145302张薇《Java程序设计》第三周学习总结
  9. CheerpJ相当于一个容器,效果类似Applet
  10. 【ccpc网络赛】Tree and Permutation【1009】【树上+组合数学】
  11. 因果信号的傅里叶变换_常用信号的傅里叶变换对
  12. The Django Book
  13. 开源微博系统Xweibo的一些主要函数注释
  14. SketchUp + Ruby 二次开发初识
  15. DLL注入之全局钩子注入
  16. wdr7660虚拟服务器设置,TP-Link TL-WDR7660路由器密码设置
  17. 密码破解---实验七:本地系统密码破解
  18. angular 部署的项目自定义访问路径,不使用root根目录的配置
  19. C++各大有名库的介绍(一)
  20. hexo个人博客搭建

热门文章

  1. 快手新人直播如何做到不冷场
  2. 【洛谷P3014】Cow Line
  3. znpc改版前后网址修改办法
  4. 基于STM32F103C8T6的MPU6050调试与数字运动处理器DMP
  5. 三种监控 Kubernetes 集群证书过期方案
  6. 网络七层模型和TCP/IP分层模型
  7. CTF论剑场学习——杂项
  8. 同或门(XNOR)电路的网络学习
  9. 写给想要开始跑步的人
  10. 兆芯服务器芯片,兆芯 ZX-200 IO扩展芯片