HRTOS 长时间运行测试发现 uptime 计时异常:一次由 float 精度导致的嵌入式 Bug 修复
HRTOS 长时间运行测试发现 uptime 计时函数可靠性问题及修复过程一、问题背景在 HRTOS 长时间稳定性测试过程中发现系统运行超过一定时间后测试程序出现偶发异常。该问题最初表现为测试节点出现 FAIL但异常频率较低且系统整体调度仍然正常运行因此初步排查难度较大。经过持续运行测试发现系统运行超过 24 小时后调度触发次数达到15479921 次累计检测到107 次 FAIL 异常。继续观察运行状态调度次数达到15628968 次异常累计增加到114 次。通过测试日志分析发现所有异常均由os_uptime_ms()函数测试触发。该函数主要用于获取系统运行时间为系统运行状态监控、性能测试以及调试提供时间基准因此其可靠性直接影响系统测试结果。二、问题函数分析原版本os_uptime_ms()实现如下u32 os_uptime_ms() { u16 tick_h; u16 tick_l; u16 tick_value; u32 TS; float tick_ms; float total_tick; float total_ms; u16 result_h; u16 result_l; EA 0; tick_h OS_TICK_COUNT_H; tick_l OS_TICK_COUNT_L; EA 1; tick_value OS_T0_TH0; tick_value 8; tick_value OS_T0_TL0; tick_ms (65536.0 - tick_value) / 1000.0; if(tick_ms 0) { tick_ms 1; } total_tick ((float)tick_h * 65536.0) tick_l; total_ms total_tick * tick_ms; if(total_ms 4294967295.0) { total_ms 4294967295.0; } result_h (u16)(total_ms / 65536.0); result_l (u16)(total_ms - ((float)result_h * 65536.0)); TS result_h; TS 16; TS result_l; return TS; }初看该实现逻辑没有明显问题关闭中断保护 32 位 tick 数据读取获取当前定时器计数根据单 tick 时间换算毫秒返回系统运行时间。但是在长时间运行后出现异常这说明问题可能隐藏在数据计算精度方面。三、问题定位Keil C51 float 精度限制经过分析问题很可能来源于Keil C51 对 float 类型的处理方式。在 8051 平台中由于资源限制float运算效率较低浮点数据有效精度有限长时间、大数值累计计算容易出现精度损失。原函数中float total_tick; float total_ms;用于保存系统累计 tick 和累计时间。随着系统运行时间增加total_tick tick_count × tick_ms中的 tick_count 会不断增大。当数值达到一定规模后float 类型无法保持完整整数精度导致计算结果产生误差。而 uptime 函数要求的是长时间运行过程中时间累计结果必须保持确定性。因此浮点计算并不适合用于系统时间基准。四、修复方案取消浮点计算改用整数运算针对该问题对函数进行了重新设计核心原则不使用 float全部采用整数计算保证长时间运行结果稳定。修复后的代码u32 os_uptime_ms() { u16 tick_h; u16 tick_l; u16 tick_value; u32 total_tick; u32 tick_us; u32 tick_ms; /* * 读取32位tick计数 */ EA 0; tick_h OS_TICK_COUNT_H; tick_l OS_TICK_COUNT_L; EA 1; /* * 组合tick数量 */ total_tick ((u32)tick_h 16) | tick_l; /* * 获取单tick时间(us) */ tick_value OS_T0_TH0; tick_value 8; tick_value OS_T0_TL0; tick_us 65536 - tick_value; /* * 转换为毫秒 */ tick_ms tick_us / 1000; if(tick_ms 0) { tick_ms 1; } return total_tick * tick_ms; }修改后tick 累计采用u32时间换算采用整数避免浮点精度损失长时间运行结果更加稳定。五、修复后的回归测试修改完成后重新进行了长时间压力测试。截至本文发布调度触发次数27320039 次测试节点1611 个循环测试节点测试结果全部 PASS运行过程中未再次出现os_uptime_ms()相关异常。说明该问题已经得到有效解决。六、问题总结此次问题再次说明在嵌入式系统开发中能运行并不代表可靠长时间运行测试才能发现隐藏问题。尤其是在资源受限的 MCU 平台浮点运算需要谨慎使用时间系统、计数系统应尽量采用整数计算长时间累计数据必须考虑溢出和精度问题。对于 RTOS 而言系统时间属于基础设施任何微小误差都可能影响延时功能超时判断性能统计系统监控。因此底层基础模块必须经过充分的压力测试验证。七、HRTOS 后续计划该问题将在后续版本HRTOS V3.32中正式修复。同时该版本计划上线HRTOS Shell 模块用于更加方便地查看系统状态、验证实时调度以及进行开发调试。后续将继续完善 HRTOS 稳定性测试体系持续提升系统可靠性。敬请期待。