根据经验,我尽量避免在我的嵌入式系统代码库中使用浮点。
浮点变量是:
- 计算密集型
- 非原子性(可能导致 RTOS 应用程序出现问题或出现中断)
- 它们的精度会导致不明显的行为(浮点比较问题)。
但是带有浮点单元的微控制器(如 STM32F4)呢?
这些担忧仍然适用吗?你还会建议不要使用浮点吗?
根据经验,我尽量避免在我的嵌入式系统代码库中使用浮点。
浮点变量是:
但是带有浮点单元的微控制器(如 STM32F4)呢?
这些担忧仍然适用吗?你还会建议不要使用浮点吗?
您应该记住,这些微控制器上的 FPU 通常只是单精度 FPU。单精度浮点只有 24 位尾数(带有隐藏的 MSB),因此在某些情况下,您可以从 32 位整数中获得更好的精度。
我已经使用定点算法完成了工作,对于数据具有有限动态范围的情况,您可以使用 32 位定点实现与单精度浮点相同的精度,并且执行时间大约提高一个数量级. 我还看到编译器为 FPU 带来了相当多的库开销。
如果您购买带有硬件 FPU 的处理器,那么您就不必担心精度*、可重入行为等。继续使用它们!
不过有几点想法:
您可能会认为处理器可以在不使用时关闭(大型)FPU,因此请检查运行您的 FP 例程是否比在软件中执行它节省了您的功率(如果您关心的话)。
根据实现的不同,FPU 也可能有不同的内核寄存器——有时编译器可以巧妙地利用这些寄存器。
不要将 FPU 用作不良固件设计的拐杖。例如,你可以用定点做同样的事情,而用普通的核心来代替吗?
(* FPU 应符合给定的标准实现,因此请注意由此产生的任何限制。)
一些担忧仍然存在。
尤其是后者可能会导致非常讨厌的问题,并迫使您编写非直观的代码,例如总是与范围进行比较,从不测试与固定值的相等性。
请记住,单精度浮点数只有 23 位分辨率,因此您可能需要用双精度浮点数替换 32 位整数。
如果你有 FPU,计算通常很好,而且权衡很容易理解。
但请注意输出。如果你有类似 C 库之类的东西,你会惊讶于printf("%0.6g", x);
我见过的malloc()
内部使用的库所固有的复杂性printf()
,而这不是你在微控制器中想要的那种东西。