1、嵌入式系统胡威武汉科技大学计算机学院C/OS-II程序设计基础C/OS-II程序设计基础程序设计基础绪论绪论 本章重点介绍C/OS-II V2.52版本嵌入式实时操作系统常用函数的基本用法,其最大的特点不仅示例程序简洁明了,而且电路也非常简单(如下图),希望初学者一看就懂、一学就会,达到快速入门的目的。注意:本章所有应用示例都全部默认采用这个图,主要是为了尽量简化示例程序,提高可读性,使用简单明了的语言和方法来解析复杂的理论知识,这是作者在多年的学习、工作和教学中一直倡导的风格和习惯性的行为,同时这也是写作本书的出发点。硬件去抖目 录任务设计任务设计系统函数使用场合系统函数使用场合系统函数概述
2、系统函数概述时间管理时间管理事件的一般使用规则事件的一般使用规则系统管理系统管理1互斥信号量互斥信号量信号量信号量事件标志组事件标志组消息邮箱消息邮箱动态内存管理动态内存管理消息队列消息队列23465789101211C/OS-II程序设计基础程序设计基础任务设计任务设计任务的任务的分类任务的优先级任务的优先级任务的划分任务的划分123任务设计任务设计|C/OS-II程序设计基础程序设计基础任务设计任务设计 在基于实时操作系统的应用程序设计中,任务设计是整个应用程序的基础,其它软件设计工作都是围绕任务设计来展开。任务设计应用程序设计“任务函数”和相关的数据结构其他软件工作任务设计任务设计|C/
3、OS-II程序设计基础程序设计基础任务的分类任务的分类按照执行方式分类任务设计任务设计|C/OS-II程序设计基础程序设计基础任务的分类任务的分类1.单次执行类任务void MyTask(void*pdata)进行准备工作的代码;任务实体代码;调用任务删除函数;运行运行创建删除删除单次执行类任务定义和初始化变量及硬件设备 完成该任务的具体功能 将自己删除,操作系统将不再管理它 任务设计任务设计|C/OS-II程序设计基础程序设计基础任务的分类任务的分类执行状态等待状态就绪状态void MyTask(void*pdata)进行准备工作的代码;while(1)任务实体代码;调用系统延时函数;延时时
4、间到延时时间到2.周期执行类任务任务优先级足够高任务优先级足够高任务设计任务设计|C/OS-II程序设计基础程序设计基础任务的分类任务的分类3.事件触发执行类任务void MyTask(void*pdata)进行准备工作的代码;while(1)调用获取事件的函数;任务实体代码;等待信号量或消息运行状态运行状态等待状态等待状态运行状态运行状态就绪状态就绪状态 任务优先级足够高消息完成具体功能任务设计任务设计|C/OS-II程序设计基础程序设计基础任务的划分任务的划分1.任务划分的目标 在对一个具体的嵌入式应用系统进行任务划分时,可以有不同的任务划分方案。为了选择最佳划分方案,就必须知道任务划分的
5、目标。高效率的系统高效率的系统1.首要目标是满足首要目标是满足“实时性实时性”指标指标:即使在最坏的情况下,系统中所有对实时性有要求的功能都能够正常实现;3.简化软件系统:简化软件系统:一个任务要实现其功能,除了需要操作系统的调度功能支持外,还需要操作系统的其它服务功能支持,合理划分任务,可以减少对操作系统的服务要求,简化软件系统;4.降低资源需求:降低资源需求:合理划分任务,减少或简化任务之间的同步和通信需求,就可以减少相应数据结构的内存规模,从而降低对系统资源的需求。2.任务数目合理:任务数目合理:对于同一个应用系统,合理的合并一些任务,使任务数目适当少一些还是比较有利;任务设计任务设计|
6、C/OS-II程序设计基础程序设计基础任务的划分任务的划分2.任务划分的方法 任务的划分方法,请参考下一章“基于LPC2000的电脑自动打铃器设计与实现”。传递性:传递性:信息传递的上游任务的优先级高于下游任务的优先级。如信号采集任务的优先级高于数据处理任务的优先级。紧迫性:紧迫性:因为紧迫任务对响应时间有严格要求,在所有紧迫任务中,按响应时间要求排序,越紧迫的任务安排的优先级越高。紧迫任务通常与ISR关联;关键性:关键性:任务越关键安排的优先级越高,以保障其执行机会;中断关联性中断关联性:与中断服务程序(ISR)有关联的任务应该安排尽可能高的优先级,以便及时处理异步事件,提高系统的实时性。如
7、果优先级安排得比较低,CPU有可能被优先级比较高的任务长期占用,以致于在第二次中断发生时连第一次中断还没有处理,产生信号丢失现象;频繁性:频繁性:对于周期性任务,执行越频繁,则周期越短,允许耽误的时间也越短,故应该安排的优先级也越高,以保障及时得到执行;快捷性:快捷性:在前面各项条件相近时,越快捷(耗时短)的任务安排的优先级越高,以使其它就绪任务的延时缩短;任务设计任务设计|C/OS-II程序设计基础程序设计基础任务的优先级任务的优先级 任务的优先级安排原则如下:紧迫性紧迫性任务优先级 关键性关键性中断关联性中断关联性快捷性快捷性频繁性频繁性传递性传递性C/OS-II程序设计基础程序设计基础系
8、统函数概述系统函数概述基本原则基本原则系统函数的分类系统函数的分类12系统函数概述系统函数概述|C/OS-II程序设计基础程序设计基础基本原则基本原则1.配对性原则 对于C/OS-II来说,大多数API都是成对的,而且一部分必须配对使用。当然,查询状态的系统函数一般不需要配对使用,而且部分API如延时,也不需要配对使用。配对的函数见下表。函数1功能函数2功能备注OSFlagPend()等待事件标志组的事件标志位OSFlagPost()置位或清0事件标志组中的标志不必须配对使用,一般不在同一个任务中(用于资源同步时必须同一个任务中配对使用)OSMboxPend()等待消息邮箱中的消息OSMbox
9、Post()或OSMboxPostOpt()以不同的方式向消息邮箱发送消息OSQPend()等待消息队列中的消息OSQPost()或OSQPostFront()或OSQPostOpt()以不同的方式向消息队列发送一条消息OSSemPend()等待一个信号量OSSemPost()发送一个信号量OSMutexPend()等待一个互斥信号量OSMutexPost()释放一个互斥信号量必须在同一个任务中配对使用函数1功能函数2功能备注OSTimeGet()获得系统时间OSTimeSet()设置系统时间不必配对使用OSIntEnter()进入中断处理OSIntExit()退出中断处理必须在中断服务程序中
10、配对使用OSSchedLock()给调度器上锁OSSchedUnlock()给调度调度必须在一个任务中配对使用OS_ENTER_CRITICAL()进入临界区OS_EXIT_CRITICAL()退出临界区必须在一个任务或中断中配对使用函数1功能函数2功能备注OSMemGet()分配一个内存块OSMemPut()释放一个内存块必须配对使用OSTaskCreate()或OSTaskCreateExt()建立任务OSTaskDel()删除任务动态使用任务时必须配对使用OSTaskSuspend()挂起任务OSTaskResume()恢复任务必须配对使用OSTimeDly()或OSTimeDlyHMS
11、M()延时OSTimeDlyResume()恢复延时的任务不必配对使用。OSTimeDlyHMSM()可能需要多个OSTimeDlyResume()才能恢复函数1功能函数2功能备注OSFlagCreate()建立事件标志组OSFlagDel()删除事件标志组动态使用事件时必须配对使用OSMboxCreate()建立消息邮箱OSMboxDel()删除消息邮箱OSMutexCreate()建立互斥信号量OSMutexDel()删除互斥信号量OSQCreate()建立消息队列OSQDel()删除消息队列OSSemCreate()建立信号量OSSemDel()删除信号量系统函数概述系统函数概述|C/O
12、S-II程序设计基础程序设计基础基本原则基本原则2.中断服务程序调用函数的限制 中断服务程序不能调用可能会导致任务调度的函数,它们主要是一些等待事件的函数,这些函数及其替代函数见下表。注意:未列入表中的函数OSTaskCreate()、OSTaskCreateExt()、OSTaskDel()、OSTaskResume()、OSTaskChangePrio()、OSTaskSuspend()、OSTimeDly()、OSTimeDlyHMSM()、OSTimeResume()都属于在中断服务程序中禁止调用的函数。禁止使用的函数替代函数功能备注OSFlagPend()OSFlagAccept()
13、无等待获得事件标志组的事件标志位需要程序自己判断是否获得了相应的事件OSMboxPend()OSMboxAccept()无等待获得消息邮箱中的消息OSMutexPend()OSMutexAccept()无等待获得一个互斥信号量OSQPend()OSQAccept()无等待获得息队列中的消息OSSemPend()OSSemAccept()无等待获得一个信号量系统函数概述系统函数概述|C/OS-II程序设计基础程序设计基础基本原则基本原则1.创建事件和删除事件的函数。一些函数虽然没有明确地规定不能被中断服务程序调用,但因为中断服务程序的特性,一般不会使用。2.与任务相关的函数OSTaskChang
14、ePrio()、OSTaskDelReq()、OSTaskStkChk()和OSTaskQuery()。至于函数OSSchedLock()和OSSchedUnlock(),在中断服务程序中使用没有任何意义。系统函数概述系统函数概述|C/OS-II程序设计基础程序设计基础基本原则基本原则3.任务必须调用某个系统函数 因为C/OS-II是完全基于优先级的操作系统,所以在一定的条件下必须出让CPU占有权以便比自己优先级更低的任务能够运行,这是通过调用部分系统函数来实现的,这些函数见下表。一般的任务必须调用表中至少一个函数,只有一种情况例外,就是单次执行的任务,因为任务删除后肯定出让CPU,所以可以不
15、调用表中的函数。函数名功能函数名功能OSFlagPend等待事件标志组的事件标志位OSMutexPend等待一个互斥信号量OSQPend等待消息队列中的消息OSQPend等待消息队列中的消息OSSemPend等待一个信号量OSTaskSuspend 挂起任务OSTimeDly延时OSTimeDlyHMSM延时一般的操作系统都提供时间管理的函数,最基本的就是延时函数,C/OS-II也不例外,C/OS-II所具有的时间管理函数见下表。C/OS-II具有简单的动态内存管理能力。C/OS-II的动态内存管理函数见下表。任务管理函数是操作与任务相关功能的函数,详见下表。系统管理函数是一些与C/OS-II
16、内核或功能相关的一些函数,详见下表。C/OS-II的初始化函数有2个:OSInit()和OSStart(),它们不能在任何任务和中断服务程序中使用,仅在main()函数中按照一定的规范被调用,其中OSInit()函数初始化C/OS-II内部变量,OSStart()函数启动多任务环境。C/OS-II把信号量等都称为事件,管理它们的就是事件管理函数。C/OS-II V2.52具有的事件有普通信号量、互斥信号量、事件标志组、消息邮箱和消息队列,这些都是C/OS-II用于同步与通讯的工具,本章后述的内容将会详细介绍。系统函数概述系统函数概述|C/OS-II程序设计基础程序设计基础系统函数的分类系统函数
17、的分类初始化初始化任务管理任务管理时间管理时间管理内存管理内存管理根据功能分类事件管理事件管理函数名功能备注OSStatInit()使能任务统计功能复位一次只能调用一次,并且必须在任务中调用,在调用时其它用户任务不能处于就绪状态OSIntEnter()进入中断处理必须由中断服务程序按照规范调用,使用本公司的模版就不需要调用它们OSIntExit()退出中断处理OSSchedLock()锁调度器必须配对使用,一般情况不需要使用。事实上,C/OS-II不推荐使用它们OSSchedUnlock()解锁调度器OS_ENTER_CRITICAL()进入临界区必须配对使用,一般通过禁止中断和允许中断来实现
18、的。对于一些移植代码来说,不能嵌套调用OS_EXIT_CRITICAL()退出临界区函数名功能函数名功能OSTaskChangePrio()改变任务优先级OSTaskSuspend()挂起任务OSTaskCreate()建立任务OSTaskResume()恢复任务OSTaskCreateExt()建立任务,比OSTaskCreate()控制任务属性更多OSTaskStkChk()检查堆栈OSTaskDel()删除任务OSTaskQuery()获得任务信息OSTaskDelReq()请求删除任务,有特殊用途系统管理系统管理函数名功能备注OSTimeDly()以时钟节拍为单位延时OSTimeDly
19、HMSM()以钟时分秒毫秒为单位延时OSTimeDlyResume()恢复延时的任务OSTimeDlyHMSM()可能需要多次才能恢复OSTimeGet()获得系统时间以时钟节拍为单位OSTimeSet()设置系统时间以时钟节拍为单位OSTimeTick()时钟节拍处理函数由时钟节拍中断处理程序调用,用户很少使用函数名功能OSMemCreate()初始化一个堆OSMemGet()从指定堆中获得一个内存块OSMemPut()从指定堆中释放一个内存块OSMemQuery()查询指定堆的状态C/OS-II程序设计基础程序设计基础系统函数使用场合系统函数使用场合时间管理时间管理行为同步行为同步资源同步
20、资源同步123系统函数使用场合系统函数使用场合|C/OS-II程序设计基础程序设计基础时间管理时间管理1.控制任务的执行周期 void MyTask(void*pdata)进行准备工作的代码;while(1)任务实体代码;调用系统延时函数;调用OSTimeDly()或OSTimeDlyHMSM()无限循坏注意:延时函数OSTimeDly()是以系统节拍数为参数,而延时函数OSTimeDlyHMSM()是以实际时间值为参数,但在执行过程中仍然转换为系统节拍数。如果实际时间不是系统节拍的整数倍,将进行四舍五入处理。设系统节拍为50毫秒,调用OSTimeDly(20)的效果是延时1秒钟,调用OSTi
21、meDlyHMSM(0,1,27,620)的实际时间是延时1分27秒600毫秒。在任务函数的代码中可以通过插入延时函数来控制任务周期性运行,定时闲置CPU一段时间,供其它任务使用。系统函数使用场合系统函数使用场合|C/OS-II程序设计基础程序设计基础时间管理时间管理2.控制任务的运行节奏 在任务函数的代码中也可以通过插入延时函数来控制任务的运行节奏。void MyTask(void*pdata)进行准备工作的代码;while(1)调用获取事件的函数;第一部分操作代码;调用系统延时函数;第二部分操作代码;调用系统延时函数;第三部分操作代码;各种时间顺序控制任务可以用这种结构的任务函数实现。调用
22、OSTimeDly()或OSTimeDlyHMSM()调用OSTimeDly()或OSTimeDlyHMSM()等待信号量、消息其他任务代码无限循环系统函数使用场合系统函数使用场合|C/OS-II程序设计基础程序设计基础时间管理时间管理3.状态查询 查询过程是一个无限循环过程,只有当希望的状态出现以后才能退出这个无限循环,这种情况在实时操作系统管理下是不允许的,它将剥夺低优先级任务的运行机会。解决这个问题的办法是“用定时查询代替连续查询”。void MyTask(void*pdata)进行准备工作的代码;while(1)while(查询的条件不成立)调用系统延时函数;其它处理代码;不成立,延时
23、再查询,同时让出cpu占有权,供低优先级任务使用查询条件成立,运行后续代码定时查询条件是否成立无限循环系统函数使用场合系统函数使用场合|C/OS-II程序设计基础程序设计基础资源同步资源同步共享资源共享资源临界区访问共享资源临界区访问共享资源等待共享资源申请共享资源.申请共享资源.任务1任务2释放临界区互斥,保证共享资源的完整性和可靠性释放1.“资源同步”图解1.使用关中断:使用关中断:通过调用禁止中断函数OS_ENTER_CRITICAL()和允许中断函数OS_EXIT_CRITICAL()实现的。2.使用关调度:使用关调度:通过调用禁止任务调度函数OSSchedLock()和允许任务调度函
24、数OSSchedUnlock()实现的,因为禁止调度违背了多任务的初衷,所以不建议用户使用。3.使用信号量与互斥信号量:使用信号量与互斥信号量:通过等待信号量和发送信号量实现共享资源的独享。系统函数使用场合系统函数使用场合|C/OS-II程序设计基础程序设计基础资源同步资源同步2.“资源同步”实现方式 系统函数使用场合系统函数使用场合|C/OS-II程序设计基础程序设计基础行为同步行为同步消息消息收到消息.等待消息.任务1任务2发送消息 一个任务的运行过程需要和其它任务的运行配合,才能达到预定的效果,任务之间的这种动作配合和协调关系称为“行为同步”。任务优先级足够高1.行为同步 信号量 事件标
25、志组 消息邮箱 消息队列 任务之间的通讯同步系统函数使用场合系统函数使用场合|C/OS-II程序设计基础程序设计基础行为同步行为同步2.数据通信 数据通讯时是否需要遵守“资源同步”规则 数据通讯的同时是否具有“行为同步”功能消息邮箱消息邮箱不需要有消息队列消息队列 不需要有全局变量全局变量需要无注意:尽管指针可能是局部变量,但只要指针指向的变量是全局变量,操作指针指向的变量时也需要当作全局变量来处理。C/OS-II程序设计基础程序设计基础时间管理时间管理系统延时函数OSTimeDly()强制延时的任务结束延时OSTimeDlyResume()系统延时函数OSTimeDlyHMSM()123获得
26、系统时间OSTimeGet()和设置系统时间OSTimeSet()4时间管理时间管理|C/OS-II程序设计基础程序设计基础概述概述 C/OS-II提供了若干个时间管理服务函数,可以满足任务在运行过程中对时间管理的需求。在使用时间管理服务函数时,必须十分清楚一个事实:时间管理服务函数是以系统节拍为处时间管理服务函数是以系统节拍为处理单位的,实际的时间与希望的时间是有误差的,最坏的情况理单位的,实际的时间与希望的时间是有误差的,最坏的情况下误差接近一个系统节拍。下误差接近一个系统节拍。因此时间管理服务函数只能用在对时间精度要求不高的场合,或者时间间隔较长的场合。时间管理时间管理|C/OS-II程
27、序设计基础程序设计基础OSTimeDly()系统延时函数OSTimeDly()调用图解任务进入运行状态任务进入运行状态进入延时,同时发生任务调度进入延时,同时发生任务调度任务调用任务调用OSTimeDly()任务进入就绪状态任务进入就绪状态 当前任务优先级为就绪态中最高延时时间到延时的长短是由时钟节拍的数目来确定时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeDly()下面我们设计一个任务,让一个LED以50个时钟节拍为单位闪耀,说明OSTimeDly()函数的用途。由于篇幅关系,只给出任务主要处理代码。void TaskLED(void *pdata)while(1)IO
28、0CLR=LED1;OSTimeDly(25);IO0SET=LED1;OSTimeDly(25);延时25个节拍 循坏控制LED以固定频率闪烁点亮LED延时25个节拍 熄灭LED初始化代码注意:上面的设计是OSTimeDly()控制任务的周期性执行,还可以用它来控制任务的运行节拍。时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeDlyHMSM()函数名称函数名称OSTimeDlyHMSM所属文件OS_TIMC.C函数原型函数原型INT8U OSTimeDlyHMSM(INT8U hours,INT8U minutes,INT8U seconds,INT16U milli)
29、功能描述功能描述延时,指定的延时时间为时、分、秒、毫秒函数参数函数参数hours:小时,minutes:分钟,seconds:秒,milli:毫秒函数返回值函数返回值OS_TIME_INVALID_MINUTES:minutes参数错误OS_TIME_INVALID_SECONDS:seconds参数错误OS_TIME_INVALID_MILLI:milli参数错误特殊说明特殊说明(1)所有参数为0时不延时,函数直接返回(2)必须正确设置全局常数OS_TICKS_PER_SEC,否则延时时间是错误的(3)因为OSTimeDlyHMSM()是通过多次(或1次)调用OSTimeDly()实现的,所
30、以延时分辨延时分辨率为时钟节拍率为时钟节拍(4)因为OSTimeDlyHMSM()是通过多次(或1次)调用OSTimeDly()实现的,所以可能需要可能需要调用多次调用多次OSTimeDlyResume()才能恢复延时的任务才能恢复延时的任务 C/OS-提供了OSTimeDlyHMSM()系统延时函数,这个函数是以小时(H)、分(M)、秒(S)和毫秒(m)四个参数来定义延时时间的,函数在内部把这些参数转换为时钟节拍,再通过单次或多次调用OSTimeDly()进行延时和任务调度,所以延时原理和调用延时函数OSTimeDly()是一样的。OSTimeDlyHMSM()详细见下表。时间管理时间管理|
31、C/OS-II程序设计基础程序设计基础OSTimeDlyHMSM()为了说明OSTimeDlyHMSM()函数的使用方法,下面我们设计一个任务,让一个LED以2Hz的频率闪耀。下面给出任务主要处理代码。void TaskLED(void *pdata)while(1)IO0CLR=LED1;OSTimeDlyHMSM(0,0,0,250);IO0SET=LED1;OSTimeDlyHMSM(0,0,0,250);250ms延时循坏控制LED以固定频率闪烁点亮LED250ms延时熄灭LED初始化代码注意:上面的设计是OSTimeDlyHMSM()控制任务的周期性执行,还可以用它来控制任务的运行节
32、拍。时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeDlyResume()任务进入运行状态任务进入运行状态任务调用延时函数任务调用延时函数任务进入就绪状态任务进入就绪状态 当前任务优先级为就绪态中最高调用OSTimeDlyResume()延时期延时期 C/OS-允许用户结束正处于延时期的任务,延时的任务可以不等待延时期满,而是通过取消其它任务的延时来使自己处于就绪态,可以通过调用OSTimeDlyResume()和指定要恢复的任务的优先级来完成。时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeDlyResume()函数名称函数名称OSTimeDlyRes
33、ume所属文件OS_TIMC.C函数原型函数原型INT8U OSTimeDlyResume(INT8U prio)功能描述功能描述让延时的任务结束延时函数参数函数参数prio:任务优先级函数返回值函数返回值OS_NO_ERR:成功,OS_PRIO_INVALID:prio错误OS_TIME_NOT_DLY:任务没有延时,OS_TASK_NOT_EXIST:任务不存在特殊说明特殊说明因为因为OSTimeDlyHMSM()是通过多次是通过多次(或或1次次)调用调用OSTimeDly()实现的,所以可能需要调用多次实现的,所以可能需要调用多次OSTimeDlyResume()才能恢复才能恢复延时的任
34、务延时的任务 OSTimeDlyResume()的具体信息见下表。时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeDlyResume()为了说明OSTimeDlyResume()函数的使用方法,我们设计一个系统,假设TaskLED的任务优先级为2。让一个LED以0.5Hz的频率闪耀,但每按键一次,LED状态翻转一次。下面是两个任务的处理流程。时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeDlyResume()TaskLED任务代码如下。void TaskLED(void *pdata)while(1)IO0CLR=LED1;OSTimeDly(OS_T
35、ICKS_PER_SEC);IO0SET=LED1;OSTimeDly(OS_TICKS_PER_SEC);1s延时循坏控制LED以固定频率闪烁点亮LED1s延时熄灭LED初始化代码时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeDlyResume()TaskKEY任务的代码如下。void TaskKEY(void *pdata)while(1)while(IO0PIN&KEY1)!=0)OSTimeDly(1);OSTimeDlyResume(2);while(IO0PIN&KEY1)=0)OSTimeDly(1);延时1个节拍,用于任务切换延时1个节拍,用于任务切换等待
36、按健按下等待按健释放TaskLED优先级为2,恢复TaskLED初始化代码4,294,967,295 调用OSStart()时初始化计数器为0 计数器满时从0开始计数 1324.4,294,967,294 时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeGet()、OSTimeSet()无论时钟节拍何时发生,C/OS-都会将一个32位的计数器加1,这个计数器在用户调用OSStart()初始化多任务和4,294,967,295个节拍执行完一遍的时候从0开始计数。发生时钟节拍32位计数器12n.时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeGet()、OS
37、TimeSet()发生时钟节拍32位计数器 用户可以通过调用OSTimeGet()来获得该计数器的当前值,OSTimeGet()的详细信息见下表。函数名称函数名称OSTimeGet所属文件所属文件OS_TIMC.C函数原型函数原型INT32U OSTimeGet(void)功能描述功能描述获得系统时间函数参数函数参数prio:任务优先级函数返回值函数返回值系统时间ticks=n;调用OSTimeGet()ticks=OSTimeGet();return(n)时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeGet()、OSTimeSet()101102n.发生时钟节拍32位计
38、数器调用OSTimeSet(101)设置计数器值为101 用户可以通过调用OSTimeSet()来改变计数器的值,OSTimeSet()的详细信息见下表。函数名称函数名称OSTimeSet所属文件所属文件OS_TIMC.C函数原型函数原型void OSTimeSet(INT32U ticks)功能描述功能描述设置系统时间函数参数函数参数ticks:需要设置的值函数返回值函数返回值无特殊说明特殊说明很少使用 时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeGet()、OSTimeSet()为了说明OSTimeGet()函数的使用方法,我们设计一个任务,计算两次按键的时间间隔放
39、在全局变量ktime中。下面是任务的处理流程。时间管理时间管理|C/OS-II程序设计基础程序设计基础OSTimeGet()、OSTimeSet()TaskKEY任务代码如下。void TaskKEY(void *pdata)while(1)while(IO0PIN&KEY1)!=0)OSTimeDly(1);ktime=OSTimeGet()-ktime;while(IO0PIN&KEY1)=0)OSTimeDly(1);延时1个节拍,用于任务切换延时1个节拍,用于任务切换等待按健按下等待按健释放获得按键间隔时间初始化代码C/OS-II程序设计基础程序设计基础系统管理系统管理进入然后退出临界
40、区禁止然后允许调度12CPU共享共享进入临界段进入临界段OS_ENTER_CRITICAL()CPU共享共享退出临界段退出临界段OS_EXIT_CRITICAL()当前任务独占当前任务独占CPU 其他任何任务和中断都无法得其他任何任务和中断都无法得到到CPU,直到退出临界段。保,直到退出临界段。保证了临界段代码的运行完整性证了临界段代码的运行完整性系统管理系统管理|C/OS-II程序设计基础程序设计基础进入然后退出临界区进入然后退出临界区 进入然后退出临界段是“资源同步”的方法之一,能够在访问共享资源时保障信息的可靠性和完整性。为了说明它在”资源同步”时的使用,我们设计一个系统,假设有两个任务
41、,它们都对全局变量sum1和sum2操作。低优先级任务让这两个变量始终相等,并不断在计数;高优先级任务不断的判断这两个变量是否相等,不相等则点亮LED,下面是两个任务的处理流程。系统管理系统管理|C/OS-II程序设计基础程序设计基础进入然后退出临界区进入然后退出临界区TaskLED任务代码如下。void TaskLED(void *pdata)while(1)OS_ENTER_CRITICAL();if(sum1!=sum2)IO0CLR=LED1;OS_EXIT_CRITICAL();OSTimeDly(2);判断两个全局变量是否相等延时2个节拍,任务切换进入临界段退出临界段两个全局变量不
42、等,点亮LED初始化代码系统管理系统管理|C/OS-II程序设计基础程序设计基础进入然后退出临界区进入然后退出临界区TaskAdd任务代码如下。void TaskAdd(void *pdata)while(1)OS_ENTER_CRITICAL();sum1+;sum2+;OS_EXIT_CRITICAL();OSTimeDly(1);全局变量sum1自加延时1个节拍,任务切换进入临界段退出临界段全局变量sum2自加初始化代码系统管理系统管理|C/OS-II程序设计基础程序设计基础进入然后退出临界区进入然后退出临界区3.调用OSSchedLock()以后,用户的应用程序不得使用任何能将现行任务
43、挂起的系统调用,直到配对的OSSchedUnlock()调用为止。1.OSSchedlock()和OSSchedUnlock()必须成对使用,也可以嵌套使用;2.OSSchedlock()只是禁止了任务的调度,而没有禁止中断,此时如果允许中断,中断到来时还是会执行对应的中断服务程序;系统管理系统管理|C/OS-II程序设计基础程序设计基础禁止然后允许调度禁止然后允许调度注意:对于用户来说,极少使用禁止然后允许调度的方法。不过,很多操作系统内部和驱动程序使用它来减少中断响应时间。给调度器上锁OSSchedlock()函数用于禁止任务调度,直到任务完成后调用给调度器开锁OSSchedUnlock(
44、)函数为止。使用它有3点需要注意。C/OS-II程序设计基础程序设计基础事件的一般使用规则事件的一般使用规则 相似性配对使用先创建后使用123在ISR中使用4事件的一般使用规则事件的一般使用规则|C/OS-II程序设计基础程序设计基础相似性相似性 事件管理函数是C/OS-II中最多的系统函数,在C/OS-II V2.52中总共有34个,而且每种事件具有的管理函数数目不同。但是所有的事件都有类似的6个函数,它们是所有事件的基本功能,其函数名类似,使用方法也类似,详细函数见下表。功能功能信号量信号量互斥信号量互斥信号量事件标志组事件标志组消息邮箱消息邮箱消息队列消息队列建立事件建立事件OSSemC
45、reateOSMutexCreateOSFlagCreateOSMboxCreateOSQCreate删除事件删除事件OSSemDelOSMutexDelOSFlagDelOSMboxDelOSQDel等待事件等待事件OSSemPendOSMutexPendOSFlagPendOSMboxPendOSQPend发送事件发送事件OSSemPostOSMutexPostOSFlagPostOSMboxPostOSQPost无等待获得事件无等待获得事件OSSemAcceptOSMutexAcceptOSFlagAcceptOSMboxAcceptOSQAccept查询事件状态查询事件状态OSSemQ
46、ueryOSMutexQueryOSFlagQueryOSMboxQueryOSQQuery另外还有4个事件管理函数为OSMboxPostOpt()、OSQPostFront()、OSQPostOpt()、OSQFlush(),各函数详见后面章节。事件的一般使用规则事件的一般使用规则|C/OS-II程序设计基础程序设计基础先创建后使用先创建后使用 任何一个事件,必须先创建后使用。创建事件是通过调用函数OS?Create()实现的,其中?为事件的类型。创建事件可以在main()函数中,但更多的是在任务初始化部分。使用方法如下。OS_EVENT*event;void Task0(void*pdat
47、a)pdata=pdata;event=OS?Create();while(1)/*其它代码*/定义事件防止编译器报警创建事件事件的一般使用规则事件的一般使用规则|C/OS-II程序设计基础程序设计基础先创建后使用先创建后使用 一般来说,在嵌入式系统中,事件是静态使用的,即创建后永远不删除。但有时候需要动态使用,即根据需要创建和删除事件,此时创建事件就是在任务的事件执行代码中,使用方法如下。OS_EVENT*event;void Task0(void*pdata)pdata=pdata;while(1)event=OS?Create();/*其它代码*/OS?Del(event,);定义事件防
48、止编译器报警创建事件删除事件删除事件后不要再使用它配对使用事件的一般使用规则事件的一般使用规则|C/OS-II程序设计基础程序设计基础 由前面介绍可知,事件是动态使用时,建立事件和删除事件必须配对使用。下面给出一个示例,假设Task0为高优先级任务,Task1为低优先级任务。Task0代码如下。配对使用配对使用OS_EVENT*event;void Task0(void*pdata)pdata=pdata;event=OS?Create();while(1)OS?Pend(event,);/*其它代码*/定义事件防止编译器报警创建事件等待获得事件1.无等待获得事件OS?Accept()是等待事
49、件的一种特殊形式,有事件时它与等待事件没有差别,没有事件时,它不等待,直接返回错误信息。2.因 为 已 经 具 有 无 等 待 获 得 事 件 的 功 能,所 以 很 少 使 用 查 询 功 能OSSemQuery()。事件的一般使用规则事件的一般使用规则|C/OS-II程序设计基础程序设计基础 Task1代码如下。配对使用配对使用void Task1(void*pdata)pdata=pdata;while(1)/*其它代码*/OS?Post(event,);/*其它代码*/防止编译器报警发送事件注意:一些事件有多个发送事件的函数,消息邮箱除OSMboxPost()外,还有增强型发送函数OS
50、MboxPostOpt(),消息队列有OSQPost()、OSQPostFront()、OSQPostOpt()三种发送函数,各函数详见后面章节。事件的一般使用规则事件的一般使用规则|C/OS-II程序设计基础程序设计基础在在ISR中使用中使用中断服务程序不能等待中断服务程序总体是顺序结构中断与所有的任务异步中断服务程序需要尽快退出 要掌握事件函数在中断服务程序中的调用规则,我们必须清楚中断服务有哪些特点。事件的一般使用规则事件的一般使用规则|C/OS-II程序设计基础程序设计基础在在ISR中使用中使用 下面给出事件在中断服务程序中使用方法,假设Task0任务接收ISR发送的消息,任务代码如下