I'm new to Rust and after many fights with the compiler and borrow-checker I am finally nearly finished with my first project. But now I have the problem that the binary gets to big to fit into the flash of the microcontroller.
I'm using an STM32F103C8 with 64K flash on a BluePill. At first I was able to fit the code on the mc and bit by bit I had to enable optimization and such. Now I compile with:
[profile.dev]
codegen-units = 1
debug = 0
lto = true
opt-level = "z"
and am able to fit the binary. opt-level = "s" does generate a to big binary. The error I am getting then is: rust-lld: error: section '.rodata' will not fit in region 'FLASH': overflowed by 606 bytes
As I have under 1000 lines of code and as I would say not so unusual dependencies this seems strange.
There are a few sites like this with ways to minimize the binary. As these are not for embedded most of the ways to minimize are followed anyway.
How am I able to minimize the binary size and am still able to debug it?
My dependencies are:
[dependencies]
cortex-m = "*"
panic-halt = "*"
embedded-hal = "*"
[dependencies.cortex-m-rtfm]
version = "0.4.3"
features = ["timer-queue"]
[dependencies.stm32f1]
version = "*"
features = ["stm32f103", "rt"]
[dependencies.stm32f1xx-hal]
version = "0.4.0"
features = ["stm32f103", "rt"]
Maybe there is a problem as I noticed that cargo build does compile some sub dependencies multiple times in different versions.
Inside the memory.x file:
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
RAM : ORIGIN = 0x20000000, LENGTH = 20K
}
Rustc version rustc 1.37.0 (eae3437df 2019-08-13)
edit
The rust panic behavior is abort.
The code is view able under: https://github.com/DarkPhoeniz/rc-switcher-rust
I've run into similar issues and may be able to shed some light on what you can do to reduce the size of the binary you're outputting.
You've already discovered one of them: opt-level = "z". The difference between s and z is the inlining constraint - essentially, the size of a function where the compiler deems it not worth inlining. z specifies this to be 25, s 75. Depending on what you are building, this may or may not be a consequent reduction in size (and it affects .rodata and .text primarily).
Another thing you can play on is the behavior on panic on your code. If I remember correctly, the stm32 target supports both unwind and abort, with unwind enabled on the dev profile. As I'm sure you can understand, unwinding the stack is a large and costly process in terms of code size. As such, setting panic = "abort" in your cargo file might reduce the binary size a bit further.
Beyond that, it is down to manual tuning, and tools like cargo-binutils may be extremely useful for this. Depending on your use case, there may be leftover Debug implementations which are only sporadically needed, and that is definitely something that you could act on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With