问题描述
我有一个开源项目 (https://github.com/WhiteFossa/yiff-l),我在其中使用 STM32F103 MCU。
在固件中,我有很多带有浮点参数的 sprintf,例如:
<span>
<a class="Update" href="{% url 'link' %}">Get Link</a>
</span>
我曾经使用相当老的 arm-none-eabi xpack 很长一段时间(IIRC 是 9.3.1 版本),一切都很好。
然后我不得不重新安装我的软呢帽,当然我有一个更新版本的 arm-none-eabi。 我的项目停止编译,我修复了一些代码,现在它再次编译,但在任何带有浮点数的 sprintf 上都会产生硬错误。
如果我排除了 -u _printf-float 链接器标志,那么硬故障就会消失,但当然我的字符串中没有浮点表示。
我很确定问题不在我的代码中,我什至尝试将 sprintf 作为 main() 的第一行,但仍然存在相同的问题。
什么会导致这种奇怪的行为?我该如何调试它? (从未用于调试 ARM 反汇编)。
附言我尝试安装较旧的 arm-none-eabi xpacks,但没有任何运气 - 问题仍然存在。
P.p.s.我尝试使用优化设置/更改版本进行调试,反之亦然,在 section.ld 中设置了 4 倍以上的堆栈 - 一切都没有成功。
任何帮助将不胜感激。
解决方法
看到这段代码我唯一能想到的就是力量的价值是巨大的:
double power = 11111111111111111111111111111111111111111111.2;
char buffer[32];
sprintf(buffer,"Power: %.1fW",power);
printf("%s\n",buffer);
如果不是这样的话,其他地方一定有一些 UB
,查找硬故障很复杂,而且很多时候可能会令人沮丧。在大多数情况下,我遇到了硬故障,我只是跳到使用一个硬件调试器。我用于 Cortex-M 设备的是 Segger 的 J-Tag Pro。还有其他型号,更便宜,更便宜。
什么会导致这种奇怪的行为?正如您所确定的,当 sprintf
被禁用时,您的问题被掩盖了。我最好的猜测是,这很可能是由输出缓冲区中的缓冲区溢出或有缺陷的库代码引起的。某些 sprintf
实现使用堆内存分配而不检查 NULL
返回。使用 Fee-RTOS 的 BSP 实现需要进行更多调整才能启用动态内存管理。
如果即使使用大缓冲区也出现硬故障,则这可能是由 sprintf
中的内部内存分配引起的。您可以尝试使用其他库。据我所知,newlib-nano
在某些情况下会导致此错误。
在某些情况下,需要增加调用 sprintf
/ snprintf
的任务的堆栈大小和全局堆大小。
我如何调试它? 可能唯一的解决方案是将一个硬件调试器与一个完整的 IDE(如 Eclipse)结合使用。 Here 是一些信息,可为您提供一些指导。 J-Link Edu Mini 硬件调试器的价格相当实惠,但您周围还有更多有用的选项。
我用类似的 CPU(Kinetis K22,从前飞思卡尔现在 NxP)给出的解决方案是创建我自己的浮点到字符串转换函数。它显着提高了性能(不再有 malloc
秒),硬故障错误消失了,我将每个任务的堆大小调整到我真正需要的大小。
我终于能够在 https://github.com/mpaland/printf
的帮助下运行我的固件即我刚刚在我的代码中去掉了 Newlib 的 sprintf()。