网站大量收购独家精品文档,联系QQ:2885784924

SmallRTOS51中的一个典型问题及其解决方法.docx

SmallRTOS51中的一个典型问题及其解决方法.docx

  1. 1、本文档共6页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
PAGE 1 PAGE 1 SmallRTOS51中的一个典型问题及其解决方法 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明明可以取到消息的,却取不到,只能以指示其等待超时的代码返回。 这还是一种相对来

您可能关注的文档

文档评论(0)

run8753 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档