新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > uc\\os-II 操作系统

uc\\os-II 操作系统

作者:时间:2018-09-04来源:网络收藏

本文面向首次接触uC/OS-II的程序员,为他们介绍一下这个系统的一些基本特征和编程上的注意事项,并介绍几个值得了解的API。本文作者已经成功的将uC/OS-II移植到几种不同CPU之上。包括EPSON S1C33和Sunplus unSP?等,积累了丰富的经验,现在愿意和朋友们分享这些经历。希望本文的资料对于希望使用这个系统来开发的朋友有所帮助,作者乐意与您分享任何您成功的喜悦。

本文引用地址:http://www.eepw.com.cn/article/201809/388406.htm

This passage is written for the basic programmers who are first developed with the uC/OS-II real time OS。I will talk about the basic structure of this system。And I will discuss how to use some of the useful API。I will also discuss the imp of the mutilty-tasking in uC/OS-II。

(一) uC/OS-II 简介

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

(二) 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吃紧的系统来说,还是不用为好。

2006-7-23 21:55 lanso

(三) 一些重要的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宏

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


上一页 1 2 下一页

关键词:

评论


相关推荐

技术专区

关闭