- void debug_printf(const char *fmt, ...)
- {
- va_list args;
- if(xSemaphoreTake(semDebug,portMAX_DELAY);
- va_start(args,fmt);
- vprintf(fmt,args);
- va_end(args);
- xSemaphoreGive(semDebug);
- }
当调用debug_printf的时候先去获取信号量semDebug,如果获取不到就一直等待直到获取。该函数执行完毕以后再释放信号量。这样就充分保证了资源的独占,同时只可能有一个任务再进行debug_printf。需要说明的是vprintf底层最终还是会调用我们重映射的fput函数。
再次上电,打印终于正常了,但是,还有但是……一波未平一波又起。开锁的时候失败了,开锁任务是一个需要实时的任务,要检测传感器转动位置。而这个异常明显是实时性得不到满足。
仔细分析下,问题就出在printf互斥量的获取。有可能造成高优先级任务产生延时,甚至造成优先级翻转。
假如有三个任务:任务A、任务B、任务C,优先级从低到高。现在任务A调用了debug_printf 获取了信号量,而高优先级的任务C也需要调用debug_printf,但因为获取不到信号量就会造成暂时挂起,等到任务A打印完成把信号量释放了任务C才能得以运行。这样高优先级的任务无法抢占低优先级任务而降低了实时性。如下图所示:

上图的是一种情况,还不算最坏的。还有可能出现优先级翻转的问题,造成延时更大。同样最低优先级任务A先运行并且调用了debug_printf获取到了信号量,而这时候任务c也需要运行并调用了debug_printf。但是因为A已经把信号量占用而无法获取到,所以暂时被挂起。任务A开始打印,在打印到一半的时候,被中等优先级的任务B给打断了(任务B不调用debug_printf所以可以打断A)。这时候A又挂起了,任务B开始运行,等到B运行完以后继续运行A。等A运行完信号量释放了,高优先任务C终于可以得到运行了。如下图所示,这时候看看任务C本来可以实时的运行的,现在却中间又穿插先运行了中优先级任务B。造成一个中优先级比高优先级任务先得到运行的优先级翻转现象。而实时性相比上图就更差了。
并且这个延时是不可估量的,想想任务B还可能再被更高优先级的任务打断。高优先级任务C反而被一再延时执行。所以出现高优先级任务出现问题就不难理解了。

发现了问题还是要解决问题。根据分析肯定要改造一下debug_printf,同时为了实时性得到满足。我就把任务C高优级的打印LOG暂时关闭。
而针对debug_printf中获取信号量修改为有时间限制,不再无限期等待。这样顶多出现获取不到信号量5ms超时返回少打印一条log信息,总比把任务卡出异常要好的多。改造后的debug_printf如下:
- void debug_printf(const char *fmt, ...)
- {
- va_list args;
- if(xSemaphoreTake(semDebug,5)==pdFALSE)return;
- va_start(args,fmt);
- vprintf(fmt,args);
- va_end(args);
- xSemaphoreGive(semDebug);
- }
转载请注明转自:电子创客营
欢迎关注我们的公众号 [电子创客营] 获取更多技术分享!