第五章 c/os-ii 在 arm 系统中的应用与开发

82
1 Jean J. Labrosse 绪绪绪 80 绪绪绪 绪绪绪绪绪 绪绪绪 ,一 Intel 80C188 绪绪绪 绪绪绪 绪绪 ,一 绪绪绪绪绪 绪绪绪绪绪绪绪绪绪绪 绪绪绪绪绪 一, B 绪绪绪绪 1000 绪绪绪绪 ) 绪绪 绪绪绪绪绪绪绪绪绪绪 绪绪绪绪绪绪绪 B 绪绪 C 绪绪绪绪 绪绪绪绪绪绪绪绪 绪绪绪绪绪绪绪绪绪绪绪 绪绪绪绪绪绪绪 绪绪绪绪绪绪绪绪绪绪 ,,。 绪绪绪绪绪绪绪绪绪绪绪绪 绪绪绪 绪绪绪 C/OS-II 绪 ARM 绪 绪绪绪绪绪 绪绪

Upload: kali

Post on 13-Jan-2016

95 views

Category:

Documents


0 download

DESCRIPTION

第五章  C/OS-II 在 ARM 系统中的应用与开发. 绪、 Jean J. Labrosse 的故事 80 年代末,我设计了一个基于 Intel 80C188 的产品,需要一个实时内核。 使用一个知名的内核太贵了,廉价的内核 B (当时大约 1000 美元以下 ) 让我总给该厂商打电话求援。该厂商声称内核 B 是用 C 语言写的,可我还得用汇编语言初始化程序的每个对象,实在是烦透了,产品的开发也耽误了。 后来我得知我是该厂商的第一个客户. 至今, μC/OS 的书已售出了 15 , 000 多册。 μC/OS 已被移植到以下一些 CPU 上。 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第五章   C/OS-II 在 ARM 系统中的应用与开发

1

绪、 Jean J. Labrosse 的故事80年代末,我设计了一个基于 Intel 80C188的产品,需要一个实时内核。使用一个知名的内核太贵了,廉价的内核 B (当时大约 1000美元以下 ) 让我总给该厂商打电话求援。该厂商声称内核 B 是用 C 语言写的,可我还得用汇编语言初始化程序的每个对象,实在是烦透了,产品的开发也耽误了。后来我得知我是该厂商的第一个客户

第五章 C/OS-II 在 ARM系统中的应用与开发

Page 2: 第五章   C/OS-II 在 ARM 系统中的应用与开发

2

至今, μC/OS的书已售出了 15, 000多册。 μC/OS已被移植到以下一些 CPU上。Analog 设备公司 AD21xxARM公司 ARM 6, ARM7日立公司 64180, H8/3xx, SH系列Intel公司 80x86( Real and PM),Pentium, Pentium II, 8051,8052, MCS-251,80196,8096三菱公司 M16和 M32摩托罗拉公司 PowerPC, 飞利浦公司 XA西门子公司 80C166和 TriCoreTI公司 TMS320Zilog公司 Z—80 和 Z—180

Page 3: 第五章   C/OS-II 在 ARM 系统中的应用与开发

3

μC/OS-II意为“微控制器操作系统版本2”。世界上已有数千人在各个领域使用μC/OS,例如,照相机行业、医疗器械、音响设施、发动机控制、网络设备、高速公路电话系统、自动提款机、工业机器人等等。很多高等院校将 μC/OS用于实时系统教学。

Page 4: 第五章   C/OS-II 在 ARM 系统中的应用与开发

4

μC/OS 的几个典型应用NSA2010 便携式电话,在日本大约有 15000 台投入市场。使用 μC/OS 实时操作系统。

CYCLONE 移动电话, Hitachi H8S/2318k 微程序控制器, 256K 闪存和 8K Ram , μC/OS 实时操作系统。

选择 μC/OS的原因:INFEA R&D 的职员从 1996 年以来开始应用 Micriμm 实时操作系统。通过比较,还没有发现比 μC/OS 更好的实时操作系统。我们将继续应用 μC/OS 以及Micriμm 的其它产品包括下一代 μC/OS-II V2.52 的产品。

Page 5: 第五章   C/OS-II 在 ARM 系统中的应用与开发

5

三轴运动控制卡

——Hitachi SH2 微处理器;

——7 个任务;—— 时钟频率 10Hz ;

用于加工眼镜的塑料镜片的计算机控制车床的运动控制。

选择 μC/OS-II 的原因: 主要原因是它与其它市场上的实时操作系统相比的相对低廉的费用。另一个主要原因是资源和内设的可获得性。最后一点, μC/OS-II 有足够的能力使我们能够顺利完成工作。 SH-2 快速,有效的执行与 μC/OS-II 的实时内核是使工作顺利完成的最重要的条件。

Page 6: 第五章   C/OS-II 在 ARM 系统中的应用与开发

6

MB-20-M 信用卡处理装置 TCP/IP 协议;20MHz Am188ES ;10 项任务;时钟频率 100Hz ;

MB-20-M 被用于对很多的教学和商务设备的控制使用和收费 , 包括身份证,安全卡和图书馆借阅卡,现在只要应用标准磁条的用户卡都可以在MB-20-M 终端上使用。

选择 μC/OS-II 的原因:

价格便宜,代码尺寸小,缩短开发周期

Page 7: 第五章   C/OS-II 在 ARM 系统中的应用与开发

7

独立静态交换机

•Hitachi H8S/2357 CPU •4 个任务 •时钟频率 1000Hz 独立静态交换机( SIEL 交换机)是一个可以连续的瞬时改变电源的装置从而控制两条电线的状态,最终保证负载的最佳电力供给。这种机器同样可以保护负载以防短路。

选择 μC/OS—II 的原因: 与其它实时方案相比低廉的价格,与很多微处理器可以进行数据传输,对源代码的完全控制。

Page 8: 第五章   C/OS-II 在 ARM 系统中的应用与开发

8

µC/ OS-Ⅱ 是一个免费的、源代码公开的实时嵌入式内核,其内核提供了实时系统所需要的一些基本功能。其中包含全部功能的核心部分代码占用 8.3 KB,全部的源代码约 5500 行,结构合理、清晰易懂,且注解详尽,非常适合初学者进行学习分析。 µC/ OS-Ⅱ 不仅使用户得到廉价的解决方案,而且由于 µC/ OS-Ⅱ 的开放源代码特性,还使用户可针对自己的硬件优化代码,获得更好的性能。 µC/ OS-Ⅱ 是在 PC机上开发的, C 编辑器使用的是Borland C/C++3.1版。从早期使用的 µCOS到现在的 µC/ OS- V2.52Ⅱ 版,应用的实例也进一步说明了该内核的实用性和可靠性。

5.1 C/OS-II系统的特点及结构

Page 9: 第五章   C/OS-II 在 ARM 系统中的应用与开发

9

5.1.1 µC / OS-Ⅱ 系统的特点

1 .有源代码, µC/ OS-Ⅱ 源代码是开放的,用户可登录 µC/ OS-Ⅱ 的网站 (www. uCOS-II. com)下载针对不同微处理器的移植代码。这极大地方便了实时嵌入式系统 µC/ OS-Ⅱ 的开发,降低了开发成本。2.可移植 (Portable), µC/ OS-Ⅱ 的源代码中,除了与微处理器硬件相关的部分是使用汇编语言编写的,其绝大部分是使用移植性很强的 ANSI C来编写的。并且把用汇编语言编写的部分已经压缩到最低的限度,以使 µC/ OS-Ⅱ 更方便于移植到其他微处理器上使用。如 Intel公司、 Zilog公司、 Motorola公司的微控制器和 TI公司的 DSP,以及包括 ARM公司、 Analog Device公司、三菱公司、日立公司、飞利浦公司和西门子公司的各种微处理器。

Page 10: 第五章   C/OS-II 在 ARM 系统中的应用与开发

10

3 .可固化 (ROMable), µC/ OS-Ⅱ 是为嵌入式应用而设计的操作系统,只要具备有合适的软硬件工具,就可将 µC/ OS-Ⅱ 嵌入到产品中去,从而成为产品的一部分。 4.可裁剪 (Scalable), µC/ OS-Ⅱ 可根据实际用户的应用需要使用条件编译来完成对操作系统的裁剪,这样就可以减少 µC/ OS-Ⅱ 对代码空间和数据空间的占用。5.可剥夺型 (Preemptive), µC/ OS-Ⅱ 是完全可剥夺型的实时内核,运行就绪条件下优先级最高的任务。6.多任务, µC/ OS-Ⅱ 可管理 64个任务。一般情况下,建议用户保留 8 个任务给 µC/ OS-Ⅱ 。这样,留给用户应用程序的任务最多可有 56个。系统赋给每个任务的优先级必须不同,这意味着 µC/ OS-Ⅱ 不支持时间片轮转调度法 (Round-robin Scheduling) 。7.可确定性,绝大多数 µC/ OS-Ⅱ 的函数调用和服务的执行时间具有确定性。在任何时候用户都能知道 µC/OS-Ⅱ 的函数调用与服务的执行时间。

Page 11: 第五章   C/OS-II 在 ARM 系统中的应用与开发

11

8 .任务栈, µC/ OS-Ⅱ 的每个任务都有自己单独的栈和栈空间。使用 µC/ OS-Ⅱ 的栈空间校验函数可确定每个任务到底需要多少栈空间。 9.系统服务,提供了例如信号量、互斥信号量、消息邮箱、事件标志、数据队列、块大小固定的内存的申请与释放及时间管理函数等。 10 .中断管理,中断可使正在执行的任务暂时挂起,如果优先级更高的任务被中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行。中断嵌套层数可达 255层。 11 .稳定性与可靠性, 2000 年 7 月, µC/ OS-Ⅱ 在一个航空项目中得到了美国联邦航空管理局对商用飞机的符合 RTCA DO--178B标准的认证。可以说, µC/OS-Ⅱ 的每一种功能、每一个函数及每一行代码都经过了考验与测试。

Page 12: 第五章   C/OS-II 在 ARM 系统中的应用与开发

12

5.1.2 µC / OS-Ⅱ 系统的内核结构与其他操作系统不同, µC / OS-Ⅱ 其实只有一

个内核,提供任务调度、任务间的通信与同步、任务管理、时间管理和内存管理等基本功能。1) 任务在 µC/ OS-Ⅱ 中,一个任务通常是一个无限的循环。一个任务看起来像其他 c 语言的函数一样,有函数返回类型,有形式参数变量,但任务是决不会返回的。故返回参数必须定义成 void,例如:Void YourTask(void *pdata){for(;; ){/ * 用户代码 * // *调用 µC/ OS-II的某种系统服务: */ / *用户代码 * /}}

Page 13: 第五章   C/OS-II 在 ARM 系统中的应用与开发

13

2) 任务调度µC/ OS-II可以管理多达 64个任务,其优先级可以从 0开始,优先级号越低,其任务的优先级就越高。但目前版本的 µC/ OS-II有两个任务已经被系统占用了,而且保留了优先级 0 、1、 2、 3、和 OS_LOWEST_PRIO-3、 OS_LOWEST__PRIO-2、 0S_LOWEST_PRIO-1以及 OS_LOWEST_PRIO这 8个任务已备将来使用。 OS_LOWEST_PRIO是作为常数在 OS_CFG.H文件中用定义常数语句 #define constant来定义的。因此用户可以使用多达 56个应用任务,但首先要给每个任务赋以不同的优先级。 µC/ OS-II总是运行进入就绪态的优先级最高的任务。目前版本的 µC/ OS-II中,任务的优先级号就是任务编号(ID)。优先级号 (或任务的 ID号 ) 也可以被一些内核服务函数调用,比如改变优先级函数 OSTaskChangePrio()或者OSTaskDel() 。为了使 µC/ OS-II能管理用户任务,用户必须在建立一个任务的时候,将任务的起始地址与其他参数一起传给OSTaskCreate()或者 OSTaskCreateExt()这两个函数中的任何一个函数。图 5-1 是 µC/ OS-II控制下的任务状态转换图,在任一时刻,任务的状态一定是这五种状态之一。

Page 14: 第五章   C/OS-II 在 ARM 系统中的应用与开发

14

由于, µC/ OS-II总是运行进入就绪态任务中优先级最高的那个任务。那么确定哪一个任务优先级最高、该哪个任务将要运行,这样的工作是由调度器完成的。 µC/ OS-II任务调度所花的时间是常数,与应用程序中建立的任务数无关。任务切换很简单,一般由以下两步完成:首先将被挂起任务的微处理器寄存器推入堆栈;然后将较高优先级的任务的寄存器值从堆栈中恢复到寄存器中。在 µC/ OS-II中,就绪任务的栈结构总是看起来跟刚刚发生过中断一样,所有微处理器的寄存器都保存在栈中。换句话说, µC/ OS-II运行就绪态的任务所要做的一切,只是恢复所有的 CPU寄存器并运行中断返回指令。

Page 15: 第五章   C/OS-II 在 ARM 系统中的应用与开发

15

5.1.3 主要模块介绍1 .内存管理在 ANSI C 中,一般采用内存分配函数 malloc() 和内存释放函数 free()两个函数动态地分配和释放内存。为了消除多次动态分配与释放内存所引起的内存碎片和分配、释放函数执行时间的不确定性的现象, µC /OS-Ⅱ 把连续的大块内存按分区来进行管理。每个分区中都包含若干个存储容量大小相同的内存块,但不同分区之间的内存块容量大小是可以不同的。在需要动态分配内存时,可选择一个适当的分区,按块来分配内存。在释放内存时,将该块放回它以前所属的分区。这样,就能有效解决内存碎片问题。而且每次调用 malloc()和 free()分配和释放的都是整数倍的固定内存块长,这样执行时间就是确定的了。

Page 16: 第五章   C/OS-II 在 ARM 系统中的应用与开发

16

( 1)内存管理控制块 OS_MEM为便于内存的管理, µC/ OS-II中使用内存控制块

(Memory Control Blocks)的数据结构跟踪每一个内存分区系统,每个分区都有属于自己的内存控制块,系统是通过内存控制块数据结构 OS_MEM来管理内存的。 ( 2)内存管理

内存管理主要通过以下 4个函数来实现: ①OSMemCreate()函数,用于建立一个内存分区。该函数共有 4个参数:内存分区的起始地址、分区内的内存块数、每个内存块的字节数和一个指向错误信息代码的指针。 ②OSMemGet()函数,用于分配一个内存块。当调度某任务执行时,必须先从已建立的内存分区中为该任务申请一个内存块。 ③OSMemPut()函数,释放一个内存块。当某一任务不再使用一个内存块时,必须及时地把它放回到相应的内存分区中,以便下一次的分配操作。 ④OSMemQuery()函数,用于查询一个特定内存分区的状态。如查询某内存分区中内存块的大小、可用内存块数和正在使用的内存块数等信息。

Page 17: 第五章   C/OS-II 在 ARM 系统中的应用与开发

17

( 3)时间管理与大部分内核一样, µC / OS-Ⅱ 要求提供定时中断,以实现延时与超时控制等功能。这个定时中断也可以被叫作为时钟节拍。在相关的内容中,介绍了时钟的中断服务子程序( ISR)和时钟节拍函数 OSTimeTick()。时钟节拍函数的作用是用于通知 µC/ OS-Ⅱ 发生了时钟节拍中断,下面再介绍几个可以处理时间问题的函数。①任务延时函数 OSTimeDIy() 调用该函数会使 µC / OS-Ⅱ 进行一次任务调度,并且执行下一个优先级最高的就绪态任务。任务调用 OSTimeDly()后,一 旦 规 定 的 时 间 期 满 或 者 有 其 他 任 务 通 过 调 用OSTimeDlyResume()取消了延时,它就会立即进入就绪状态。只有当该任务在所有就绪任务中具有最高的优先级时,它才会立即运行。②恢复延时的任务函数 OSTimeDlyResume() µC / OS-II 具有允许结束正处于延时期的任务的功能。具体方法是通过调用 OSTimeDlyResume()和指定要恢复的任务的优先级的方式,这样延时的任务就可以不用等待延时期满,而是通过其他任务取消延时来使自己处于就绪态。实际上, OSTimeDlyResume()也可唤醒正在等待事件的任务。

Page 18: 第五章   C/OS-II 在 ARM 系统中的应用与开发

18

③按时、分、秒、毫秒延时函数 OSTimeDlyHMSM() OSTimeDly() 是一个非常有用的函数,但用户的应用程序须要 知 道 延 时 时 间 所 对 应 的 时 钟 节 拍 的 数 目 。 增 加 了OSTimeDlyHMSM()函数后,就可按时、分、秒和毫秒来定义时间了,这样会显得更加方便。与 OSTimeDly() 一样,调用OSTimeDIyHMSM()函数也会使 µC / OS-II进行一次任务调度,并 且执行 下 一 个 优先级最高的就绪态任务。任务调用OSTimeDlyHMSM()后,一旦规定的时间期满或有其他任务通过调用 OSTimeDlyResume()取消了延时,它就会立即处于就绪态。同样,只有当该任务在所有就绪态任务中具有最高的优先级时,它才会立即运行。④系统时间函数 OSTimeGet()和 OSTimeSet() 无论时钟节拍何时发生, µC / OS-II都会将一个 32位的计数器加 1 。这个计数器在调用 OSStart()初始化多任务和 4294967295 个节拍执行完一遍后,从 0开始计数。在时钟节拍频率等于 100Hz时,这个 32位的计数器每隔 497 天就重新开始计数。在执行的过程中可以通过调用 OSTimeGet()函数来获得该计数器的当前值,也可以通过调用 OSTimeSet()函数来改变该计数器的值。

Page 19: 第五章   C/OS-II 在 ARM 系统中的应用与开发

19

2 、任务的管理µC/ OS-II提过大量的 API函数实现对任务的管理,主要的任务有:( 1)建立任务µC/ OS-II要管理用户的任务,就必须先建立任务。通过将任务的地址和其他参数传递给以下两个函数来建立任务。 OSTaskCreate()和带有扩展附加功能的OSTaskCreateExt()函数。在 main()函数内开始多任务调度( OSStart()前,必须至少建立一个任务,而且任务不能由中断服务程序( ISR)建立。创建一个任务控制块,并通过任务控制块把任务代码和任务堆栈关联起来形成一个完整的任务。还有使刚创建的任务进入就绪状态,并引发一次任务调度(取决于任务是否处于多多任务工作状态)。

Page 20: 第五章   C/OS-II 在 ARM 系统中的应用与开发

20

两个函数 OSTaskCreate() 和OSTaskCreateExt()原型如下:INT8U OSTaskCreate(

void (*task)(void *pd); //指向任务的指针

void * pdata; //传递给任务的参数

OS_STK * ptos;//指向任务堆栈栈顶的指针

INT8U prio //任务的优先级

)

Page 21: 第五章   C/OS-II 在 ARM 系统中的应用与开发

21

INT8U OSTaskCreateExt( void (*task)(void *pd); //指向任务的指针 void * pdata; //传递给任务的参数 OS_STK * ptos;//指向任务堆栈栈顶的指针 INT8U prio //任务的优先级 INT16U id //任务的标识 OS_STK * pbos;//指向任务堆栈栈低的指针 INT32U stk_siaze; //任务堆栈容量 void * pext; //指向附加数据域的指针

INT16U opt //用于设定操作选项 ) 在调用任务建立函数后, µC/ OS-II内核会首先从 TCB空闲列表内申请一个空的 TCB指针;然后根据用户给出的参数初始化任务堆栈,并在内部的任务就绪表中标记该任务为就绪状态;最后返回。这样就建立了一个任务。

Page 22: 第五章   C/OS-II 在 ARM 系统中的应用与开发

22

( 2)任务堆栈在 µC/ OS-II中,每个任务都有自己的堆栈空间。堆栈必须声明为 OS_STK类型,并且由连续的内存空间组成。可以静态分配堆栈空间(在编译时分配),也可以动态分配堆栈空间(在运行时分配),这两种声明方式都应放置在函数外面。任务所需堆栈的容量由应用程序确定。但必须考虑到任务调用的所有函数的嵌套情况、任务调用的所有函数为局部变量分配的所有内存的数目,以及所有可能的中断服务子程序嵌套对堆栈的需求。此外,堆栈必须能够保存 CPU所有的寄存器。µC/ OS-II提供了堆栈检验函数 OSTaskStkChk(),用来确定任务实际需要的堆栈空间的大小。这样能够避免为任务分配过多的堆栈空间,从而减少应用程序代码所需的 RAM数量。调用堆栈检验函数后,所得到的只是一个大致的堆栈使用情况,并不能说明堆栈使用的全部实际情况。为了适应系统以后的升级和扩展,应该多分配 10%~ 100%的堆栈空间。

Page 23: 第五章   C/OS-II 在 ARM 系统中的应用与开发

23

( 3)任务的挂起和恢复挂起一个任务,就是停止这个任务的运行。在uC/OS-II中,用户任务可以通过调用系统提供的函数 OSTaskSuspend()来挂起自身或者除空闲任务之外的其他任务。挂起的任务,只能在其他任务中通过调用恢复函数OSTaskResume()使其恢复为就绪状态。该函数并不要求和挂起函数 OSTaskSuspend()成对使用。但是,如果任务在被挂起的同时还在等待延迟时间到,则需要对任务取消挂起操作,并且要继续等待延迟时间到,任务才能转入就绪状态。

Page 24: 第五章   C/OS-II 在 ARM 系统中的应用与开发

24

( 4 )任务的删除 删除一个任务,就是把该任务置于睡眠状态,任务的代码不再被 uC/OS-II使用,而并不是说任务的代码被删除了。调用OSTaskDel()后,先进行条件判断,当所有的条件都满足后,就会从所有可能的 uC/OS-II的数据结构中去除任务的任务控制块 OS_TCB,这样就不会被其他的任务或中断服务子程序置于就绪态,即任务置于休眠状态。

函数原型如下: INT8U OSTaskDel(INT8U prio) 可删除任务自身或者除了空闲任务之外的其他任务。删除自

己参数为: OS_PRIO_SELF 直接调用这样的删除任务,可能出现某些问题,如果任务拥

有一些动态的内存或者信号量之类的资源,那么如果它被删除了,它的资源就不会被释放而丢失,会造成同样使用资源的其他任务进入死等待,出现错误情况。要慎重使用。提供了一个可以在请求删除方和被删除方通信完成删除的函数。原型如下:

INT8U OSTaskDelReq(INT8U prio) 返回是否被删除和是否有要删除自己的要求。被删除方调用得知要删除自己,释放资源后,在删除自己。

Page 25: 第五章   C/OS-II 在 ARM 系统中的应用与开发

25

( 5)其他任务管理函数任务优先级别修改

任务运行过程中,用户可以根据需要来改变任务的优先级别。调用的函数原型如下:

INT8U OSTaskChangePrio( INT8U oldprio; //任务现在的优先级别

INT8U newprio //要修改的优先级别 ) 查询任务的信息

查询一些任务中的信息,函数原型如下: INT8U OSTaskQuery( INT8U prio; OS_TCB * pdata )

Page 26: 第五章   C/OS-II 在 ARM 系统中的应用与开发

26

3 、任务间同步与通信的管理uC/OS-II中,使用信号量、邮箱(消息邮箱)和消息队列来实现任务相互同步或相互之间的通信。

uC/OS-II把关于它们的操作都定义为全局函数,以供应用程序的所有任务来调用等待任务列表

采用 INT8U类型的数组 OSEventTbl[]作为记录等待事件任务的记录表,叫做等待任务表,每个任务占 1位,为 1表示是等待任务。任务的等待时限,记录在等待任务的任务控制块TCB的成员 OSTCBDly中

Page 27: 第五章   C/OS-II 在 ARM 系统中的应用与开发

27

( 1)事件控制块 uC/OS-II使用叫做事件控制块 ECB的数据结构来描述诸如信号量、邮箱和消息队列这些事件。事件控制块包含包括等待任务表在内的所有有关事件的数据。

Page 28: 第五章   C/OS-II 在 ARM 系统中的应用与开发

28

操作事件控制块的函数 uC/OS-II有 4个对事件控制块进行基本操作的函数

(定义在 OS_CORE.C中)。事件控制块的初始化函数 void OS_EventWaitListInit(OS_ENENT * pevent )

把变量 OSEventGrp及任务等待表中的每一位都清0,即令事件的任务等待表中不含有任何等待任务。该函数被 OSXXXCreate()创建时所调用。

XXX Sem 信号量 Mutex 互斥信号量 Mbox 消息邮箱 Q 消息队列

Page 29: 第五章   C/OS-II 在 ARM 系统中的应用与开发

29

使一个任务进入等待状态的函数 void OS_EventTaskWait( OS_ENENT * pevent) 将在任务调用函数 OSXXXPend ()请求一个事件时调用。 使一个正在等待任务进入就绪状态的函数 INT8U OS_EventTaskRdy( OS_EVENT * pevent, void *msg , INT8U msk)

作用:把调用这个函数的任务在任务等待表中的位置清 0后,再把任务在任务就绪表中的对应的位置 1 ,然后引发一次任务调度

将在任务调用函数 OSXXXPost ()发送一个事件时,被调用。 使一个等待超时的任务仅需就绪状态的函数 void OS_EventTo(OS_EVENT *pevent) 作用:当任务已经超过了等待的时间,却要使它进入就绪状态。

将在任务调用函数 OSXXXPend ()请求一个事 件时,被调用

Page 30: 第五章   C/OS-II 在 ARM 系统中的应用与开发

30

( 2)信号量管理使用信号量可以在任务间传递信息,实现任务与任务或中断服务子程序的同步。 uC/OS-II中的信号量由两部分组成: 16 位的无符号整数信号量的计数值( 0~ 65535);另一部分是由等待该信号量的任务组成的等待任务列表。 uC/OS-II提供了以下 6个函数对信号量进行操作。

操作创建信号量 OSSemCreat( INT16U cnt)创建,返回已创建信号量的指针。

请求信号量 OSSemPend( OS_EVENT *pevent INT16U timeout INT8U *err)

Page 31: 第五章   C/OS-II 在 ARM 系统中的应用与开发

31

time为 0,则表示无限等待。 不等待调用的函数为OSSemAccept( OS_EVENT * pevent)。

发送信号量 INT8U OSSemPost( OS_EVENT * pevent)

当获得信号量,访问共享资源结束以后,释放信号量,调用该函数。先检查是否有等待该信号量的任务。没有,信号量计数器加 1 ,有,则调用调度器 OS_Sched()。

Page 32: 第五章   C/OS-II 在 ARM 系统中的应用与开发

32

删除信号量 OS_EVENT *OSSemDel( OS_EVENT * pevent,

INT8U opt, INT8U *err) opt OS_DEL_NO_PEND 没有等待任务删除 OS_DEL_ALLWAYS 立即删除 只能任务执行,不能在中断服务程序中删除查询信号量的状态 INT8U OSSemQuery( OS_EVENT * pevent OS_SEM_DATA *pdata)

pdata是一个结构指针,存储信号量的状态。

Page 33: 第五章   C/OS-II 在 ARM 系统中的应用与开发

33

( 3)消息邮箱管理消息邮箱是 uC/OS-II中的一种通信机制,通常使用时要先定义一个指针型的变量该指针指向一个包含了消息内容的特定数据结构。发送消息的任务或中断服务子程序把这个变量送往邮箱,接收消息的任务从邮箱中取出该指针变量,完成信息交换。 uC/OS-II提供 6种对消息邮箱的操作,它们通过以下函数实现:创建OS_EVENT * OSMoxCreate( void * msg)

Msg为消息指针,一般初始为 NULL 。

Page 34: 第五章   C/OS-II 在 ARM 系统中的应用与开发

34

向消息邮箱发送消息INT8U OSMboxPost( OS_EVENT * pevent, void * msg)发送广播消息INT8U OSMboxPostOpt( OS_EVENT * pevent,

void * msg,

INT8U opt)

opt: OS_POST_OPT_BROADCAST 广播消息 OS_POST_OPT_NONE 最高优先级

Page 35: 第五章   C/OS-II 在 ARM 系统中的应用与开发

35

请求消息邮箱void * OSMboxPend( OS_EVENT * pevent, INT16U timeout, INT8U *err)查询邮箱状态INT8U OSMboxQuery ( OS_EVENT * pevent, OS_MBOX_DATA *pdata)

删除邮箱OS_EVENT *OSMboxDel( OS_EVENT * pevent, INT8U opt,

INT8U *err)

Page 36: 第五章   C/OS-II 在 ARM 系统中的应用与开发

36

( 4 )消息队列管理消息队列是 uC/OS-II的另一种通信机制,它可以使一个任务或中断服务子程序向另一个任务发送以指针定义的变量。 uC/OS-II提供了 9个对消息队列进行操作的函数。创建 先创建一个指针数组,然后用该数组来创建消息队列

OS_EVENT OSQCreate( void ** start,INT16U size)

请求消息队列 void* OSQPend( OS_EVENT * pevent, INT16U timeout,INT8U *err)

Page 37: 第五章   C/OS-II 在 ARM 系统中的应用与开发

37

向消息队列发送消息INT8U OSQPost( OS_EVENT * pevent,void * msg ) 工作方式 FIFO

INT8U OSQPostFront( OS_EVENT * pevent,void * msg )

工作方式 LIFO发送广播消息INT8U OSQPostOpt( OS_EVENT * pevent,void * msg,

INT8U opt)

Page 38: 第五章   C/OS-II 在 ARM 系统中的应用与开发

38

清空消息队列INT8U OSQFlush ( OS_EVENT * pevent )删除消息队列OS_EVENT * OSQDel ( OS_EVENT * pevent )

查询消息队列INT8U OSQQuery ( OS_EVENT * pevent, OS_Q_DATA *pdata)

Page 39: 第五章   C/OS-II 在 ARM 系统中的应用与开发

39

4. µC / OS-II操作系统的文件系统µC / OS-II操作系统的文件体系结构如图 2 所示,其核心主要可分为以下 3部分:( 1)应用软件层,指的是基于 µC/ OS-II的应用程序代码。( 2)内核的核心代码层,主要包括 8 个源代码文件。这 8 个源代 码 文 件 为OS_CORE.C 、 OS_MBOX.C 、 OS_MEM.C 、 OS_SEM.C 、 OS_TIME.C、 uCOS_II.C、 OS_Q.C和 OS_TASK.C,其主要实现的功能分别是核心管理、事件管理、存储管理、消息队列管理、定时管理、信号量处理、消息管理和任务调度等,这部分代码与处理器无关。( 3)系统设置与移植层。系统设置部分的代码由两个头文件OS_CFG.H 和 INCLUDES.H组成。其主要功能是用来配置事件控制块的数目以及是否包含消息管理的相关代码等。与处理器相关的移植代码部分包括:一个头文件 OS_CPU.H、一个汇编文件OS_CPU_A.ASM和一个 C 代码文件 OS_CPU_C.C。系统设置与移植层与具体应用和处理器相关,在随后的 µC/ OS-II的移植和开发过程中,用户所需要关注的就是这部分文件。

Page 40: 第五章   C/OS-II 在 ARM 系统中的应用与开发

40

图 2 µC / OS-II文件体系结构

Page 41: 第五章   C/OS-II 在 ARM 系统中的应用与开发

41

5.1.4 µC / OS-II 操作系统的初始化

在调用 µC/ OS-II操作系统的其他服务之前, µC/ OS-II操作系统要求用户首先调用系统初始化函数 OSInit()。执行 OSInit()函数后将初始化 µC/ OS-II所有的变量和数据结构,另外 OSInit()会建立空闲任务,并且这个任务总是处于就绪状态的。空闲任务OSTaskldle() 函数的 优先级总 是 设置成 为 最 低级别,即OS_LOWEST_PRIO。多任务的启动是用户通过调用 OSStart()函数来实现的。然而 ,在启动 µC/ OS-II之前,用户至少要建立一个应用任务,例如:void main(){ OSInit();

..通过 OSTaskCreate()或 OSTaskCreateExt()创建至少一个任务

..OSStart(); /*开始多任务调度, OSStart()永远都不会返回 */}

Page 42: 第五章   C/OS-II 在 ARM 系统中的应用与开发

42

5.2 µC / OS-II系统在 ARM系统中的移植 所谓移植,就是指使一个实时操作系统能够在其他的微处理器平台上进行运行。由于 µC/ OS-II的主要代码都是由标准的 C 语言写成

的,所以,一般来说移植过程并不复杂。5.2.1 µC / OS-II移植条件虽然 µC / OS-II 的大部分源代码是用 C 语言写成的,但是,仍需要用汇编语言完成一些与微处理器相关的代码。例如, µC / OS-II 在读写微处理器、寄存器时只能通过汇编语言来实现。这是因为 µC / OS-II 在设计的时候就已经充分考虑了可移植性。为了要使 µC / OS-II 可以正常工作,处理器必须要满足如下要求:

Page 43: 第五章   C/OS-II 在 ARM 系统中的应用与开发

43

1) .微处理器的 C 编译器能产生可重入代码可重入的代码指的是一段代码 ( 如一个函数 ) 可以被多个任务同时调用,而不必担心会破坏其内部的数据。也就是说,可重入型函数在任何时候都可以被中断执行,也不会因为在函数中断的时候被其他的任务重新调用,影响函数中的数据。可重入代码或者只使用局部变量,即变量保存在 CPU寄存器中或堆栈中;或者使用全局变量,则要对全局变量予以保护。通常的 C 编译器,把局部变量分配在栈中。所以,多次调用同一个函数,可以保证每次的局部变量互不受影响。而全局变量,在多次调用函数的时候,必然受到影响。代码的可重入性是保证完成多任务的基础,除了在 C 程序中使用局部变量以外,还需要 C 编译器的支持。基于ARM 的 SDT 、 ADS等集成开发环境,都可以生成可重入的代码。

Page 44: 第五章   C/OS-II 在 ARM 系统中的应用与开发

44

2) .在程序中可以使用 c 语言打开或者关闭中断在 µC / OS-II 中,可以通过进入中断屏蔽的宏定义OS_ENTER_CRITICAL()或者退出中断屏蔽的宏定义OS EXIT_CRITICAL()来控制系统关闭中断或者打开中断,这需要微处理器的支持。在目前的 ARM 系列的微处理器上,都可以设置相应的寄存器来关闭或者打开系统的所有中断。3).微处理器支持中断,并且能产生定时中断 ( 通常在 10Hz-1000Hz之间 ) 。 µC / OS-II是通过微处理器产生定时的中断来实现多任务之间的调度的。4 ).微处理器支持能够容纳一定量数据的硬件堆栈,并具有将堆栈指针和其他 CPU寄存器读写到堆栈 (或者内存 ) 的指令。5) µC/ OS-II进行任务调度的时候,会把当前任务的 CPU内部寄存器的内容存放到此任务的堆栈中。然后,再从另一个任务的堆栈中恢复原来的工作寄存器,继续运行另一个任务。所以,寄存器中内容的入栈和出栈是 µC/ OS-II多任务调度的基础。

Page 45: 第五章   C/OS-II 在 ARM 系统中的应用与开发

45

5.2.2 µC/ OS-II的移植步骤在的移植过程中,使用的是基于 ARM公司架构的软件开发工具作为编译器,所值得关注的问题是与微处理器相关的代码,这部分主 要 包 括 一 个 头 文 件 OS_CPU.H 、 一 个 汇 编 文 件OS_CPU_A.ASM和一个 C 代码文件 OS_CPU_C.C。1).设置头文件 OS_CPU.H中与处理器和编译器相关的代码( 1)与编译器相关的数据类型

#define INT8U unsigned char #define INTl6U unsigned short #define INT32U unsigned long #define OS_STK unsigned long #define BOOLEAN int #define OS_CPU_SR unsigned long#define INT8S char因为不同的微处理器有不同的字长,所以 µC/ OS-Ⅱ 的移植包括了一系列的类型定义以确保其可移植性。

Page 46: 第五章   C/OS-II 在 ARM 系统中的应用与开发

46

用户必须将任务堆栈的数据类型定义到 µC/ OS-II操作系统中,这个过程是通过为 OS_STK声明正确的 C 语言数据类型来完成的。由于使用的微处理器上的堆栈成员是 16 位的,所以将 OS_TSK声明为无符号整形数据类型。值得注意的是,所有的任务堆栈都必须使用OS_STK声明数据类型。( 2)进入中断屏蔽的宏定义 OS_ENTER_CRITICAL()和退出中断屏蔽的宏定义 OS_EXIT_CRITICAL()

extern int INTS_OFF(void); extern void INTS_ON(void); #define OS_ENTER_CRITICAL() {cpu_sr = INTS_OFF(); }

#define OS_EXIT_CRITICAL() {if(cpu_sr==0) INTS_ON() ; }与所有的实时内核一样, µC/ OS-II操作系统在进行任务切换时需要先禁止中断在访问代码的临界区,并且在访问完毕后重新允许中断。这就使得 µC/ OS-II能够保护临界区代码免受多任务或中断服务例程 (ISR) 的 破 坏 。 在 S3C44B0 微 处 理 器 上 是 通 过OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()两个函数来实现开、关中断的。

Page 47: 第五章   C/OS-II 在 ARM 系统中的应用与开发

47

( 3)栈增长方向标 OS_STK_GROWTH#define OS_STK_GROWTH 1

#define STACKSIZE 256绝大多数的微处理器的堆栈是从高地址向低地址增长的,但是有些微处理器是采用相反方式工作的。鉴于这种情况 µC / OS-II 操作系统被设计成为这两种情况都可以处理,只要在结构常量OS_STK_GROWTH中指定堆栈的生长方式就可以了。例如:设 OS_STK_GROWTH 为 0 表示堆栈从下往上增长。设 OS_STK_GROWTH 为 1 表示堆栈从上往下增长。

Page 48: 第五章   C/OS-II 在 ARM 系统中的应用与开发

48

2) . 用汇编语言在 OS_CPU_A.ASM文件中编写 4个与微处理器相关的函数(1) 调用优先级最高的就绪任务函数 OSStartHighRdy()(2)任务级的任务切换函数 OSCtxSw() (3) 中断级的任务切换函数 OSIntCtxSw() (4)时钟节拍中断服务函数 OSTickISR()3).用 C 语言编写 6个操作系统相关的函数( OS_CPU_C.C )这里主要涉及 6个函数:OSTaskStkInit() 、 OSTaskCreateHook() 、 OSTaskDelHook() 、 OSTaskSwHook() 、 OSTaskStatHook() 及OSTimeTickHook() 。这些函数中,惟一必须移植的是任务堆栈初始化函数OSTaskStkInit()。这个函数在任务创建时被调用,负责初始化任务的堆栈结构并返回新堆栈的指针 stk。在 ARM体系结构下,任务堆栈空间由高至低依次保存着PC、 LR、 R12、 R11、 R10 …、 、 R1、 R0、 CPSR及SPSR 。堆栈初始化工作结束后,返回新的堆栈栈顶指针。

Page 49: 第五章   C/OS-II 在 ARM 系统中的应用与开发

49

以下 5 个 Hook函数,又称为钩子函数,主要用来扩展µC/ OS-Ⅱ 功能,使用前必须被声明,但并不一定要包含任何代码。 (1) 0STaskCreateHook()函数 当用 OSTaskCreate()函数或 OSTaskCreateExt()函数建立任务时,就会调用 OSTaskCreateHook()函数。 µC/ OS-Ⅱ设置完自己的内部结构后,会在调用任务调度程序之前调用OSTaskCreateHook()函数。该函数被调用时中断是禁止的,因此应尽量减少该函数中的代码,以缩短中断的响应时问。 (2) OSTaskDelHook()函数 当任务被删除时,就会调用 OSTaskDelHook()函数。该函数在把任务从 µC/ OS-Ⅱ 的内部任务链表中解开之前被调用。当OSTaskDelHook()函数被调用时,会收到指向正被删除任务的OS_TCB的指针,这样它就可访问所有的结构成员了。 OSTaskDelHook()函数可用来检验 TCB扩展是否被建立了 (一个非空指针 ),并进行一些清除操作。注意,此函数不返回任何值。

Page 50: 第五章   C/OS-II 在 ARM 系统中的应用与开发

50

(3) OSTaskSwHook()函数 当发生任务切换时,调用 OSTaskSwHook()函数。不管任务切换是通过 OSCtxSw()函数,还是通过 OSIntCtxSw()函数来执行的,都会调用该函数。 OSTaskSwHook()函数可直接访问OSTCBCur和 OSTCBHighRdy,这是因为它们都是全局变量。 OSTCBCur指向被切换出去的任务的 OS_TCB,而OSTCBHighRdy指向新任务的 OS_TCB。在调用 OSTaskSwHook()函数期间,中断一直是被禁止的。这时因为代码的多少会影响到中断的响应时间,所以应尽量使代码简化。此函数没有任何参数,也不返回任何值。 (4) OSTaskStatHook()函数 OSTaskStatHook() 函数每秒都会被 OSTaskStat() 函数调用一次,可用 OSTaskStatHook()函数来扩展统计功能。该函数没有任何参数,也不返回任何值。 (5) OSTimeTickHook()函数 OSTimeTickHook()函数在每个时钟节拍都会被0STimeTick()函数调用。实际上, OSTimeTickHook()函数是在节拍被 µC/ OS-Ⅱ 处理,并在通知用户的移植实例或应用程序之前被调用的。 OSTimeTickHook()函数没有任何参数,也不返回任何值。

Page 51: 第五章   C/OS-II 在 ARM 系统中的应用与开发

51

5.2.3 5.2.3 μC/OS-II BSPμC/OS-II BSP 编写编写

BSP(板级支持包)是介于底层硬件和操作系统之间的软件层次,它完成系统上电后最初的硬件和软件初始化,并对底层硬件进行封装,使得操作系统不再面对具体的操作。

BSP的特点:硬件相关性:因为嵌入式实时系统的硬件环境具有应用相关性,所以,作为高层软件与硬件之间的接口, BSP必须为操作系统提供操作和控制具体硬件的方法。操作系统相关性:不同的操作系统具有各自的软件层次结构,因此,不同的操作系统具有特定的硬件接口形式。

Page 52: 第五章   C/OS-II 在 ARM 系统中的应用与开发

52

嵌入式系统初始化过程及 BSP功能

Page 53: 第五章   C/OS-II 在 ARM 系统中的应用与开发

53

系统调用通用设备驱动程序与BSP 的关系

Page 54: 第五章   C/OS-II 在 ARM 系统中的应用与开发

54

设计 BSP 的方法

一、以典型的 BSP 做为参考

二、参照操作系统或芯片厂商提供的 BSP模板

Page 55: 第五章   C/OS-II 在 ARM 系统中的应用与开发

55

μC/OS-II BSP for ARM

μC/OS-II 的 BSP, 它首先设置 CPU内部寄存器和系统堆栈,并初始化堆栈指针,建立程序的运行和调用环境; 然后可以方便地使用 C语言设置 ARM片选地址( CS0~ CS7)、 GPIO以及 SDRAM控制器,初始化串口( UART0)作为默认打印口,并向操作系统提供一些硬件相关例程和函数如 dprintf(),以方便调试; 在 CPU、板级和程序自身初始化完成后,就可以把 CPU的控制权交给操作系统了

Page 56: 第五章   C/OS-II 在 ARM 系统中的应用与开发

56

5.3 基于 µC/ OS-Ⅱ 的应用开发 需要说明的是, uCOS-II作为一个实时操作系统只提供了多任务调度等基本功能,这在实际应用中显然是不够的。除了移植好的操作系统内核部分,还必须有文件系统,全部硬件的驱动程序,图形 API,控件函数,综合提高的消息函数以及几个系统必须的基本任务,象键盘,触摸屏, LCD刷新等。有了这些, uCOS-II才能实现复杂的功能。特殊需求的地方还需要像 USB通信协议, TCP/IP协议等更复杂的软件模块。 我们提供的 uCOS-II库文件中包含了上述大部分功能,基于库的开发变的非常简单,在基本的程序框架下应用提供的丰富 API函数即可。实际开发中,用户的工程中无需包括 uCOS-II的源代码,只需要包括库文件即可。当然,用户也可以了解库中部分代码的源文件,可以根据自己的需求就行重新编译,也可以对自己的一系列源文件生成一个专门的库,方便自己后续工作。

Page 57: 第五章   C/OS-II 在 ARM 系统中的应用与开发

57

uCOS-II 的开发中,应用程序和操作系统是绑在一起编译的,所生成的 system.bin文件是唯一的可执行文件,其中包括了所需要的 uCOS-II 代码和被用到的驱 动 程 序 等 函 数 代 码 , 以 及 应 用 程 序 的 代码。 system.bin文件是存放在平台的 16M FLASH中的,在系统启动时由 BIOS依靠文件系统从 FLASH中读入到 SDRAM 中,然后把控制转移到该代码上,完成所谓的引导。而 BIOS 是存储在另外的 ROM 中的。 目前提供了基于库的 uCOS-II 开发框架,读者可以打开工程进行了解。图 5-4 是 ADS环境下看到的该框架的文件组成,读者可以展开各目录查看更多的文件信息。

Page 58: 第五章   C/OS-II 在 ARM 系统中的应用与开发

58

Page 59: 第五章   C/OS-II 在 ARM 系统中的应用与开发

59

可以看出, STARTUP下的都是最基本的硬件初始化和配置文件; Ucos_lib.a 是 ADS环境下的库; SRC是用户编写的工程文件; UCOS-II下都是系统用到的头文件,其中 ADD 下是添加的基本系统任务和消息函数的相关头文件。 INC 下主要是硬件驱动程序的头文件。Init下的几个文件是 ADS环境下配置存储器及堆栈的,和 UCOS-II无直接关系。 打开 Main.c文件,可以看到一个应用工程的基本框架,在这个实验中,所谓的应用很简单,就是在 LCD 上显示“ Hello world!” ,大部分代码都是框架。用户可以在这些代码的基础上进行应用开发,创建新任务,编写必要的函数。当然,如果针对特定的项目有相对独立并集中的一些函数则最好新建源文件和头文件,以方便管理,这些用户新建的源文件可以放到 SRC目录下,在编译环境下用 Add Files命令加入对应位置。

Page 60: 第五章   C/OS-II 在 ARM 系统中的应用与开发

60

下面是 Main()函数中的内容: int main(void){

ARMTargetInit(); //开发板初始化

OSInit(); //操作系统初始化

uHALr_ResetMMU(); //复位 MMULCD_Init(); //初始化 LCD模块LCD_printf("LCD initialization is OK\n"); //向

液晶屏输出数据initOSGUI(); //初始化图形界面LoadFont(); //调 Unicode字库LoadConfigSys(); //使用 config.sys文件配置系

统设置LCD_printf("Create task on uCOS-II...\n");OSTaskCreate(Main_Task, (void *)0,

(OS_STK )&Main_Stack[STACKSIZE*8-1], Main_Task_Prio); // 创建系统任务

OSAddTask_Init(); //创建系统附加任务

Page 61: 第五章   C/OS-II 在 ARM 系统中的应用与开发

61

LCD_printf("Starting uCOS-II...\n");LCD_printf("Entering graph mode...\n");LCD_ChangeMode(DspGraMode); // 变

LCD显示模式为图形模式InitRtc(); // 初始化系统时钟Nand_Rw_Sem=OSSemCreate(1); //创

建 Nand-Flash读写控制权旗语 , 初值为 1满足互斥条件OSStart(); // 操作系统任务调度开始 // 不会执行到这里return 0;

}main()函数中调用了必要的初始化函数,创建了系统任务和用户任务,然后启动系统任务调度。建议用户不要改动该函数中的初始化过程,但可以按任务创建方法来创建更多的任务,注意每个任务必须具有不同的优先级。

Page 62: 第五章   C/OS-II 在 ARM 系统中的应用与开发

62

3.1 在 µC/ OS-Ⅱ 系统上的应用程序结构

1 .任务一个任务通常是一个无限循环,也如同其他 C 的

函数一样,具有函数返回类型,有形式参数变量,但是,任务是不会返回参数的。void YourTask(void *pdata){for(;;){/ * 用户代码 * /}OSTaskDel(OS_PRIO_SELF);}

Page 63: 第五章   C/OS-II 在 ARM 系统中的应用与开发

63

形式参数变量是由用户代码在第一次执行的时候带入的,该变量的类型是一个指向 void的指针。这是为了允许用户应用程序传递任何类型的数据给任务。不同的是,当任务完成以后,任务可以自我删除。任务代码并非真的删除了, µC /OS-II 只是简单地不再理会这个任务了,这个任务的代码也不会再运行,如果任务调用了OSTaskDel()函数,这个任务绝不会返回什么。为了使 µC / OS-II 能管理用户任务,用户必须在建立一个任务的时候,将任务的起始地址与其 他 参 数 一 起 传 给 任 务 创 建 函 数OSTaskCreate() 或 任 务 创 建 扩 展 函 数OSTaskCreateExt() 这两个函数中的任一个。

Page 64: 第五章   C/OS-II 在 ARM 系统中的应用与开发

64

2 . µC/ OS-II的启动系统多任务的启动是用户通过调用 OSStart()函数来实现的。然而 , 启动 µC/ OS-II之前,用户至少要建立一个应用任务。void main(void){ OSInit();/ * 初始化 µC/ OS—II * /…通 过 调 用 OSTaskCreate() 或OSTaskCreateExt()创建至少一个任务 … OSStart() ;/ * 开始多任务调度 !OSStart()永远不会返回。}

Page 65: 第五章   C/OS-II 在 ARM 系统中的应用与开发

65

5.3.2 µC / OS-Ⅱ 的 API任何一个操作系统都会提供大量的应用程序接口 API供开发者使用, µC/ OS-Ⅱ 也不例外。由于 µC/ OS-Ⅱ面向的是实时嵌入式系统开发,并不要求大而全。所以,内核提供的 API也就大多与多任务相关。主要有如下几类:任务类、消息类、同步类、时间类及临界区与事件类。下面介绍几个比较重要的 API函数。 1). OSTaskCreate()函数 该函数在使用前,至少应在主函数 main()内被调用一次,同时要求是在调用 OSInit()函数之后才可再调用该函数,它的作用就是创建一个任务。 OSTaskCreate()函数有 4个参数,它们分别是任务的入口地址、任务的参数、任务堆栈的首地址和任务的优先级。在调用这个函数后,系统会首先从 TCB空闲列表内申请一个空的 TCB指针,然后根据用户给出的参数初始化任务堆栈,并在内部的任务就绪表内标记该任务为就绪状,然后返回。这样,一个任务就创建成功了。

Page 66: 第五章   C/OS-II 在 ARM 系统中的应用与开发

66

2). OSTaskSuspend()函数 该函数可将指定的任务挂起。如果挂起的是当前任务,那么还会引发系统执行任务切换先导函数 OSShed()来进行一次任务切换。实际上,这个函数只有一个指定任务优先级的参数。事实上在系统内部,优先级除了表示一个任务执行的先后次序外,还起着区分每一个任务的作用。换句话说,优先级也就是任务的 ID。所以,µC/ OS-Ⅱ 不允许出现相同优先级的任务。 3). OSTaskResume()函数 该函数与 OSTaskSuspend()函数的作用正好相反,它用于将指定的已经挂起的函数恢复为就绪状态。如果恢复任务的优先级高于当前任务,那么还将引发一次任务切换。其参数类似于 OSTaskSuspend()函数,用来指定任务的优先级。需要特别说明的是,该函数并不要求和 OSTaskSuspend()函数成对使用。

Page 67: 第五章   C/OS-II 在 ARM 系统中的应用与开发

67

4 ). OS_ENTER_CRITICAL()宏 由 OS_CPU . H 文件可知, OS_ENTER_CRITICAL()和下面要谈到的OS_EXIT_CRITI_CAL()都是宏,它们都与特定的 CPU相关,一般都被替换为一条或者几条嵌入式汇编代码。由于系统希望向上层开发者隐藏内部实现,故一般都宣称执行此条指令后系统进入临界区。其实,它就是关个中断而已。这样,只要任务不主动放弃 CPU使用权,别的任务就没有占用 CPU的机会了。相对这个任务而言,它就是独占了,所以说进入临界区了。这个宏应尽量少用,因为它会破坏系统的一些服务,尤其是时间服务,并使系统对外界响应性能降低。

Page 68: 第五章   C/OS-II 在 ARM 系统中的应用与开发

68

5) . OS_EXIT__CRITICAL()宏 该宏与上面介绍的宏配套使用,在退出临界区时使用。其实它就是重新开中断。需要注意的是,它必须和上面的宏成对出现,否则会带来意想不到的后果。严重时会使系统崩溃。因此,建议程序员尽量少用这两个宏调用,使用它们会破坏系统的多任务性能。 6) . OSTimeDly()函数 该函数实现的功能是先挂起当前任务,然后进行任务切换。在指定的时间到来之后,将当前任务恢复为就绪状态,但并不一定运行。如果恢复后是优先级最高的就绪任务,那么运行之。简而言之,就是可使任务延时一定时间后再次执行它。或者说,暂时放弃 CPU的使用权。一个任务可以不显式地调用这些可导致放弃 CPU使用权的 API,但那样多任务性能会大大降低。因为,此时仅仅依靠时钟机制在进行任务切换,一个好的任务应在完成一些操作后主动放弃 CPU的使用权。

Page 69: 第五章   C/OS-II 在 ARM 系统中的应用与开发

69

5.3.3 绘图函数介绍以及开发范例µC / OS-Ⅱ 仅仅是一个实时多任务的内核。移植 µC /OS-Ⅱ 到具体的微处理器平台以后,离实际的应用还是有些距离的。通常根据实际项目要求,需要对 µC/ OS-Ⅱ进行扩展,建立一个简单实用的实时操作系统。比如,添加外设驱动程序、添加文件系统、以及添加基本的绘图函数。绘图是操作系统的图形界面的基础, µC / OS-Ⅱ 操作系统为图形界面提供了丰富的绘图函数。在多任务操作系统中,绘图设备上下文 (DC)是绘图的关键。绘图设备上下文 (DC)保存了每一个绘图对象的相关参数 (如绘图画笔的宽度、绘图的原点坐标等 ) 。在多任务操作系统中,通过绘图设备上下文 (DC)来绘图,可以保证在不同的任务中绘图的参数是相互独立的,不会互相影响。 常用的绘图函数( 35个函数)

Page 70: 第五章   C/OS-II 在 ARM 系统中的应用与开发

70

typedef struct{int DrawPointx;int DrawPointy; // 绘图所使用的坐标点int PenWidth; // 画笔宽度U32 PenMode; // 画笔模式COLORREF PenColor; // 画笔的颜色int DrawOrgx; // 绘图的坐标原点位置int DrawOrgy;int WndOrgx; // 绘图的窗口坐标位置int WndOrgy;int DrawRangex; // 绘图的区域范围int DrawRangey;structRECT DrawRect;// 绘图的有效范围U8 bUpdataBuffer; // 是否更新后台缓冲区及显示U32 Fontcolor; // 字符颜色

}DC,*PDC

Page 71: 第五章   C/OS-II 在 ARM 系统中的应用与开发

71

initOSDC定义: void initOSDC()功能:初始化系统的绘图设备上下文( DC ),为DC 的动态分配开辟内存空间CreateDC定义: PDC CreateDC()功能:创建一个绘图设备上下文( DC ),返回指向 DC 的指针DestoryDC定义: void DestoryDC(PDC pdc)功能:删除绘图设备上下文( DC ),释放相应的资源参数说明: pdc :指向绘图设备上下文( DC )的指针

Page 72: 第五章   C/OS-II 在 ARM 系统中的应用与开发

72

TextOut定义: void TextOut(PDC pdc, int x, int y, U16 *ch, U8 bunicode, U8 fnt)功能:在 LCD 屏幕上显示文字参数说明: pdc :指向绘图设备上下文( DC )的指针x,y :所输出文字左上角的屏幕坐标ch :指向输出文字字符串的指针bunicode :是否为 Unicode 编码,如果是 TRUE ,表示 ch 指向的字符串为 Unicode 字符集;如果为 FALSE ,表示表示 ch 指向的字符串为 GB 字符集。fnt :指定字体的大小型号

Page 73: 第五章   C/OS-II 在 ARM 系统中的应用与开发

73

MoveTo

定义: void MoveTo(PDC pdc, int x, int y)

功能:把绘图点移动到指定的坐标参数说明: pdc :指向绘图设备上下文( DC )的指针x,y :移动画笔到绘图点的屏幕坐标LineTo

定义: void LineTo(PDC pdc, int x, int y)

功能:在屏幕上画线。从当前画笔的位置画直线到指定的坐标位置,并使画笔停留在当前指定的位置参数说明: pdc :指向绘图设备上下文( DC )的指针x,y :直线绘图目的点的屏幕坐标

Page 74: 第五章   C/OS-II 在 ARM 系统中的应用与开发

74

Circle定义: void Circle(PDC pdc, int x0, int y0, int r)功能:绘制指定圆心和半径的圆参数说明: pdc :指向绘图设备上下文( DC )的指针x0,y0 :圆心坐标r :圆的半径

ArcTo定义: void ArcTo(PDC pdc, int x1,int y1, U8 arctype, int R)功能:绘制圆弧,从画笔的当前位置绘制指定圆心的圆弧到给定的位置参数说明: pdc :指向绘图设备上下文( DC )的指针x1,y1 :绘制圆弧的目的位置arctype :圆弧的绘制模式R :圆弧的半径

Page 75: 第五章   C/OS-II 在 ARM 系统中的应用与开发

75

SetDrawOrg定义: void SetDrawOrg(PDC pdc, int x,int y, int* oldx, int *oldy)功能:设置绘图设备上下文( DC )的原点参数说明: pdc :指向绘图设备上下文( DC )的指针x,y :设定的新原点oldx,oldy :返回的以前原点的位置

ClearScreen定义: void ClearScreen()功能:清除整个屏幕的绘图缓冲区,即:清空LCDBuffer2

Page 76: 第五章   C/OS-II 在 ARM 系统中的应用与开发

76

FillRect定义: void FillRect(PDC pdc, int left,int top ,int right, int bottom,U32 DrawMode , COLORREF color)

功能:在屏幕上填充指定大小的矩形。参数说明: pdc :指向绘图设备上下文( DC )的指针left :绘制矩形的左边框位置right :绘制矩形的右边框位置top :绘制矩形的上边框位置bottom :绘制矩形的下边框位置DrawMode :矩形的的填充模式和颜色color :填充的颜色值,高 8 位为空,接下来的 24 位分别对应 RGB 颜色的 8 位码

Page 77: 第五章   C/OS-II 在 ARM 系统中的应用与开发

77

Draw3DRect定义: void Draw3DRect(PDC pdc, int left,int top, int right, int botton, COLORREF color1,COLORREF color2)功能:绘制指定大小和风格的 3D 边框的矩形参数说明: pdc :指向绘图设备上下文( DC )的指针left :绘制矩形的左边框位置right :绘制矩形的右边框位置top :绘制矩形的上边框位置bottom :绘制矩形的下边框位置color1 :左和上的边框颜色,高 8 位为空,接下来的24 位分别对应 RGB 颜色的 8 位码。color2 :右和下的边框颜色,高 8 位为空,接下来的24 位分别对应 RGB 颜色的 8 位码。

Page 78: 第五章   C/OS-II 在 ARM 系统中的应用与开发

78

SetPenWidth

定义: U8 SetPenWidth(PDC pdc, U8 width)

功能:设置画笔的宽度,并返回以前的画笔宽度参数说明: pdc :指向绘图设备上下文( DC )的指针width :画笔的宽度,默认值是 1 ,即一个像素点宽

SetPenMode

定义: void SetPenMode(PDC pdc, U32 mode)

功能:设置画笔画图的模式参数说明: pdc :指向绘图设备上下文( DC )的指针mode :绘图的更新模式

Page 79: 第五章   C/OS-II 在 ARM 系统中的应用与开发

79

GetBmpSize定义: void GetBmpSize(char filename[], int* Width, int* Height)功能:取得指定位图文件位图的大小参数说明: filename[] :位图文件的文件名Width :位图的宽Height :位图的高

ShowBmp定义: void ShowBmp(PDC pdc, char filename[], int x, int y)功能:显示指定的位图( Bitmap )文件,到指定的坐标参数说明: pdc :指向绘图设备上下文( DC )的指针filename[] :显示的位图( Bitmap )文件名x,y :显示位图的左上角坐标

Page 80: 第五章   C/OS-II 在 ARM 系统中的应用与开发

80

5.4 构建的 TCP/IP/PPP协议栈1)嵌入式协议栈概述嵌入式协议栈的运行必须基于嵌入式操作系统平台的支持,可以与大多数嵌入式操作系统集成运行。但是,协议栈以及附带的上层接口和下层驱动程序会给嵌入式系统设计设置其他的约束。例如,协议栈必须有准确的时间源,以便进行时间管理。2)选择协议栈首先要根据应用环境和使用的网络技术来选择合适的网络协议栈。例如,开发的嵌入式产品是基于网络的打印机,可以选择 TCP/IP的协议栈。

Page 81: 第五章   C/OS-II 在 ARM 系统中的应用与开发

81

为嵌入式系统选择网络协议栈需要从三方面进行考虑:( 1)网络协议栈占用的内存;( 2)硬件资源,如通信控制器、物理层接口等;( 3 ) CPU运行协议时的开销。3)嵌入式 TCP/IP协议栈嵌入式系统通过以太网、电力线和电话线等载体可以实现与 Internet互连;也可以利用无线接入技术解决基础电缆不到位的问题。如果是与局域网连接,则只需要为嵌入式设备配备以太网卡和 IP地址即可。如果是利用电话线路,则设备可以使用电话用户的 ID,通过PPP协议与 TCP/IP进行互联,在这里 PPP协议运载IP数据包。通过其网络协议栈几乎可以从世界上任何地方来的访问或控制这些实现了互联的嵌入式装置。

Page 82: 第五章   C/OS-II 在 ARM 系统中的应用与开发

82

一般情况下, RTOS都提供了 TCP/IP协议栈,并可以进行裁减。嵌入式 TCP/IP协议栈省去了诸如接口间转发软件、全套 Internet服务工具以及支持电子邮件的工具等几个协议,这些软件工具在嵌入式装置中很少使用。嵌入式协议栈的一些指标和接口可能与普通的协议栈的区别可在如下几个方面:( 1)两者的 API可能不同;( 2)嵌入式协议栈具有可裁减性;( 3)嵌入式 TCP/IP协议栈的平台具有兼容性,便于移植;( 4 )嵌入式协议栈的效率较高,代码少可减少对处理器的处理速度的要求。