近日开发NRF52832的项目时,发现FreeRTOS使用Tickless模式存在一个隐含问题,即在线程中调用vTaskDelay时候存在一定概率延时到达时也不能从其中返回。
具体调试过程如下:
该问题直接体现:
NRF52832通过串口打印调试信息,当调试信息输出频率很高,运行一段时间之后会出现停止打印的情况。但是程序总体运行没有其他异常。
对该问题进行如下分析和调试:
(1)怀疑串口模块出现溢出之类错误:
通过在各种报错回调位置设置断点,并未在出现异常时候停下。
(2)怀疑专门用于打印错误信息的Debug_out线程出现逻辑问题导致死循环,或者卡死在某个等待操作系统事件位置:
出现异常后,在线程各部分尝试打断点,皆未停下,且没有继续调用串口发送函数。可认定并未在线程内发生死循环,并非串口发送引起的Bug,卡死或者挂起位置应该在所调用函数内。
(3)用全局变量作为记录,在线程各地方打入不同的值,通过卡死时候该变量的值,确定最终卡死位置。
而该函数内部比较简单,没有复杂逻辑,调用的官方库的函数也非常简单基本不存在卡死可能。唯一可能只有vTaskDelay。但感觉概率极低。故再用全局变量方式进行一次调试。如图。
最终确定了卡死的位置就在于vTaskDelay(10)这个函数上。但这个应该是系统一个非常基础功能,直接出问题可能性应该很低。故继续进行如下推测:
http://s10/mw690/002VF2gAzy7kGwFwHHP59&690
(4)怀疑是CPU负荷过大,该线程优先级太低导致
用内部自己编写的模块查看了实时CPU使用情况(即cpu_usage,0.1%分辨率),CPU使用率基本在1%。不过该线程优先级仅为2(最大为8),确实较低。但如此CPU负荷下应该不存在该问题。
(5)怀疑是启用了Tickless模式导致
Tickless模式是通过预先计算下一次唤醒的任务唤醒时间而在idle的时候直接定时到下一次任务唤醒才唤醒CPU进行处理,故不需要像通常操作系统每固定事件就唤醒并进行一次检查,非常适合用于控制功耗。但该模式也导致了调度控制算法的复杂性。
重新编译下载程序后进行测试,该问题得到解决,运行30min未出现异常(之前大概2-5min)。
由此可以知道Tickless模式存在该项问题,但具体是移植,配置,内核本身bug或者是用法问题还不清楚,暂时没有时间深入调试。
但该问题确实比较坑,这里只是相对比较显著一次暴露。最可怕就是其隐含导致出现其他地方奇怪的问题就很难调试了。故在低功耗要求不太高的场景下,建议暂时先不使用该模式进行具体的开发。