我在 STM32F446 MCU 上有一个 Rust 嵌入式项目。考虑下一行:
leds::set_g(self.next_update_time % 2000 == 0)
取模,网上看的,Cortex M4好像没有取模指令。相反,一个函数被添加到在软件中执行此操作的二进制文件中。使用cargo bloat(基于Google的Bloaty),可以找到。
File .text Size Crate Name
...
0.1% 6.9% 990B compiler_builtins __udivmoddi4
...
令我惊讶的是,它只需要不到 1 KB 的内存。我想这已经很多了。其背后的代码也很长,参见this关联。我认为这个实现速度很快。幸运的是我还有空闲内存。
使用 opt-level = 'z'
不会改变这一点。
但是如果我买不起这个怎么办,我怎样才能让它占用更少的内存呢?
当然可以求助于 this 这样的解决方案可以,但随后我将失去使用 %
运算符的能力。
最佳答案
不确定 Rust 链接器有多聪明,但在许多嵌入式链接器实现中,您可以交换自己的 __udivmodi4
实现,该实现使用更小(但更慢)的方法,而不是编译器提供的版本。
一般来说,通用除法和取模在嵌入式平台上是昂贵的,但是除以常量通常可以通过智能编译器通过“固定”实现来专门化(通常有公约数的特殊情况 - 3, 5, 7, 10 , ETC)。
如果您可以控制应用程序,那么更改代码以除或模 2^N
显然是更好的选择(它折叠为除法的“右移”指令或“与”指令)模指令)。例如。在本例中,2048 可能接近 2000,可以接受,并将 1 KB 代码转换为 4 字节代码。
FWIW Rust 版本确实看起来有点胖 - GCC implementation例如要小得多。
关于rust - 如何在 ARM 嵌入式 Rust 中使用更少的内存进行取模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59054054/