扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

移植了FreeRTOS,跑了一夜之后出现异常是怎么回事?

03/05 09:28
219
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

新的一年开始了!上班后的第一周不太忙,处理了一个年前遗留的问题。

某工程师移植了一个FreeRTOS操作系统,运行了3个任务

MainTask: 间隔10秒(不是非常精确,大概9秒左右) LCD数值加一。

JcqTask: 间隔1秒翻转LED指示灯

ModbusTask:等待信号量(按键中断),刷新LCD的数据。

该工程师反馈跑了一夜后,第2个任务的LED灯不闪烁了,出现异常后,其它两个任务都还正常,就LED灯闪烁的任务不正常。

这个问题听起来挺诡异,我在年前也复现出来了,确实需要好几个小时才能复现出来。

起初怀疑是栈溢出,后来通过增加调试信息,发现并没有。

另外这个出问题的任务优先级还是最高,排除是优先级引起的问题。

后来看了看他移植的代码,他用到了FreeRTOS的低功耗tickless模式,它的核心逻辑是:让系统在没有任务需要处理时,直接进入深度睡眠,而不是靠“定时器中断”来维持心跳。

这样的好处是省电,避免了无意义的定时器中断,让CPU在需要时才运行工作。

在 FreeRTOS中,Tickless模式通常通过配置宏 configUSE_TICKLESS_IDLE来开启。

#define configUSE_TICKLESS_IDLE        2

当系统进入idle 状态下,调用portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )这个函数。

这是由移植者根据MCU平台要实现的一个关键底层函数。它的核心功能是计算休眠时间、关闭系统节拍定时器、让CPU进入低功耗模式,并在正确的时间唤醒系统。唤醒系统要靠一个低功耗定时器来实现。

想来想去,大概率问题会出在这里。

后来咨询了一下VsCode Copilot AI,它快速帮我定位到了问题,问题出在下面这个代码

将其修改为如下代码就没问题了。

原因是当 LPTIM 是一个16位的计数器,如果不加 & 0xFFFFUL 掩码,当溢出时会导致计算出的差值为一个很大的负数(当做 uint32_t 时就是个巨大的正数),传给 vTaskStepTick()函数就会引起异常现象。

扫码加入嵌入式交流群:

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录