精华--UCOS学习总结
- 格式:doc
- 大小:88.00 KB
- 文档页数:20
第一天:对UCOS基本概念和常用知识的理解1.所有UC/OS-II 的要素(函数、变量、常数定义、宏)都已OS开头2.临界区:指处理时不可分割的代码。
一旦开始执行,则不允许任何中断打入。
3.资源:任何为任务所占用的实体(如:打印机、键盘、变量、结构体等)4.共享资源:可以被一个以上的任务所使用的资源。
(必须存在互斥即每个任务使用时独占资源。
)5.任务:也叫线程,是一个简单的程序。
典型的每个任务都是一个无限的循环。
处于5种状态之下:休眠、就绪、运行、挂起、中断。
见图1.1休眠态:驻留在内存中,但不被多任务内核调度。
就绪态:该任务可以运行,但是priority比较低,暂不能运行运行态:掌握了CPU的控制权挂起态:该任务在等待,等待某一事件的发射。
中断态:进入被中断的状态。
6.任务切换:(上下文切换/CPU寄存器内容切换)将当前状态即CPU寄存器全部入栈,将新任务状态出栈,并进行下一个任务。
7.内核(kennel)负责管理各个任务。
其提供的基本服务就是任务切换!8.调度(scheduler)内核的职责之一,就是决定轮到那个任务运行了。
UCOS采用的是占先式内核。
采用的是优先级调度法:让处在就绪态的优先级最高的任务运行。
8.1占先式内核:响应时间得到了最优化,应用程序不应直接使用不可重入型函数。
调用不可重入型函数时,要满足互斥条件。
8.2占先式内核总是让就绪态的高优先级的任务运行,中断服务程序可以抢占CPU,到ISR完成后,内核让优先级最高的任务运行,并不一定是被中断了的任务了。
8.3可重入性(reentrancy)可重入型函数可以被一个以上的任务调用,不用担心数据破坏,可被中断,因为其使用的是局部变量,或者在使用全局变量时,进行了保护。
不可重入型函数会使数据等破坏,使用以下三点可以使其成为可重入型:1.把全局变量定义成局部变量2.调用函数时关中断,然后开中断3.用信号量禁止该函数在使用时被调入。
9.时间片轮番调度法UC/OS没有用,它要求当优先级相同时的一种方法,UC/OS要求priority都不相同。
UCOS的主要内容一:内核管理1:ucos的文件结构2:临界段,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。
它们可以用不同的方法去实现,用定义(#define)常数OS_CRITICAL_METHOD(1,2,3)来选择用哪种方法来实现。
当OS_CRITICAL_METHOD=1时,表示用处理器指令关中断,完成OS_ENTER_CRITIACL,用开中断完成OS_EXIT_CRITICAL.利用这种方法有点小问题,即是调用UCOS功能函数之前,中断是关掉的,从UCOS返回后,中断就打开了。
当OS_CRITICAL_METHOD=2时,这种方法是在堆栈中保存中断的开关状态,然后再关中断。
在实现OS_EXIT_CRITICAL时,只需简单的从堆栈中弹出原来中断的开关状态。
利用这种方法,不论用户在调用函数之前中断是开着的还是关着的,函数的进入和返回状态都得到了保护。
当OS_CRITICAL_METHOD=3时,一些编译器提供了扩展功能,用户可以得到当前处理器的状态字,并保存在C函数的局部变量中,这个变量可以用于恢复PSW。
3:任务的状态睡眠态:通过调用下述两个函数(OSTaskCreat()或OSTaskCreatExt())之一来实现的。
就绪态:任务一旦建立这个任务就进入了就绪态,准备运行。
可以通过调用OSTaskDel()返回到睡眠态。
运行态:调用OSStart()可以启动多任务。
等待状态:正在运行的任务可以通过调用以下两个函数(OSTimeDly()或OSTimeDlyHMSM())之一,将自身延迟一段时间。
正在运行的任务可能需要等待某一事件的发生,可以调用函数(OSFlagPend(),OSSempend(),OSMutexPend(),OSMboxPend(),OSQPend())之一来实现。
中断服务态:正在运行的任务可以被中断。
4:任务控制块(OS_TCB)???作用:当任务的CPU使用权被剥夺时,UCOS利用它来保存任务的状态。
μC/OS读书笔记1.可重入函数:可以被一个以上的任务调用,而不必担心数据被破坏。
可重入函数任何时候都可以被中断,一段时间以后又可以运行,而相应的数据不会丢失。
可重入函数或者只使用局部变量,即变量保存在CPU寄存器中或堆栈中;或者使用全局变量,则要对全局变量予以保护。
2. 时间片轮番调度法:当2个或2个以上任务有同样的优先级时,内核允许1个任务运行事先确定的一段时间,这段时间叫做时间额度(quantum),然后切换给另一个任务。
这个过程叫做时间片轮番调度。
内核在满足一下条件时,把CPU的使用权交给下一个就绪态的任务:(1)当前任务已空闲;(2)当前任务在时间片还没结束时已经完成了;(3)时间片结束。
μC/OS-Ⅱ目前还不支持时间片轮番调度法,应用程序中各任务的优先级必须互不相同。
3. 任务优先级:就大多数内核而言,每个任务的优先级是由用户决定的。
(1)静态优先级:应用程序执行过程中诸任务优先级不变。
诸任务以及它们的时间约束在程序编译时是已知的。
(2)动态优先级:应用程序执行过程中,任务的优先级是可变的。
优先级翻转:应避免出现优先级翻转。
为防止发生优先级翻转,内核能自动变换任务的优先级,称为优先级继承(priority inheritance).μC/OS-Ⅱ不支持优先级继承。
4. 共享数据区简化了任务间的信息交换,但是必须保证每个任务在处理共享数据时的排他性,以避免竞争和数据的破坏。
满足互斥条件的方法:(1)关中断μC/OS-Ⅱ使用开/关中断的方法:OS_ENTER_CRITICAL();关中断OS_EXIT_CRITICAL();开中断使用某种实时内核,一般来说,关中断的时间最长不超过内核本身的关中断时间。
(2)使用测试并置位指令如果不使用实时内核,当2个任务共享一个资源时,须约定好,先测试一全局变量,如果该变量为0,允许该任务与共享资源打交道;为防止另一任务也要使用该资源,第一个得到资源的任务只需要简单的将全局变量置为1。
以前在学校的时候硬着头皮读过uCOSII的源代码,可能是当时没做详细笔记,貌似读懂了,用的时候思路还是比较混乱,后面在电信学院,王老师有次要我写个uCOSII的总结,当时知道迟早会离开那里,只是一心想抓紧机会多接触点新东西,以后出去就没这么好机会了,没那个耐心静下来看代码,最近有点时间,重新梳理了一边源代码。
刚接触操作系统的时候觉得这个最神秘,到底里面做了什么,怎么就成了个操作系统,它到底有什么用,为什么要引进来着个东东。
学了之后才知道,原来最根本的思想还是源于汇编里面的跳转和压栈,以调用一个函数为例,编译后的汇编肯定是先通过SP压入当前代码段地址然后就是保存一些寄存器的值放栈里面(51单片机好像不是这样),然后执行程序,完了之后,出栈把寄存器恢复,最后把原来存的代码段地址付给PC然后回到原来的程序,这是汇编执行函数的做法,而操作系统人为强行的模拟这样操作,把代码写成不同代码块假定为A、B,要相互之间执行似乎不受影响,是这么实现的,假设首先代码在A中执行,代码段一直往下指,如果我要执行B,首先把A的代码段压入栈,所有的寄存器值存入A的栈,然后让SP强行指到B的栈执行出栈操作,把寄存器恢复成B的,B的代码段地址放入PC,这样就B在执行,如果又要A接着上次执行,又强行把B的寄存器、当前代码段地址压入B的栈,然后SP强行指到A的栈恢复的时候恢复成A最近一次保存的东西(和函数调用不同每次切换栈里面的东西是随机的),这样,可以很自由的在A、B中切换,如果切换足够快,A、B看以来好像同时在执行,这就是并行,A、B就是任务。
如果这个切操作放到定时器函数中来做,就可以严格按照时间来切换,这就是操作系统雏形。
另外,各个任务之间有存在一定的关系,有逻辑上的先后等,必须引进全局的结构体、变量来标记一些信息,全局的这些数据是不会被释放的,所以所有的任务可以去通过读、写这些数据来实现各个程序块交流信息,实现所谓的同步、互斥。
1、其中最有用的功能应该是时间片轮转法(roundrobin), 这个是uC/OS-II 中不支持的,但是现在已经是uC/OS-III 的一个功能了2、uC/OS-III 被设计用于32 位处理器,但是它也能在16 位或8 位处理器中很好地工作。
3、一共有2 种类型的实时系统:软实时系统和硬实时系统。
硬实时系统中,运算超时是不允许发生的,运算超时会导致严重后果。
但是在软实时系统中,超时不会导致严重后果4、前后台系统:包含一个无限循环的模块实现需要的操作(后台)。
中断处理程序实现异步事件(前台)。
前台也叫做中断级,后台也叫作任务级。
5、临界操作应该在任务级中被执行,不可避免地必须在中断处理程序中执行也要确保是在很短的时间内完成。
因为这会导致ISR 占用更长的时间。
通常的,ISR 中使能相关的信息而在后台程序中执行相应的操作。
6、ucos-iii中的任务(也叫做线程)是一段简单的程序,运行时完全地占用CPU 。
在单CPU 中,任何时候只有1 个任务被执行。
7、内核的责任是管理任务,协调和切换多个任务依次享用CPU 。
让我们感觉是多个CPU 在同时运行,也有利于处理模块化的应用它也负责管理任务间的交流,系统资源的管理(内存和I/O )等。
8、uC/OS-III 是一个抢占式内核,这意味着uC/OS-III 总是执行最重要的就绪任务9、ISR 响应中断请求设备,但是ISR 只做非常少的工作。
ISR 应该标记或发送消息到一个高优先级的任务,让中断能够快速处理完毕10、系统中加入内核需要额外的支出,因为内核提供服务时需要时间去处理。
内核占用CPU 的时间介于2% 到4% 之间。
因为uC/OS-III是一个软件,添加到目标系统中需要额外的ROM 和RAM 。
11、。
uC/OS-III 内核需要1K 到4K 之间的RAM ,加上每个任务自己所需的堆栈空间。
至少有4K 大小RAM 的处理器才有可能成功移植uC/OS-III 。
1.ucos体系结构以及任务的创建与运行 (1)2.cpu利用率的计算 (6)3.Ucos中常见类型的宏定 (8)4.任务优先级 (8)5邮箱,信号量 (11)有些是在网上抄的,有些是自己写的。
只希望把好的东西分享给大家。
1.ucos体系结构以及任务的创建与运行UCOS体系结构图:ucos最主要的功能是多任务,看其如何实现:uC/OS ii是通过中断(软)来实现任务现场的切换,做到任务的切换。
程序在创建任务之前首先通过调用OSInit(); ;初始化系统相关变量与数据结构。
通过函数OSTaskCreate()创建任务。
它的定义如下:OSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INTU prio),该函数包括 4 个参数: task:是指向任务代码的指针; pdata:是任务开始执行时,传递给任务的参数的指针; ptos:是分配给任务的堆栈的栈顶指针; prio 是分配给任务的优先级。
OSTaskCreate()函数中的关键代码如下:psp = OSTaskStkInit(task, p_arg, ptos, 0u);err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);if (err == OS_ERR_NONE) {if (OSRunning == OS_TRUE) { /* Find highest priority task ifmultitasking has started */OS_Sched();}OSTaskCreate()函数通过调用OSTaskStkInit()初始化任务的栈结构,任务的堆栈看起来就像刚发生了中断一样(所以的寄存器按一定的次序都保存在堆栈中,为什么要这样做?因为任务间的切换就是任务堆栈中保存的CPU现场的切换,所以任务被创建时,要初始化它的堆栈,为后面的切换做准备),堆栈初始化之后,如果系统已经在运行了,则有可能执行任务切换。
一.为什么需要操作系统1.操作系统可以显著降低开发难度。
操作系统帮我们协调多个程序之间的耦合关系,比如我们需要将串口的接收到的数据显示在一块LCD上。
传统做法是如图1所示:图1.无操作系统流程该流程中当串口接收到数据再调用LCD显示程序将数据显示出来,而图2展示了一种基于操作系统的方法。
在该方法中串口接收数据和LCD显示程序均以为自己独占CPU,各自都只是执行自己相关部分的工作,而什么时候显示到LCD屏幕,什么时候又继续接收串口数据这个协调工作将由操作系统完成。
图2 操作系统流程从以上比较可以看出操作系统协调了不同功能程序以让他们共同完成同一个工作。
同时操作系统又隔离了各个功能程序让它们的耦合程度降低。
这样就方便设计人员编写各个功能模块,同时整个系统的结构也更加清晰。
特别是系统逻辑结构复杂,功能模块较多的情况下操作系统的这一优点体现的更加明显。
2.操纵系统让每一个任务都认为自己独占CPU,方便代码编写。
同样采用上边的例子,无操作系统情况下我么需要在适当的时候分别调用串口接收数据程序和LCD显示程序,而有操作系统时我们只需要完成两个功能模块代码然后加入到操作系统就可以了。
两个功能代码都是以无限循环的方式执行,结构显得就很简单。
3.操作系统增加代码的移植性。
这一点我认为在ucOS系统上体现得并不明显,对于其他系统例如android,linux等系统可以这样讲,因为他们基本上应该算是一个中等复杂系统,而ucOS是一个简单嵌入式系统。
对于一个中等复杂系统它的底层硬件设备是有一定要求的,例如android 设备,根据系统特性它就需要有GPS支持,显示屏支持,电子罗盘支持,摄像头支持这些支持都被列入android设备的系统内,它们以驱动的形式存在。
而上层的应用程序通过调用底层的支持进而实现复杂的功能。
而ucOS我认为它仅仅只是一个调度器,他的工作就是协调多个应用程序在单个MCU上"同时"运行而已,它几乎是没有驱动这个概念的。
ucos学习基于UCOS的ARM嵌入式系统学习学习嵌入式有一段时间了,从刚开始,只知道有这么个东西,具体是什么,一概不知。
到后来,参加的一个ARM嵌入式培训班,算是对嵌入式系统有所了解,并且通过了ARM 嵌入式工程师资格认证,但那些东西都只是停留在概念的基础上,根本不会用它来做点什么,哪怕是点亮一个流水灯程序也不会(我说的是这其中的代码完全有自己写),后来便开始做实验,用的是SmartSOPC实验箱。
刚开始做的时候,只是看应用程序。
因为应用程序都是基于UCOS系统上运行的,比如,创建任务,邮箱,等等。
这些函数以前在C函数里根本没学过,于是便花了一段时间学习UCOS,不过没有去分析它的代码,对UCOS的了解只是停留在概念上,知道怎么用就行。
可是后来发现,对于ARM的体系结构,一知半解,比如说:当发生中断时,系统改如何处理;ARM7的7中模式,又该如何利用,更无从说起,后来便开始写启动代码,移植UCOS,才慢慢的揭开ARM体系结构那神秘的面纱。
一:ARM的启动代码在学启动代码前,首先必须对ARM内核的体系结构有所了解。
刚开始对引导块,存储器映射,和存储器重映射,很难理解,所以在写启动代码前,对这些概念的理解很有必要。
1:系统在上电或复位后,最开始并不是运行的并不是用户程序,而是引导模块(boot block),它是芯片厂家在LPC2000系列固化的一段代码,用户无法修改或删除。
(尽管有的芯片没有片内Flash,但它依然存在boot block)这段代码在芯片复位后首先被运行,其主要功能是:1.1:判断运行在哪个存储器上的程序:LPC2200系列可同时存在片内存储器和片外存储器,boot block通过芯片上的boot0和boot1引脚来判断程序的运行。
Boot0和boot1决定程序是从片外引导还是从片内引导,以及控制片外存储器的位数。
而MAP[1:0]决定异常向ARM芯片复位后,系统进入管理模式,ARM状态,PC寄存器值为0x00000000,所以必须保证用户的向量表代码定位在0x00000000处,或者映射到0x00000000处(例如向量表代码在0x80000000处,通过存储器映射,访问0x00000000就是访问0x80000000)。
姓名:李峰学号:2011123125μC/OS-II,初学者的总结和心得μC/OS-II 是一个源代码公开、可移植、可裁剪的实时多任务操作系统,具有稳定可靠、实时性好等优点。
和学习其他操作系统一样,我习惯从操作系统内核开始学习,然后扩展到其他细节和方面。
这次初学μC/OS-II操作系统,我大体了解了构建一个操作系统的思路和运行流程,本文也主要围绕系统运行过程和通信谈谈自己的理解。
一个系统的运行过程包括初始化、任务创建以及任务调度这几个主要的方面,而系统内通信则涉及到了信号量管理、消息邮箱以及消息队列等。
其中我最感兴趣的是μC/OS-II查找最高优先级算法的实现,这一数据结构以及用空间换时间的基本思想是该操作系统中一个重要的环节;其次,μC/OS-II 中的通信媒介也是我比较关注的部分,我将总结一下几种通信方式的特点以及异同。
相比而言,μC/OS-II是一个较为简单的操作系统,远没有Linux复杂,学习起来也比较好掌握,但这些基本思想在很多操作系统中是可以借鉴甚至相通的,可以作为学习其他操作系统的一个基础。
书中的介绍方式是把一个实时系统分为很多个模块,然后逐一介绍。
我觉得这种方式缺少整体把握,让初学者难以了解一个系统的大概运行情况。
所以我先从操作系统运行过程切入,这与程序运行从Main开始有类似之处,比较好理解。
μC/OS-II的运行过程可分为系统初始化、任务创建和任务调度三个方面。
其中主函数Main不到十行,由OSInit(),OSTaskCreate(),OSStart()分别完成初始化,创建任务和调度的工作。
其高度的结构化以及良好的函数封装对了解运行过程和学习μC/OS-II的编程思想以及设计思路有重大的意义。
在μC/OS-II中,系统初始化可以分为全局变量初始化、创建空闲任务任务、堆栈初始化、任务控制块初始化等部分内容。
由于μC/OS-II 操作系统中定义了众多与系统参数有关的全局变量,因此全局变量的初始化包含众多内容。
μC/OS简介及快速入门μC/OS概述uC/OS是由美国人Jean Labrosse 1992 年编写的一种体积小巧而实用的实时操作系统。
uC/OS-II是一种基于优先级的占先式实时多任务内核,专门为嵌入式设备设计的内核。
目前已经被移植到40多种不同结构的CPU上,可以运行在8位到64位的各种系统之上。
鉴于uC/OS-II可以免费获得代码,对于嵌入式RTOS而言,选择uC/OS无疑是最经济的选择。
从2.51版本之后,通过了美国FAA认证,可以运行在诸如航天器等对安全要求极为苛刻的系统之上。
μC/OS特点1可移植性强:绝大部分的µCOS -I I 的源代码是用移植性很强的ANSI C写的,和微处理器硬件相关的那部分使用汇编语言写,并且已经压到最低限度。
可在绝大多数8 位、16位、32位、64位微处理器、微控制器、数字信号处理器(DSP)上运行。
2可裁剪用户可以在应用程序中通过语句#define constants来定义所需的µ COS-II功能模块,以减少不必要的存储器空间的开支。
3占先式属于完全占先式的实时内核,意味着µCOS-II总是运行就绪条件下优先级最高的任务。
4多任务可剥夺实时内核,可以管理64个任务,支持56个用户任务。
赋予每个任务的优先级必须是不相同的,不支持时间片轮转调度法。
优先级越高,数字越小。
系统占用了两个任务,空闲任务和统计任务。
5中断管理中断可以使正在执行的任务暂时挂起。
如果优先级更高的任务被唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套可达255 层。
6其它特点公开源代码、可固化、可确定性、任务栈、提供很多系统服务、稳定性和可靠性强。
μC/OS不足之处1、固定的基于优先级的调度,不支持时间片,使用起来不方便。
一个任务的基础上可增加一个基于时间片的微型调度核。
2、在对临界资源的访问上使用关闭中断实现,没有使用CPU 提供的硬件指令。
UCOS主要内容一:内核管理1:ucos文件结构2:临界段,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。
它们可以用不同的方法去实现,用定义(#define)常数OS_CRITICAL_METHOD(1,2,3)来选择用哪种方法来实现。
当OS_CRITICAL_METHOD=1时,表示用处理器指令关中断,完成OS_ENTER_CRITIACL,用开中断完成OS_EXIT_CRITICAL.利用这种方法有点小问题,即是调用UCOS功能函数之前,中断是关掉的,从UCOS返回后,中断就打开了。
当OS_CRITICAL_METHOD=2时,这种方法是在堆栈中保存中断的开关状态,然后再关中断。
在实现OS_EXIT_CRITICAL时,只需简单的从堆栈中弹出原来中断的开关状态。
利用这种方法,不论用户在调用函数之前中断是开着的还是关着的,函数的进入和返回状态都得到了保护。
当OS_CRITICAL_METHOD=3时,一些编译器提供了扩展功能,用户可以得到当前处理器的状态字,并保存在C函数的局部变量中,这个变量可以用于恢复PSW。
3:任务的状态睡眠态:通过调用下述两个函数(OSTaskCreat()或OSTaskCreatExt())之一来实现的。
就绪态:任务一旦建立这个任务就进入了就绪态,准备运行。
可以通过调用OSTaskDel()返回到睡眠态。
运行态:调用OSStart()可以启动多任务。
等待状态:正在运行的任务可以通过调用以下两个函数(OSTimeDly()或OSTimeDlyHMSM())之一,将自身延迟一段时间。
正在运行的任务可能需要等待某一事件的发生,可以调用函数(OSFlagPend(),OSSempend(),OSMutexPend(),OSMboxPend(),OSQPend())之一来实现。
中断服务态:正在运行的任务可以被中断。
4:任务控制块(OS_TCB)???作用:当任务的CPU使用权被剥夺时,UCOS利用它来保存任务的状态。
5:就绪表每个就绪的任务都放在就绪表中,就绪表中有两个变量,OSRdyGRP 和OSRdyTbl【】。
OSRdyGrp中每一位表示8组任务中每一组是否有进入就绪态的任务。
当有任务进入就绪态时,就绪表OSRdyTbl[]中相应元素的相应位也置为1。
6:任务调度OS_SCHED()Ucos总是进行进入就绪态任务中优先级最高的任务,确定哪个任务优先级最高,这一工作就是有调度器完成的。
7:任务切换OS_TASK_SW()需恢复该任务在CPU使用权被剥夺时保存下来的全部寄存器的值,之后,运行被切换的任务。
8:给调度器上锁和开锁给调度器上锁函数OSSchedlock()用于禁止任务调度,直到任务完成后,调用调度器开锁函数OSSchedUnlock()为止。
这两函数必须成对使用。
9:空闲任务OS_TaskIdle()这个任务没有其他任务进入就绪态时,投入运行,空闲任务永远处于就绪态。
空闲任务始终设为最低优先级。
OSTaskIdle()可以调用OSTaskIdleHook()让CPU进入STOP指令,从而进入低功耗模式。
当应用系统有电池供电时,这种方式特别有用。
10:统计任务OSTaskStat()有一个统计运行时间的任务,叫做OSTaskStat()。
告诉用户使用了多少CPU时间,用百分比表示。
如果应用程序打算使用统计任务,在调用系统启动函数OSStart()之前,用户初始化代码中必须先建立一个任务,在这个任务中调用统计任务初始化函数OSStatInit(),然后再建立应用程序中的其他任务。
11:ucos的中断a:中断请求,但还不能被CPU识别。
b:ucos或应用程序关中断。
c:转到相应的中断向量d:保存CPU寄存器e:通知内核:OsIntEnter()。
f:ISR给任务发信号。
g:通知内核退出中断服务:OSIntExit()h:恢复CPU寄存器i:中断返回j:通知内核退出中断OSIntExit(),k:恢复CPU寄存器,中断返回。
12:时钟节拍OSTimTick()注意点:必须在多任务系统启动后,也就是调用OSStart()之后,再开启时钟节拍器。
13:ucos的初始化14:ucos的启动二:任务管理1:建立任务OSTaskCreat()/OSTaskCreatExt()如果想让UCOS管理用户的任务,必须先建立任务。
可以通过将任务的地址和其他参数传递到以下两个函数之一来建立任务。
当调用OSTaskCreat()时,需要四个参数:OSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INTU prio)Task:是指向任务代码的指针,pdata:是任务开始执行是,传递给任务的参数的指针,ptos:是分配给任务的堆栈的栈顶指针,prio是分配给任务的优先级。
OSTaskCreateExt()函数来建立任务会更加灵活,但是会增加一些额外的开销。
2:任务堆栈OS_STK()每个任务都有自己的堆栈,堆栈必须申明为OS_STK类型,并且由连续的内存空间组成。
可以静态分配堆栈空间,也可以动态分配堆栈空间。
3:堆栈检验OSTaskStkChk()有时确定任务实际需要的堆栈空间的大小是很有必要的,因为这样就可以避免为任务分配过多的堆栈空间,从而减少应用程序代码所需的RAM空间。
4:删除任务OSTaskDel()有时需要删除任务,删除任务,是说任务返回并处于休眠态,并不是说任务的代码被删除了,只是任务的代码不再被UCOS调用。
5:请求删除任务OSTaskDelReq()有时,任务会占用一些内存缓冲或信号量一类的资源。
这时,假如另一个任务试图删除该任务,这些被占用的资源就会因为没有被释放而丢失。
在这种情况下,需想办法拥有这些资源的任务在使用完资源后先释放资源,再删除自己6:改变任务的优先级OSTaskChangePrio()在建立任务是,会分配给任务一个优先级。
在程序运行期间,可以通过调用该函数改变任务的优先级。
也就是说,UCOS允许动态的改变任务的优先级。
7:挂起任务OSTaskSuspend()任务挂起是一个附加功能,也就是说,如果任务在被挂起的同时也在等待延迟时间到,那么,需要对任务做取消挂起的操作,并且等待延迟时间到,任务才能转让就绪状态。
任务可以挂起自己或者其他任务。
8:恢复任务OSTaskResume()别挂起的任务只有通过该函数才能被恢复。
9:获得任务的信息OSTaskQuery()通过调用该函数,来获得自身或其他应用任务的信息三:时间管理1:任务延迟函数OSTimeDly()Ucos提供一个可以被任务调用而将任务延时一段特定时间的功能函数,即OSTimeDly().任务调用OSTimeDly()后,一旦规定的时间期满或者有其他的任务通过调用OSTimeDlyResume()取消了延时,他就会进入就绪状态。
只有当该任务在所有就绪态任务中具有最高的优先级,它才会立即运行。
2:按时,分,秒延时函数OSRimeDLyHMSM()与OSTimeDly()一样,调用OSRimeDlyHMSM()函数也会是UCOS进行一次任务调度,并且执行下一个优先级最高的就绪任务。
当OSTimeDlyHMSM()后,一旦规定的时间期满,或者有OSTimeDlyResume(),它就会马上处于就绪态。
同样,只有当该任务在所有就绪态任务中具有最高的优先级,他才开始运行。
3:恢复延时的任务OSTimeDlyResume()延时的任务可以不等待延时的期满,而是通过其他任务取消延时而使自己处于就绪态,可以通过该函数来实现,实际上,OSTimeDlyResume()也可以唤醒正在等待的事件。
4:系统时间OSTimeGet()和OSTimeSet()四:事件控制块(ECB)任何任务或中断服务子程序可以通过事件控制块ECB向另外的任务发信号,这里信号看成是事件。
事件控制块ECB的数据结构Typedef struct{INT8U OSEventType; ;定义了事件的具体类型INT8U OSEventGrp; ;INT16U OSEventCnt; ;当事件控制块用于信号量时,该变量用于信号量的计数器。
V oid *OSEventPtr; ;只有所定义的事件是消息邮箱或者消息队列时才使用。
INT8U OSEventTbl[OS_EVENT_TBL_SIZE];}OS_EVENT;1:初始化一个事件控制块,OS_EventWaitLListInit()当建立一个信号量,邮箱或者消息队列时,通过调用该函数,对事件控制块中的等待任务列表进行初始化。
2:使一个任务进入就绪态,OS_EventTaskRdy()该函数从等待任务队列中使最高优先级任务脱离等待状态,并把该任务置于就绪态。
3:使一个任务进入等待某事件发生状态OS_EventTaskWait()当某个任务需等待一个事件的发生时,信号量,互斥型信号量,邮箱及消息队列会通过相应的PEND函数调用该函数,使当前任务从就绪任务表中脱离就绪态,并放到相应事件的事件控制块的等待任务表中。
4:由于等待超时而降任务置为就绪态OS_EventTo()如果在预先指定的等待时限内任务等待的事件没有发生,那么该函数就会因为等待超时而将任务的状态量置为就绪态。
在这种情况下,信号量,互斥型信号量及消息队列会通过PEND调用该函数,以完成这项工作。
五:信号量管理信号量有两部分组成:一部分是16位无符号整型信号量的计数值,另一部分是有等待该信号量的任务组成的等待任务表。
1:建立一个信号量,OSSemCreate()使用一个信号量之前,首先须建立该信号量,可以调用该函数来建立信号量,并对信号量赋予初始计数值。
该初始值为0~65535.如果该信号量是用来表示一个或者多个事件发生,那么该信号量的初始值通常赋为0;如果该信号量用于对共享资源的访问,那么该信号量的初始值应赋为1;如果该信号量用来表示允许任务访问n个相同的资源,那么该信号量的初始值应赋为n,并把该信号量作为一个可记数的信号量使用。
2:删除一个信号量,OSSemDel()如果要删除一个信号量,在OS_CFG.H中,OS_SEM_DEL_EN须置为1,该函数才能被使用。
3:等待一个信号量OSSemPend()4:发出一个信号量OSSempend()5:无等待的请求一个信号量OSSemAccept()当一个任务请求一个信号量时,如果该信号量暂时无效,也可以让该任务简单的返回,而不是进入睡眠等待状态。
这种操作由该函数完成。
6:查询一个信号量的当前状态,OSSemQuerey()可以通过该函数,来插叙一个信号量的当前状态。