uCOS-II中的任务切换机制

合集下载

ucosII任务切换是怎样实现的

ucosII任务切换是怎样实现的

UC/OS-II学习笔记之——任务切换是怎样实现的问题是,o Uc/OS-II如何切换任务?通过任务调度器OS_Sched(),那么谁在调用这个函数?o CPU在这里肯定有作用,因为任务切换必然涉及到CPU寄存器的入栈和出栈,那么这一块工作是如何完成的?书上讲:为了做到任务切换,运行OS_TASK_SW(),人为模仿一次中断。

中断服务子程序或陷阱处理(trap hardler),也称作事故处理(exception handler),必须给汇编语言函数OSCtxSw()提供中断向量[1.92]。

那么,“人为模仿一次中断”是什么意思?是指:OS_TASK_SW()触发了一个中断,由中断完成了任务切换?阅读源代码,查找答案……#define OS_TASK_SW()OSCtxSw()//这是一个宏调用,定义在os_cpu.h,Os_cpu_a.asm中定义了OSCtxSwNVIC_INT_CTRL EQU0xE000ED04NVIC_PENDSVSET EQU0x10000000;******************************************************************************;PERFORM A CONTEXT SWITCH(From task level);void OSCtxSw(void);;Note(s):1)OSCtxSw()is called when OS wants to perform a task context switch.This function;triggers the PendSV exception which is where the real work is done.;******************************************************************************OSCtxSwLDR R0,=NVIC_INT_CTRL;Trigger the PendSV exception(causes context switch) LDR R1,=NVIC_PENDSVSETSTR R1,[R0]BX LR注释说明该段汇编代码触发了一个PendSV的异常。

关于ucos优先级机制

关于ucos优先级机制

关于ucos优先级机制一:任务原理任务,在UCOS-ii实时系统中,一个任务其实就是一个线程,该任务可以认为CPU完全属于它自己。

UCOS-ii中的任务拥有自己的堆栈和CPU寄存器,并且赋予一定的优先级,在UCOS-ii中,它可能处于睡眠、就绪、运行、等待、中断服务状态之一。

具体这5种状态的定义请看我的另一篇博文《UCOS Learning Notes N.O. 01》。

基于优先级的内核有两种:不可剥夺型和可剥夺型。

不可剥夺型内核它要求每个任务互相合作,也称为合作型内核,每个任务不会被其它任务剥夺去,除非中断的到来,即便如此,当中断结束后,还是会回到原来被中断的程序,而不会切换到具有高优先级的任务中去,这样,高优先级的任务就不能够及时得到执行,所以它的实时性是比较差的。

但是它有一个很重要的特点,就是它可以使用可重入函数,因为每个任务必须执行完,才能释放CPU,这样它对其它任务调用可重入函数没有影响;同理在大多数情况下它无须使用信号量来保护资源。

补记:我们有时候写前后台的程序时,通常利用了分时的观念,即我们在延迟中执行其他代码,这从本质上也可以说是借鉴不可剥夺的内核特点来写的,至少它们有相同之处吧,不过这要球程序对自己的程序运行过程非常清楚,其实这也是正确使用UCOS实现它最优实时性的前提,不过这境界有点难咯,我自己也没有做到,让我们努力吧!对于可剥夺型内核,只要高优先级任务一就绪,那它就会被执行,而当前正在执行的任务就会被挂起;正因为如此,对于系统的资源就不能像不可剥夺型那样去使用,而是在使用前必须检查是否可以使用,即互斥机制来保护临界资源,如果不用的话,那么如果低优先级在使用临界资源时,突然被高优先级把CPU给抢过去了,那么低优先级的临界资源就可能会被告优先级任务给破坏掉;可剥夺型的优点是是系统的响应时间得到了优化,且是可知的。

实时系统中,中断优先级反转这一问题是出现得最多的,这问题的本质其实也不能理解,就是低优先级的任务占有高优先级的任务所需要的资源,而使高优先级不得不等低优先级把资源释放才能执行。

实验二 多任务的调度与切换

实验二 多任务的调度与切换

实验二多任务的调度与切换1.实验目的(1)在移植好的UC/OS-II上学习用户任务的建立方法和任务切换的实现方式。

(2)为以后的掌握深层次模块的移植和任务切换奠定基础。

(3)进一步掌握UC/OS移植的细节,学习UC/OS-II设置合适的延时时间来实现任务切换的方法。

2.实验任务(1)观察示例程序中的代码,进一步体会实时操作系统与前后台程序的不同之处。

(2)看懂示例代码的程序,明白多任务的调度与切换的具体过程是如何实现的。

(3)通过示例程序,明白任务调度与切换时堆栈的变化情况。

3.预习要求(1)参考《嵌入式实时操作系统uCOS-II》(第2版),熟悉uCOS-II各模块的基本工作原理。

(2)参考《单片机与嵌入式系统开发方法》第9章内容以及《uCOS-II移植说明文档》。

熟悉uCOS-II多任务调度与切换的具体实现方法。

(3)通过预习,明白各任务堆栈中哪些是与任务调度和切换有关。

(4)思考如何用可见的方式来展现多任务的调度与切换。

4.实验步骤(1)打开示例程序,观察程序代码。

(2)参考注释,理解弹出堆栈内容的实现方法。

(3)修改.prm文件中的中断向量,将其中的ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFEFF;改为ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xEEFF;将结尾处原有的VECTOR 0 _Startup;改为VECTOR ADDRESS 0xEFFE _Startup;再添加上VECTOR ADDRESS 0xEFF6 OSCtxSw;VECTOR ADDRESS 0xEFF0 OSTickISR两个中断向量。

(4)通过超级终端将编译好的程序下载到目标板上,然后运行程序,观察实验现象。

并思考其工作机制。

(5)实验现象如下图所示:首先弹出的为初始化任务堆栈时所对应的CPU以及PPAGE的值,可比对任务初始化函数void *OSTaskStkInit(void(*task)(void *pd), void *pdata, void *ptos, INT16U opt)中对任务堆栈初试的值。

UC-OS II多任务机制

UC-OS II多任务机制

UC/OS II 多任务机制前面已经说过,uC/OS-II是一种基于优先级的可抢先的多任务内核。

那么,它的多任务机制到底如何实现的呢?了解这些原理,可以帮助我们写出更加健壮的代码来。

首先我们来看看为什么多任务机制可以实现?其实在单一CPU的情况下,是不存在真正的多任务机制的,存在的只有不同的任务轮流使用CPU,所以本质上还是单任务的。

但由于CPU执行速度非常快,加上任务切换十分频繁并且切换的很快,所以我们感觉好像有很多任务同时在运行一样。

这就是所谓的多任务机制。

由上面的描述,不难发现,要实现多任务机制,那么目标CPU必须具备一种在运行期更改PC的途径,否则无法做到切换。

不幸的使,直接设置PC指针,目前还没有哪个CPU支持这样的指令。

但是一般CPU都允许通过类似JMP,CALL这样的指令来间接的修改PC。

我们的多任务机制的实现也正是基于这个出发点。

事实上,我们使用CALL指令或者软中断指令来修改PC,主要是软中断。

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

执行完毕之后,一般都是执行一条RETI指令,这条指令会把当前堆栈里的值弹出恢复到状态寄存器和PC里。

这样,系统就会回到中断以前的地方继续执行了。

那么设想一下?如果再中断的时候,人为的更改了堆栈里的值,那会发生什么?或者通过更改当前堆栈指针的值,又会发生什么呢?如果更改是随意的,那么结果是无法预料的错误。

因为我们无法确定机器下一条会执行些什么指令,但是如果更。

关于uCOS-Ⅱ中任务切换的仪器仪表的实现实例

关于uCOS-Ⅱ中任务切换的仪器仪表的实现实例

关于uCOS-Ⅱ中任务切换的仪器仪表的实现实例假设某仪器要实现A/D采样、输入控制、显示等功能。

uC/OS-Ⅱ*作系统将对这三个任务进行管理,协调各自工作。

任务描述:统计任务:每做完例行统计后执行一次显示输出;初始任务:每隔10节拍进行一次A/D采样;用户任务:每秒判断一次是否有输入控制信号。

实验中为了测量与观察方便,采用对89C51的P1口每次取反的*作来模拟仪器执行的任务,由于关心的是*作系统的*能,而非任务本身,因此简化是可行的。

设置时钟节拍:50Hz三个任务(包含系统空闲任务):任务名优先级*作空闲任务63空*作统计任务62每秒做一次统计并对P1。

2取反初始任务4每秒对P1。

0取反一次用户任务5每10个节拍对P1。

1取反一次设计中须注意以下两点:(1)任务的现场保护:除PUSH到堆栈的CPU寄存器外,还应包括任务运行过程中保存到堆栈的信息,所以每次保存的信息量是变化的。

(2)任务堆栈的大小应根据实际情况充分估计,避免过大或者不足。

在这个例子中定义了TASKSTKSIZE(任务堆栈)为64个字节,故在内部RAM中预留出64个字节作为*作系统的系统堆栈,用全局变量定义如下:INT8Uidatasp[64]at0x30;该语句表示系统堆栈从30H开始。

(1)开始多任务调度每个任务堆栈初始化情况:堆栈指针SP=48-1+8+5+2+2+sizeof(void*),即系统堆栈放入以上信息后SP指针所指的位置。

下面开始多任务调度:系统堆栈指针SP初始值30H,将初始任务的任务堆栈内容(在xdata段)Load到系统堆栈内,完成后SP应指向系统堆栈栈顶,然后运用pop指令切换到初始任务。

(2)在任务运行中进行任务切换切换前系统堆栈为:将系统堆栈中从当前SP开始一直到30H的堆栈信息保存到当前任务堆栈中,然后把新任务的任务堆栈的内容Load到系统堆栈中来。

然后用POP指令将任务切换到新任务中去。

(3)在中断返回时切换任务须保存的信息在中断时应保存,切换任务时,只要将SP减去由于调用OSIntExit()和OSIntCtxSw()两个函数而使SP指针增加的4个字节,其他与任务级切换一样。

uCOS-II的任务切换机理及中断调度优化

uCOS-II的任务切换机理及中断调度优化

摘要:μC/OS-II是一种适用于嵌入式系统的抢占式实时多任务操作系统,开放源代码,便于学习和使用。

介绍μC/OS-II在任务级和中断级的任务切换原理,以及这一操作系统基于嵌入式系统的对于中断的处理;相对于内存资源较少的单片机,着重讨论一种优化的实用堆栈格式和切换形式,以提高资源的利用率;结合MSP430单片机,做具体的分析。

关键词:实时多任务操作系统μC/OS MSP430 中断堆栈引言在嵌入式操作系统领域,由Jean J. Labrosse开发的μC/OS,由于开放源代码和强大而稳定的功能,曾经一度在嵌入式系统领域引起强烈反响。

而其本人也早已成为了嵌入式系统会议(美国)的顾问委员会的成员。

不管是对于初学者,还是有经验的工程师,μC/OS开放源代码的方式使其不但知其然,还知其所以然。

通过对于系统内部结构的深入了解,能更加方便地进行开发和调试;并且在这种条件下,完全可以按照设计要求进行合理的裁减、扩充、配置和移植。

通常,购买RTOS往往需要一大笔资金,使得一般的学习者望而却步;而μC/OS对于学校研究完全免费,只有在应用于盈利项目时才需要支付少量的版权费,特别适合一般使用者的学习、研究和开发。

自1992 第1版问世以来,已有成千上万的开发者把它成功地应用于各种系统,安全性和稳定性已经得到认证,现已经通过美国FAA认证。

1 μC/OS-II的几大组成部分μC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。

核心部分(OSCore.c) 是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。

能够维持系统基本工作的部分都在这里。

任务处理部分(OSTask.c)任务处理部分中的内容都是与任务的操作密切相关的。

包括任务的建立、删除、挂起、恢复等等。

因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。

μCOS-Ⅱ操作系统的任务切换

μCOS-Ⅱ操作系统的任务切换

μC\OS-Ⅱ操作系统的任务切换作者:司新生来源:《数字技术与应用》2010年第06期摘要:μC\OS-Ⅱ操作系统是一个多任务占先式实时操作系统,每一个任务由三部分组成,任务控制块,任务的私有堆栈、任务代码。

每一个任务有一个决定其重要性的任务优先级,系统通过任务就绪表来进行任务的切换,就绪的任务在任务就绪表中设置其标志位,退出就绪的任务在就绪表中撤消其标志位。

任务的切换过程就是通过任务就绪表找到优先级最高的任务,保存原来运行任务的上下文到该任务的私有堆栈中,从最高优先级的任务私有堆栈中复制断点数据到工作寄存器中,pc指针指向该任务的代码段,实现了任务的切换。

关键词:操作系统任务控制块优先级任务切换1 μC\OS-Ⅱ的任务μC\OS-Ⅱ操作系统是一个多任务系统,它最多可以管理64个任务,但两个优先级最低的任务已被系统占用,一个是统计任务,一个是空闲任务。

空闲任务的作用为当操作系统没有其它任务执行时,就转入空闲任务而不使系统没事可做。

任务的结构每一个任务都有如下结构。

它由任务控制块TCB,任务代码,任务堆栈组成,多个任务控制块形成一个任务控制块链表。

每一个任务在创建时都被分配有一个任务优先级,优先级序号从0到63,优先级数值越大则表示优先级越低,最高的优先级是优先级序号为0的任务,最低的优先级是优先级为63的任务。

操作系统可以设定管理的任务数,在OS_CFG.H文件中,可以定义OS_LOWEST_PRIO值,该值最大为63。

每一个任务都有唯一的任务优先级,μC\OS-Ⅱ操作系统任务切换的关键就是该任务的优先级,操作系统总是运行处于就绪状态的最高优先级的任务。

创建任务主要完成四项任务,一是指出任务代码存放的地址,二是指明任务参数指针,也即任务参数地址,三是指明任务堆栈栈顶指针,在进行任务切换时保存或恢复与任务相关的寄存器的值,四是确定任务的优先级,优先级的高低决定了任务的紧迫性和重要性。

任务创建的代码如下。

ucoscpu使用率原理

ucoscpu使用率原理

ucoscpu使用率原理
uCosCPU(MicroC/OS-II中的任务调度算法)的使用率原理涉及到任务调度和时间片轮转的概念。

uCosCPU是一个实时操作系统内核,它使用优先级抢占式的多任务调度算法来管理任务。

任务的使用率原理可从以下几个方面来解释:
1. 任务调度,uCosCPU使用优先级抢占式的调度算法,即高优先级任务可以抢占正在执行的低优先级任务。

这意味着当一个高优先级任务就绪时,它会立即取代当前正在执行的低优先级任务,以确保高优先级任务能够及时得到执行。

这种调度算法可以保证系统对实时任务的响应性。

2. 时间片轮转,uCosCPU还支持时间片轮转的调度方式。

在时间片轮转中,每个任务被分配一个时间片,在时间片用完之后,系统会将CPU资源分配给下一个就绪的任务。

这种方式可以确保每个任务都有机会执行,避免某个任务长时间占用CPU资源而导致其他任务无法得到执行。

3. 任务优先级,uCosCPU中的任务可以设置不同的优先级,高优先级的任务会比低优先级的任务得到更多的CPU时间。

这样可以
确保系统能够优先处理重要的任务,提高系统的实时性和响应性。

4. 中断处理,uCosCPU还会处理各种硬件和软件中断,这些中断可能会导致任务切换或者延迟。

系统需要合理地处理中断,以确保不会影响到系统的实时性和稳定性。

总的来说,uCosCPU的使用率原理涉及到任务调度、时间片轮转、任务优先级和中断处理等多个方面,这些方面相互作用,共同保证了系统的实时性和稳定性。

通过合理配置任务的优先级和时间片大小,可以更好地利用CPU资源,提高系统的性能和响应速度。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

uCOS-II中的任务切换机制【@.1 函数周期与死循环】一般函数的生命周期很简单,从开始调用函数起,直到函数返回,即结束。

这样一来就完成了这个函数的使命,它也就不再需要了。

对于一般的函数就是这样,但是回过头想想,对于一个系统、OS、或者工业控制中的一个控制器重的系统个,函数返回是很轻易很随便的就能返回吗?返回就意味着函数结束,死亡,若是想系统这样一个很大的函数,它的返回就意味着系统结束。

因此,对于系统的函数返回有些时候我们不希望它返回,返回时是需要好好设计的,像嵌入式中的控制程序我们也并不需要它返回,直接关机就好了。

因此,一个系统往往就是一个很大的循环,不停的扫描,而我们编程的时候对于这个死循环是需要好好设计的。

考虑以下一个控制要求,@.按键控制电机启、停、正转反转,并每秒发送CAN报文报告当前情况。

我们可以有多种方法实现这一要求:方法一:每次在循环体重扫描当前按键的电平,从而进入对应的控制电机函数,如果所有电平都没有信号则直接进入下一个循环。

发送CAN报文就直接用一个定时中断。

这样的好处就是编程简单直白,每次循环进入不同的电机控制函数,坏处很明显,一定要等待到下一个循环才能进入其他的电机控制函数,每次循环的时间不好控制,不管你用函数指针还是if/else来判断,每次循环一定要等待电机动作结束才能进入下一个循环。

方法二:改用外部中断来处理按键。

仅当按键按下时触发外部中断,从而控制响应的电机进行操作。

这样的好处就是循环体简单,可以仅仅就是一个计数器加一,所有控制都等中断来实现。

但这样带来的问题也很明显,就是中断嵌套问题。

比如当电机正转时按下停止按钮,这时由于是在中断中,停止按钮是否真的能够得到响应?这就涉及到中断嵌套问题,并不见得所有CPU都能支持中断嵌套,我的这一篇文章对中断嵌套问题进行了一个讨论。

方法三:采用RTOS的思想,加入任务调度系统。

每次任务调度系统就是一个小小的循环,对于各个任务进行轮询,当这次轮询发现某任务是已经就绪的优先级最高的任务,则交给CPU处理,所有中断与任务,任务与任务之间有通讯机制可以交换信息。

当然实际上并不仅仅只在任务调度器轮询时才进行任务的切换,实际上的操作比这个复杂一些,我的这篇文章就想以uCOS-II为例讨论RTOS的任务调度系统是怎样执行的。

【@.2 uCOS-II中的任务调度】回到前面的方法一,二,我们将这种任务称作前后台任务。

后台就是指程序的大循环,程序一定要等到前台任务(可以说中断或某个功能函数)返回才能继续运行下去。

而在RTOS中每个任务都有自己的控制块指向改任务,由任务调度器来决定这个时候该运行哪个任务。

所有这些任务控制快(TCB)构成一个双向链表,每个TCB中都有一些控制字,比如一个指向堆栈的指针(*sp),一个表明当前任务状态的位(State),指明任务被挂起等待的超时时间(dly),任务的优先级(Prio),指向事件控制块的指针(*Event,事件机制后面会讨论)。

一个全局的任务就续表记录了当前任务是否就绪,任务调度器就靠查询任务就绪表寻找到就绪任务中优先级最高的一个任务。

每一个任务都是一个死循环,并且必须在循环内调用系统函数来释放CPU控制权,比如调用系统的延时函数OSTimeDly()延时一段时间,这个时候系统就会知道这个任务被延时了,延时时间记录在TCB中的超时时间dly中,任务调度器将其他任务予以运行。

实际的任务调度有两种机制1.中断级任务调度:任何中断返回时必须调用一个系统函数OSIntExit(void),进行一次任务调度。

比如一般任务调度器通常是一个定时中断,比如1000次每秒,成为OS时钟。

每次OS时钟要返回时都会调用OSInitExit()进行任务切换,运行当前就绪的优先级最高任务。

一般这个OS时钟的优先级很低,为整个系统优先级倒数第二低(倒数第一低的是Idle Task,空闲任务),因此实际上这个OS时钟最终并不会返回。

2.任务级任务调度:在任务运行中执行一次OS的特定函数,比如前面提到的OSTimeDly(),此函数在返回之前会执行一次任务调度。

因此总的任务调度次数会远远高于OS时钟的轮询频率的。

我们下面举例来说明这两种调度机制:【@.3 中断级任务调度】当OS时钟的定时中断来临时(比如1000次每秒),会进入OS时钟的服务函数,它会做大致一下工作,递增一个全局的计数器OSTIme,遍历所有OSTCB链表,将其中的dly超时时间递减,若等于0,则在就绪列表中置位。

最后这个中断要返回时会调用OSInitExit(),它会找到在任务就绪表中处于就绪状态的最高优先级的任务,并且调用OSInitCtxSw(),即上下文切换,将之前找到的任务放在任务堆栈中的寄存器推入到CPU的R0~R15,CPSR 中,最后结束。

这里的这个OSInitCtxSw(),上下文切换函数是实际上跟CPU打交道的函数,也是移植uCOS-II需要编写的函数。

任何中断返回时都必须调用这个OSInitExit(),不管是外部中断,定时器中断,串口中断。

当然,我们可以在实际编写中将这一中断过程编写一个统一模板,调用中断服务实际函数。

这是后话了。

【@.4 任务级任务调度】这种调度方式实际上丰富了任务之间的通讯机制以及任务的控制,也是最需要理解的一种方式。

主要的流程跟中断级方式类似,不过是需要在任务中调用一些特定的系统函数。

实际的任务切换函数是OSSched(),会调用实际的上下文切换函数OS_TASK_SW()。

这个函数往往跟中断级的上下文切换函数是一样的,我们移植时只需要编写一个函数即可。

下面以几个具体的函数为例进行讲解:1.OSTaskResume/ OSTaskSuspend首先是一个比较好理解的OSTaskSuspend()和OSTaskResume(),直接控制任务的挂起和恢复。

对于图中的TaskA,在任务运行到某处调用OSTaskSuspend()之后,会挂起就绪表中优先级为prio的任务x(优先级也就是这个函数的传入参数)。

之后调用OSSched,进行任务切换。

若挂起的是自己,即调用OSTaskSuspend时传入的优先级是自己的,则自身被挂起,函数不返回;若挂起的是别的任务,那么别的任务就直接被挂起,当前函数返回。

另一个任务TaskB中调用OSTaskResume(),将首先在置位表中置位优先级为prio的任务,之后交给OSSched()进行任务切换,之后就是一个优先级的判断问题,若恢复的任务比自己任务高,那么自己被挂起,高优先级任务运行;若被恢复的任务优先级低于自己,则函数自己函数返回,继续运行,直到TaskB运行到其他函数释放CPU控制权。

所以像TaskB这样的任务中还需要包含一个其他的函数,比如OSTimeDly来释放CPU。

最后,若恢复的任务是自己,很明显是没有意义的。

2.OSSemPost/OSSemPend在通讯机制上uCOS-II利用事件管理块(ECB)统一进行处理,其中信号量是最基本的一种方式,可以起到共享资源单独访问和任务间同步的功能。

我们建立一个信号量,类型为OS_EVENT的指针,其内部包含了一个事件等待表,记录着等待该事件(也就是Sem自身)的所有任务,当某一任务等待此信号量时,在它的事件等待表上相应优先级置一。

若任务TaskA调用了OSSemPend()等待一个信号量,此函数会调用OS_EventTaskWait,一个内部的事件等待函数。

图中表明了此函数的流程,首先会建立任务A的TCB与此信号量Sem之间的链接,即TCB中的Event指针指向Sem。

之后清楚任务就绪表中的相应位,再将Sem中的事件等待表置一,OS_EventTaskWait之后会调用OSSched进行实际的上下问切换,此时由于之前的一些列操作将导致这个时候任务会被挂起,只能等待其他任务(或等待超时)将其重新恢复成就绪状态。

调用OSSemPost时的流程如下OSSemPost会调用OS_EventTaskRdy,图中可以看出这个函数的流程,首先从Sem的等待事件列表中寻找到等待该事件的优先级最高的任务。

可能同时有多个任务在等待此信号量,假如其中优先级最高的寻找结果就是前面的TaskA,则接下来将切断此任务的TCB与ECB 的联系,并且在任务就续表中置位此任务。

OS_EventTaskRdy返回之后将进入OSSched,将根据前面的一些列操作进行任务调度,当然,若发送信号量后接收方(TaskA)的优先级大于发送方(TaskB),则TaskB自身被挂起,运行TaskA;反之,TaskB继续运行。

这种信号量的发送/接收机制适用于任务同步,共享资源的独占,比如:上图中所示,当TaskA调用Pend接收到信号量Sem时执行foo函数,此时TaskB在Pend 处,不管怎么调度也不会执行foo函数,直到TaskA运行到Post处时才有可能执行下去。

这样就防止了同一时间有两个任务同时处理共享资源(这里是函数foo())。

另一种情况如上图示,Post一方由一个任务或一个中断服务函数调用,接受的一方由另一个任务调用Pend。

只有当发送方Post这个信号量之后,接收方Pend处才有可能继续往下运行。

注意:这点跟OSTaskResume恢复一个任务很像,但是还是有区别,一旦Resume一个任务这个任务就一直运行下去了,但是Post一个信号量之后含有Pend的任务执行一次,之后到进入任务的下个循环继续Pend,只有等新的一次Post了之后才能继续运行。

3.OSFlagPost/OSFlagPend信号量集的发送和接受,也是一种多信号的集体通讯方式,这里不详细讨论,只举例简单说明其作用图中所示TaskA和TaskB共同控制TaskTarget,只有当TaskA,B都发送了信号之后,TaskTarget才得以运行。

实际上这种信号集的机制还可以有其他的逻辑关系可以配置,比如发送方中任意一个发送任务之后就可以让接收方运行。

【@.5 任务调度总结】先简单的利用前面的内容,回过头来看文章一开头的任务,搭建一个完整的电机控制系统。

这里我们利用uCOS-II中的通讯机制进行设计。

例:带按键去抖的电机控制任务:四个外部中断控制电机的启停,正转反转。

外部中断服务函数中Post一个信号量给一个专门的电机调度任务,电机调度任务之后Post一个信号量给按键去抖任务,此任务会利用OSTimeDly函数延时一段时间,比如说20ms,再次判断刚才按键的电平值,若任然有按键值则说明不是抖动,可以控制电机,之后利用Resume,恢复一个电机转动的实际任务。

Post信号量启用一个任务跟Resume恢复一个任务是区别很大的,最大的区别是,Post信号量之后只能让接收方运行一次,必须不停的Post才能不停的运行,而Resume一个任务之后,被恢复的任务将一直运行,只能用Suspend将其再次挂起。

相关文档
最新文档