现在的裸机程序已经不能满足嵌入式机器人所需的代码结构要求了,因为一个嵌入式机器人的系统是非常庞大的,分别由感知算法,决策算法和控制算法等组成,这还没有算上一些需要联网的程序。庞大的代码需要一个芯片级的操作系统来屏蔽掉硬件对于上层算法的影响,同时向上层提供API,帮助上层的算法调用底层硬件,因此一个芯片级操作系统就十分重要了,而RT-Thread是一种国产的芯片级操作系统,而我的课程刚好也涉及到了该系统,所以我准备写一系列的博客来记录下我在学习这个操作系统过程中的种种问题,希望能带给大家一些帮助~
问题现象
这学期我们在上嵌入式的课程,学习了一个新的轻量级操作系统——RT-Thread(后面简称为rtt),这是一个国产的操作系统,这个操作系统的特点就是只有线程,没有进程,那么我们要使用这个系统的话只需要操作相应的线程就可以了,那么我们用好这个系统的方法就很简单了,我们只需要实现各个线程间的协调工作就可以了。
言归正传,在我学习这个rtt的时候我出现了一个问题,那就是当我的main函数的while(1)里面啥东西也不放,空跑的时候,整个芯片就宕机了,代码如图:
原因及解决办法
【走过的弯路】
开始的时候我以为这个原因就是在我的整个工程中main线程的优先级比较高,其他线程的优先级都是最低的(我这里设置的是25),那么在线程调度的时候高优先级的线程会先被调度,main线程作为我的系统中优先级最高的线程,而且是在空跑的一个线程,那么就是这个main线程在一直占用着系统资源,其他线程都不能被调度,因此出现了类似于系统宕机的现象。
说到这里就不得不说一下我们这张rtt系统的线程调度的状态流转图了。
在普通的操作系统中,这些状态之间的流转还是比较好理解的,但是在rtt中,它有一个与其他操作系统所不同的地方,这我在前面也已经讲过了,那就是它是没有进程这个东西的,因此在rtt操作系统中,就绪状态=运行状态。也就是说图中的2号圆圈代表的循环就相当于等价。
但是,这样就出现问题了,因为如果按照我这个逻辑的话,不止是在空跑main线程的while(1)的时候会出现系统宕机的情况,就算main线程的while(1)里面加入了任务程序,那么我们整个rtt系统也是会根据系统进程的调度机制(高优先级的线程一定会先被调度)来不停的循环调用main线程里while(1)里面的任务,同样其他的线程也是不会被调用的,这样肯定是不行的,于是我就去rtt的官网查询相关资料,最终解开了这个问题背后的谜团。
恍然大悟
首先让我们来rtt系统中明确一些概念。
我们以下面这个代码段来举例说明:
void thread_entry(void* paramenter) { /* 等待事件的发生 */ /* 对事件进行服务、进行处理 */ }
线程就绪/运行
这个代码是线程的实体函数,那rtt系统届时会怎样执行这个程序呢?我画一个形象的图给大家解释一下。
如果这个线程优先级够高的话,rtt系统会一直执行这个线程,也就不会执行其他线程了,因为该线程运行结束之后会进入就绪状态,又因为该线程有最高优先级,所以进入线程调度池之后马上又会被调度运行,进入运行状态,但是在rtt 中,实际上(实现过程中)线程并不存在运行状态,就绪状态和运行状态是等同的,但是在理解机制时照上面说的来理解较为方便。
线程挂起
rtt官网有对其较为详细,清楚的描述,我这里做了一个搬运,侵删。
这段话里面重要的就是这句话,线程不参与调度,也就是说不论该线程优先级有多高,他都不会进入到线程调度池里面,根据表格中的描述,导致线程挂起的条件有2个资源不可用。
线程主动延时一段时间
解决问题
main线程就是一个特殊的线程,所以他肯定也符合rtt系统管理线程的机制。
那我们这个问题就很好说明了。当main线程的while(1)循环内程序没有发生资源不可用或者线程主动延时的操作时,该线程一直会处于运行/就绪阶段,又因为我的程序中,main线程优先级最高,所以我的main线程一直霸占着系统资源,造成了系统宕机的假象。但是如果我在main线程的while(1)循环中插入一段延时程序,main线程就会进入挂起状态,让出系统资源,从而使其他线程有机会得到调度,使得该系统能稳定运行。
原文标题:机器人”大脑”:RT-Thread的main线程“卡死”的一种可能原因及解决方案
文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。
责任编辑:haq
全部0条评论
快来发表一下你的评论吧 !