当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读][b]引 言 [/b] Small RTOS5l是一款专门为80C5l系列单片机设计的实时操作系统(实际上应该称其为实时内核),大部分代码用C语言编写,易于移植,十分适合于资源紧张的8位机。

[b]引 言 [/b] Small RTOS5l是一款专门为80C5l系列单片机设计的实时操作系统(实际上应该称其为实时内核),大部分代码用C语言编写,易于移植,十分适合于资源紧张的8位机。同时,它也是学习嵌入式操作系统原理极好的入门材料。本人就是在学习完SmallRTOS5l的基础上进一步学习了著名的uC/0S-II,受益颇多。 1 问题描述 在将Smau RTOS51应用于实验室某项目时,发现了一个奇怪的问题。简单说来,就是一个以无条件方式申请消息的任务竟然在没有取到消息的情况下,以指示“等待超时”的代码返回了。 在这里,首先解释一下任务申请消息的两种方式:无条件方式和超时方式。所谓五条件方式是指任务申请消息时,如果暂时没有消息可取,则任务将一直等待消息,直至取到为止;而超时方式是指任务等待消息是有时间限制的,超过所设定的最大时间,即便没有取到消息,函数也可以正常返回,只是返回值不是消息,而是“超时代码”(此方式可以防止任务因取不到消息而被永久性挂起)。可见,如果任务以无条件方式申请消息,那么函数若能够返回,则说明任务一定是取到消息了,而返回值又怎么可能是“等待超时”呢?经过仔细分析SmallRTS5l的源代码,找到了问题产生的根源。 假定有任务IDX以超时方式调用OSQPend()函数申请消息。OSQPend()函数首先会把IDX放到此消息队列的等待任务表中,然后再去判断队列中是否有消息。最佳情况是队列中确实有消息,则OSQPend()再把IDX从此消息队列的等待任务表中删除,接着OSQPend()返回,任务取到消息。 此刻,假定消息队列中设有消息。那么,OSQPend()就会调用OSClearSigna1(OSRunningTaskID())和OS- Sched()这两个系统函数,迫使IDX进入休眠态,同时调度器调度下一个最高优先级的就绪任务来运行。假定任务IDY被选中,且IDY在运行中通过调用OSQIntPost()函数向此消息队列发送了一则消息。则OSIntPost()将把所有等待这个消息队列的任务中优先级最高的那个任务唤醒,并且把它从该消息队列的等待任务表中删除,假定它就是IDX。 当任务IDY进入休眠态后,操作系统才会调度IDX来运行。于是IDX从上次被强迫休眠的地方开始运行,即从OSQPend()函数中紧接着 OSSched()的那条指令开始执行。具体来说,OSQPend()将首先查看IDX是否满足超时条件(用来判断任务是因为等待超时被唤醒的还是因为确实取到消息而被唤醒的),若超时时限尚未到达,OSQPend()再接着检查消息队列中是否已经有了消息。根据上面的假定,可以知道任务IDX确实是因为取到消息而被唤醒的。于是,OSQpend()把IDX从此消息队列的等待任务表中删除,OSQPend()正常返回。这样,任务IDX取到消息,接着运行。 以上都没有什么问题,但是,有一种情况被忽略了,而正是这种情况的出现导致了任务IDX被长时间挂起,就算队列中有消息存在,IDX也无法被唤醒,只能等到其超时为止。 为讨论方便,不妨仍按上述假定情况来分析。当任务IDX被唤醒且IDY进入休眠状态后,系统必将调度下一个优先级最高的就绪任务来运行。在前面,认为这个任务就是IDX,然而此时,假定它是另一个比IDX优先级更高的任务IDZ(因为有可能是中断把IDZ唤醒的,所以中断退出时,操作系统强制IDY进入休眠态,转而调度IDZ运行)。非常巧合的是,IDZ在运行的过程中向同一个消息队列也申请了消息。由于之前IDY已经向消息队列发送过一条消息,则IDZ 将正常取到此条消息。于是,消息队列中的消息数减为O(Buf[0]==0)。在任务IDZ进入休 眠后,任务IDX被操作系统调入CPU运行。同样,函数OSQPend()首先查看IDX是否等待超时。如果没有超时再检查消息队列中是否存在消息。注意到先前已经假定消息被任务IDZ给取走了,所以检查的结果当然是队列中不存在消息。IDX就只好再次进入休眠,函数OSSched()调度别的任务运行。 于是问题出现了。IDX是因为暂时取不到消息而被挂起的,但此时这个消息队列的等待任务表中已经投有IDX的踪影了,它之前就已被那个发送消息的IDY在 OSQIntPost()函数中给删除了。 结果,即使后面有任务再次向队列中发送消息,IDX也取不到了,因为消息发送函数OSQIntPost()已经无法从消息队列的等待任务表中找到IDX 了,它将被长时间挂起,直至超时。也就是说,任务IDX明明可以取到消息的,却取不到,最后只能以指示其等待超时的代码返回。 这还是一种相对来说不太严重的错误,无非就是任务没取到消息,以超时返回而已.如果任务IDX以无条件方式申请消息,而又恰恰发生了上面的情况,会有什么样的后果呢?由于OSQPend()函数自身的特性,所谓五条件等待就是把超时时间设为0。结果任务IDX被唤醒后,OSQPend()必然会检测到其已超时,然后又会检测到队列中没有消息,所以就必然以“超时代码”返回。结果就发生了文章开头所说的一幕;一个必须在取到消息后才能返回的任务,居然在没有取到消息的情况下以指示其等待超时的代码返回了。 2 解决方法 问题已经找到,就有解决的办法.以《嵌入式实时操作系统SmallRT0s5l原理与应用》(陈明计,北京航空航天大学出版社,2004)中程序清单 7.5为例。书中的代码如下: #if OS_MAX_TASKS<9 //把当前任务加入到此消息队 //列的等待任务表中 Buf[3]=OSMapTbl[OSRunnmgTasklD()]; (5) #else if(OSRunningTasklD()<8){ (6) Buf[3]=OSMap Tbl[OSRunningTasklD()]; (7) else{ Buf[4] |= OSMapTbl[OSRunningTasklD( ) %26;amp;()x07]; (8) } #endif while(Buf[O]==0) //消息队列中暂时投有消息 (9) { #ifdef_C51_ SP=SP+sizeof(Buf)。 (10) *((uint8 0S_Q_MEM_SEL * data*)(SP+l-slzeof(Buf))=Buf; (11) #endif{ OSClearSignal(OSRunningTask()); //当前任务进入休眠 //状态 (12) OSSched(); //调度下一个最高优先级的就绪任务运行(13) #ifdef_C51_ Buf= *((uint8 OS_Q_MEM SEL*dota*)(SP+1-sizeof(Buf)); (14) SP=SP-sizeof(Buf); (15) #endif if(OSWaitTick[OSRunningTasklD()]==O)(16) { break; //任务再次运行,如果超时到,退出循环 } } //while(Buf[0]==O) 修改的方法是把(5)"(8)放在(9)后面作为while()循环的第一步,其他不变。即只有在OSQPend()函数检测到没有消息可取的情况下,才把任务添加到对应于此消息队列的等待任务表中。一来,若队列中已经存在消息,这可以加快。SQPend()的执行速度;二来,对于以超时方式申请消息的任务,不会发生如前所述的队列申明明有消息,任务却取不到,只能等待至超时为止的情况。即使IDZ抢先一步取走消息,只要尚未超时,IDX会再一次被 OSQPend()添加到消息队列的等待任务表中。这样,以后运行的OSQIntPost()函数就能够知道IDX仍然在等待消息,从而使lDX有机会获得消息。 此法简单易行,但对于以无条件方式申请消息的任务并不凑效。因为无条件等待时,任务被唤醒,其必然满足超时条件。所以无论其能否取到消息,指令都会跳出 while(Buf[0]==0)循环,结果就有可能返回让人难以理解的超时代码。这时,需应用程序通过额外检测OSQPend()的返回代码类型来判断任务是否真正取到消息。 另一种方法是仿照uC/OS—II的思路(较复杂,不推荐)。在发送消息的OSQInatPost()函数中,如果检测到有任务正在等待此消息,则并不把消息数(Buf[0])加l,其他部分不变。这样,即使IDZ抢在IDX再次运行前申请消息,也会因为发现队列中没有消息而被迫进入休眠.但对于正在函数 OSQPCnd()中等待消息的任务IDX来说,当它再次运行时也会发现消息队列中的消息数为O。这时,OSQPend()就需要另外检测IDX是否仍然在等待任务表中来判断任务到底能否取到消息。若任务还处在消息队列的等待任务表中,则任务必定是由“超时”唤醒的,可直接返回超时代码;否则,说明是有别的任务通过发送消息将其唤醒的,则可以取到消息。这样,以无条件方式等待消息的任务也就不会返回指示其等待超时的代码了。只是此方法也有一个BUG,那就是如果有任务抢在IDX取走此消息之前向队列中又发送了另一个消息,则新入队列的消息存放位置将会重叠前一条消息(uC/OS—II中不存在此问题)。也就是说,首先进入队列的那条消息被覆盖掉了,而谁也不知道它曾经存在过。 同样的问题也会发生在互斥型信号量的操作中,感兴趣的读者可以参看相关代码分析。 结 语 需说明一点,以上分析仅仅针对Small RTOS51(V1.12.1)。在本文发表前,本人曾与《嵌入式实时操作系统Smell RTOS61原理与应用》一书的作者陈明计先生就此问题通过E_mail进行过讨论。他指出:“V1.12.1的版本确实有此问题,但在V1.20的版本中不会(尽管代码相似)”。只是笔者在看过V1.20版本后觉得,只有当任务IDX优先级较高时,才有可能不发生此类错误,否则就很难保证了。不知广大爱好者有何见解,希望能与您共同探讨,请发E_mial到nt_chen@163.net或投稿到本刊。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

北京2024年5月13日 /美通社/ -- 5月11日,软通动力在鲲鹏昇腾开发者大会2024期间举办"软硬全栈,加速智能化赋能"分论坛。业界专家学者和优秀企业代表齐聚一堂,共同交流分享鲲鹏昇腾生态的创...

关键字: 智能化 全栈 PEN 计算机

上海2024年4月16日 /美通社/ -- 4月14日,为期四天的第89届中国国际医疗器械博览会(CMEF)盛大收官。澳鹏Appen很荣幸再次作为唯一的人工智能训练数据参展商参与此次"航母级"规模医疗...

关键字: APP 医疗器械 PEN 模型

北京2023年9月22日 /美通社/ -- 随着人工智能、云计算等技术的快速发展,算力需求爆发,服务器设计呈现多元异构特征,如何快速适配多种通用计算处理器、多种异构加速器和各类部件,实现服务器高效、稳定、可靠运行,对服务...

关键字: 三星 开源 英特尔 PEN

北京2023年9月21日 /美通社/ -- 近日,由开放数据中心委员会(ODCC)主办的2023“开放数据中心大会”在北京国际会议中心举行。今年是ODCC成立10周年,大会汇集了数据中心产业链上下游企业、科研机构、专家学...

关键字: 数据中心 TI PEN DC

北京2023年9月15日 /美通社/ -- 9月8日,2023年鲲鹏应用创新大赛陕西赛区决赛成功落幕。经过现场答辩、问题答疑等环节,软通动力"基于鲲鹏硬件的信创医共体解决方案" 最终荣获20...

关键字: 大赛 PEN 操作系统 华为

冠闵信息近年云收入保持双位数增长 北京2023年9月13日 /美通社/ -- 亚马逊云科技连续七年授予上海冠闵信息科技有限公司(以下简称:冠闵信息)托管服务提供商(MSP)认证,其借助亚马逊云科技在云能力、技术方案构建...

关键字: 亚马逊 数字化 SEARCH PEN

与全球一线标准治疗方案泰瑞沙单药治疗相比,联合疗法降低疾病进展风险38% 新加坡2023年9月12日 /美通社/ -- III 期临床研究FLAURA2的阳性结果显示,在局部晚期(IIIB-IIIC 期)或转移性(IV...

关键字: BSP AI FOR SMALL

(全球TMT2023年9月4日讯)8月31日,第二十五届中国国际软件博览会在天津梅江会展中心拉开帷幕。软通动力子公司鸿湖万联受邀参会,通过展示开源生态建设成果,为中国软件产业腾飞提供“加速度”。 鸿湖万联...

关键字: PEN HARMONY AI 软件

北京2023年8月22日 /美通社/ -- 共聚软件名城,共谋数字未来。8月20日—8月23日由江苏省工业和信息化厅、南京市人民政府主办,南京市工业和信息化局、南京市软件集群发展促进机构承办的2023中国(南京)国际软件...

关键字: 开源 软件 鸿蒙 PEN

北京2023年8月16日 /美通社/ -- 近日,在备受业界关注的OCP China Day 2023(开放计算中国技术峰会)上,面对多元算力平台运维管理方面的重重挑战,浪潮信息正式发布了基于OpenBMC的I...

关键字: 固件 PEN 开源 芯片
关闭
关闭