初级程序员指南:uC/OS-II 的使用手册在这里

uC/OS-II 简介程序员

uC/OS-II是一种基于优先级的可抢先的硬实时内核。自从92年发布以来,在世界各地都得到了普遍的应用,它是一种专门为嵌入式设备设计的内核,目前已经被移植到40多种不一样结构的CPU上,运行在从8位到64位的各类系统之上。尤为值得一提的是,该系统自从2.51版本以后,就经过了美国FAA认证,能够运行在诸如航天器等对安全要求极为苛刻的系统之上。鉴于uC/OS-II能够免费得到代码,对于嵌入式RTOS而言,选择uC/OS无疑是最经济的选择。数组

 

2安全

uC/OS-II 应用程序基本结构数据结构

应用uC/OS-II,天然要为它开发应用程序,下面论述基于uC/OS-II的应用程序的基本结构以及注意事项。函数

 

每个uC/OS-II应用至少要有一个任务。而每个任务必须被写成无限循环的形式。如下是推荐的结构:源码分析

void task ( void* pdata )性能

{学习

INT8U err;操作系统

InitTimer(); // 可选设计

For( ;; )

{

// 你的应用程序代码

……。

……。.

OSTimeDly(1); // 可选

}

}

 

以上就是基本结构,至于为何要写成无限循环的形式呢?那是由于系统会为每个任务保留一个堆栈空间,由系统在任务切换的时候换恢复上下文,并执行一条reti 指令返回。若是容许任务执行到最后一个花括号(那通常都意味着一条ret指令)的话,极可能会破坏系统堆栈空间从而使应用程序的执行不肯定。换句话说,就是“跑飞”了。嵌入式学习企鹅意义气呜呜吧久零就易,因此,每个任务必须被写成无限循环的形式。程序员必定要相信,本身的任务是会放弃CPU使用权的,而不论是系统强制(经过ISR)仍是主动放弃(经过调用OS API)。

 

如今来谈论上面程序中的InitTimer()函数,这个函数应该由系统提供,程序员有义务在优先级最高的任务内调用它并且不能在for循环内调用。注意,这个函数是和所使用的CPU相关的,每种系统都有本身的Timer初始化程序。在uC/OS-II的帮助手册内,做者特意强调绝对不能在OSInit()或者OSStart()内调用Timer初始化程序,那会破坏系统的可移植性同时带来性能上的损失。

 

因此,一个折中的办法就是象上面这样,在优先级最高的程序内调用,这样能够保证当OSStart()调用系统内部函数OSStartHighRdy()开始多任务后,首先执行的就是Timer初始化程序。或者专门开一个优先级最高的任务,只作一件事情,那就是执行Timer初始化,以后经过调用OSTaskSuspend()将本身挂起来,永远再也不执行。不过这样会浪费一个TCB空间。对于那些RAM吃紧的系统来讲,仍是不用为好。

 

3

一些重要的uC/OS-II API介绍

任何一个操做系统都会提供大量的API供程序员使用,uC/OS-II也不例外。因为uC/OS-II面向的是嵌入式开发,并不要求大而全,因此内核提供的API也就大多和多任务息息相关。主要的有如下几类:

1)任务类

2)消息类

3)同步类

4)时间类

5)临界区与事件类

 

我我的认为对于初级程序员而言,任务类和时间类是必需要首先掌握的两种类型的API。下面我就来介绍比较重要的:

 

1) OSTaskCreate函数

这个函数应该至少再main函数内调用一次,在OSInit函数调用以后调用。做用就是建立一个任务。目前有四个参数,分别是任务的入口地址,任务的参数,任务堆栈的首地址和任务的优先级。调用本函数后,系统会首先从TCB空闲列表内申请一个空的TCB指针,而后将会根据用户给出参数初始化任务堆栈,并在内部的任务就绪表内标记该任务为就绪状态。最后返回,这样一个任务就建立成功了。

 

2) OSTaskSuspend函数

这个函数很简单,一看名字就该明白它的做用,它能够将指定的任务挂起。若是挂起的是当前任务的话,那么还会引起系统执行任务切换先导函数OSShed来进行一次任务切换。这个函数只有一个参数,那就是指定任务的优先级。那为何是优先级呢?事实上在系统内部,优先级除了表示一个任务执行的前后次序外,还起着分别每个任务的做用,换句话说,优先级也就是任务的ID。因此uC/OS-II不容许出现相同优先级的任务。

 

3) OSTaskResume函数

这个函数和上面的函数正好相反,它用于将指定的已经挂起的函数恢复成就绪状态。若是恢复任务的优先级高于当前任务,那么还为引起一次任务切换。其参数相似OSTaskSuspend函数,为指定任务的优先级。须要特别说明是,本函数并不要求和OSTaskSuspend函数成对使用。

 

4) OS_ENTER_CRITICAL宏

不少人都觉得它是个函数,其实否则,仔细分析一下OS_CPU.H文件,它和下面立刻要谈到的OS_EXIT_CRITICAL都是宏。他们都是涉及特定CPU的实现。通常都被替换为一条或者几条嵌入式汇编代码。因为系统但愿向上层程序员隐藏内部实现,故而通常都宣称执行此条指令后系统进入临界区。其实,它就是关个中断而已。这样,只要任务不主动放弃CPU使用权,别的任务就没有占用CPU的机会了,相对这个任务而言,它就是独占了。因此说进入临界区了。这个宏能少用仍是少用,由于它会破坏系统的一些服务,尤为是时间服务。并使系统对外界响应性能下降。

 

5) OS_EXIT_CRITICAL宏

这个是和上面介绍的宏配套使用另外一个宏,它在系统手册里的说明是退出临界区。其实它就是从新开中断。须要注意的是,它必须和上面的宏成对出现,不然会带来意想不到的后果。最坏的状况下,系统会崩溃。咱们推荐程序员们尽可能少使用这两个宏调用,由于他们的确会破坏系统的多任务性能。

 

6) OSTimeDly函数

这应该程序员们调用最多的一个函数了,这个函数完成功能很简单,就是先挂起当起当前任务,而后进行任务切换,在指定的时间到来以后,将当前任务恢复为就绪状态,可是并不必定运行,若是恢复后是优先级最高就绪任务的话,那么运行之。简单点说,就是能够任务延时必定时间后再次执行它,或者说,暂时放弃CPU的使用权。一个任务能够不显式的调用这些能够致使放弃CPU使用权的API,但那样多任务性能会大大下降,由于此时仅仅依靠时钟机制在进行任务切换。一个好的任务应该在完成一些操做主动放弃使用权,好东西要你们分享嘛!

 

4

uC/OS-II 多任务实现机制分析

前面已经说过,uC/OS-II是一种基于优先级的可抢先的多任务内核。那么,它的多任务机制到底如何实现的呢?了解这些原理,能够帮助咱们写出更加健壮的代码来。因为咱们面向的初级程序员,本文不打算写成又一篇uC/OS-II的源码分析,那样的文章太多了,打算从实现原理的角度探讨这个问题。

 

首先咱们来看看为何多任务机制能够实现?其实在单一CPU的状况下,是不存在真正的多任务机制的,存在的只有不一样的任务轮流使用CPU,因此本质上仍是单任务的。但因为CPU执行速度很是快,加上任务切换十分频繁而且切换的很快,因此咱们感受好像有不少任务同时在运行同样。这就是所谓的多任务机制。

 

由上面的描述,不难发现,要实现多任务机制,那么目标CPU必须具有一种在运行期更改PC的途径,不然没法作到切换。不幸的是,直接设置PC指针,目前尚未哪一个CPU支持这样的指令。可是通常CPU都容许经过相似JMP,CALL这样的指令来间接的修改PC。

 

咱们的多任务机制的实现也正是基于这个出发点。事实上,咱们使用CALL指令或者软中断指令来修改PC,主要是软中断。但在一些CPU上,并不存在软中断这样的概念,因此,咱们在那些CPU上,使用几条PUSH指令加上一条CALL指令来模拟一次软中断的发生。

 

回想一下你在微机原理课程上学过的知识,当发生中断的时候,CPU保存当前的PC和状态寄存器的值到堆栈里,而后将PC设置为中断服务程序的入口地址,再下来一个机器周期,就能够去执行中断服务程序了。

 

执行完毕以后,通常都是执行一条RETI指令,这条指令会把当前堆栈里的值弹出恢复到状态寄存器和PC里。这样,系统就会回到中断之前的地方继续执行了。那么设想一下?若是再中断的时候,人为的更改了堆栈里的值,那会发生什么?或者经过更改当前堆栈指针的值,又会发生什么呢?若是更改是随意的,那么结果是没法预料的错误。由于咱们没法肯定机器下一条会执行些什么指令,可是若是更改是计划好的,按照必定规则的话,那么咱们就能够实现多任务机制。事实上,这就是目前几乎全部的OS的核心部分。不过他们的实现不像这样简单罢了。

 

下面,咱们来看看uC/OS-II在这方面是怎么处理的。在uC/OS-II里,每一个任务都有一个任务控制块(Task Control Block),这是一个比较复杂的数据结构。在任务控制快的偏移为0的地方,存储着一个指针,它记录了所属任务的专用堆栈地址。事实上,在uC/OS-II内,每一个任务都有本身的专用堆栈,彼此之间不能侵犯。这点要求程序员在他们的程序中保证。通常的作法是把他们申明成静态数组。并且要申明成OS_STK类型。当任务有了本身的堆栈,那么就能够将每个任务堆栈再那里记录到前面谈到的任务控制快偏移为0的地方。

 

之后每当发生任务切换,系统必然会先进入一个中断,这通常是经过软中断或者时钟中断实现。而后系统会先把当前任务的堆栈地址保存起来,仅接着恢复要切换的任务的堆栈地址。因为那个任务的堆栈里必定也存的是地址(还记得咱们前面说过的,每当发生任务切换,系统必然会先进入一个中断,而一旦中断CPU就会把地址压入堆栈),这样,就达到了修改PC为下一个任务的地址的目的。

 

以上就是uC/OS-II的多任务实现机制,咱们在这里大费笔墨谈论这个问题,是但愿咱们的程序员们能够善加利用这个机制,写出更健壮,更富有效率的代码来

相关文章
相关标签/搜索