UCOSii(一)——系统初始化
扫描二维码
随时随地手机看文章
之前看完了sdcc man和datasheet之后,用sdcc写了几个小程序。大部分时间都在干一些调式代码的事,就趁这段时间把UCOS复习一下吧。由于这是UCOS的第一篇,就来扯点闲话吧。
对于UCOSii,我其实没有在实际的项目中用到过。只是记得在以前看过一本UCOS作者自己写的书,书名已经忘记了。这种语言或者系统架构的设计者写的书往往看起来很有意思,因为作者不仅会给你解释代码,还会告诉你他为什么要这么做。这比生硬得给出流程图和注释的参考类书要更有趣味,不得不说国内的一些书看起来就像是使用说明,在网络日益发达的今天这些书的作用越来越小。比如我想知道一个基类的具体功能,搜索要比翻书快上许多。
UCOS的本名是μ/cOS,用希腊字母μ表示它的轻量级。其实它并不是一个免费的RTOS,只有当被用作教育用途时(往往被用来供大家学习操作系统),才可以有免费的授权。但是在目前的环境下,大家用μ/cOS来进行开发应该还是不要紧的。据我所知,我还没有听说过有使用未授权μ/cOS被起诉的。又由于μ/cOS的相关文档以及结构性代码库还算比较完善,因此也算是个在嵌入式设备上较为流行的操作系统。
二、如何取得UCOSUCOS的官网上有很多移植好的工程,还有一些相应的APP和Drive,这可以给大家节省不少时间。
UCOS下载中心:
http://micrium.com/downloadcenter/
三、系统初始化3.1 UCOS的任务作为一个可移植的嵌入式实时操作系统,μ/cOS的任务应该仅仅被限定为用户进程管理。它应该将硬件层尽量抽象掉,所以在main入口以前的芯片初始化(初始化系统时钟、初始化Flash读取,初始化芯片工作模式等等)、板卡初始化以及C环境的初始化都交于用户自己来进行。这个部分,通俗的做法是载入芯片厂商提供一些已经标准化的库函数,许多编译器也会在编译工程时自动链接一些startup_函数以引导C环境的运行。
3.3 时钟节拍要进行任务调度,内核的优先级必然要在各用户进程之上。它定期的打断各个任务运行,使自己突然占用CPU,并进行各种针对进程的操作。
这很自然让我们联想到中断,的确在Ucos中,常常用时钟中断来完成进程的管理工作。如果你不想在时钟中断里做太多的事,那么可以在中断产生时启动一个被注册为最高优先级的进程,由该进程来做调度工作。
3.4 UCOS的初始化流程对UCOS内核来说,所有的进程都是一个对象,所以要有描述进程属性的数据结构,以供内核控制进程。内核还要创建另外一些数据结构来作为标记各种自身需要记录和调用的属性,还有一些数据结构被创建用以算法辅助。
UCOS运行的第一步,就是初始化这些数据结构。
给这些数据结构分配空间以及设初值之后,用户可以注册几个最开始的用户进程。紧接着内核对刚注册的这几个进程进行初始化,系统就进入了一个多任务运行的常态。
UCOSii初始化的伪代码:
int main (void)
{ /* 关闭系统中断,防止在初始化时去跑中断服务程序而造成难以预料的问题。OS_ENTER_CRITICAL()宏*/
/* 初始化内核的数据结构 OSInit()函数 */
/* 注册用户进程 OSTaskCreate()函数*/
/* 系统启动 OSStart()函数 */}12345678910
OSInit会初始化内核用到的数据结构,了解这些数据结构对理解UCOS是必须的,这些数据结构这里只做个简要的描述,在之后的文章里再详细解释。
普通全局变量
用于描述一些内核的属性。一些计数器(比如计算一共进行了几次中断),状态器(比如是否已经进入多任务环境)。
OSPrioCur
OSPrioHighRdy
OSTCBCur
OSTCBHighRdy
OSTime
OSIntNesting
OSLockNesting
OSCtxSwCtr
OSTaskCtr
OSRunning
OSCPUUsage
OSIdleCtrMax
OSIdleCtrRun
OSIdleCtr
OSStatRdy
OSIntExitY
数组
就绪队列,用于调度算法。
链表
这个描述进程属性的数据结构一般叫做PCB(Process control block),UCOS里叫作TCB(Task control block)。所有的操作系统都会定义这样一个数据结构。