Article summary
I’ve written a few posts on using Rust for embedded projects:
- Rust Sysroots for Easier Embedded Projects
- Using Rust 1.8 Stable for Building Embedded Firmware
- Generating Rust Bindings for Embedded Libraries
- Embedded Rust Right Now!
I think they gave a decent overview of a couple of tricky parts, but as always, the devil is in the details. To help with all the gritty details, I’ve written up a more complete example.
Overview
In order to actually run this example, you’ll need an STM32L1 Discovery Board. I don’t expect many readers to have this exact board, but it should be relatively easy to port to other targets/boards, and I thought a complete example would be useful as a point of comparison. This is basically just STM’s GPIO_IOToggle example but with the core inner loop replaced with some Rust code.
Essentially what I did was:
- Started with STM’s GPIO_IOToggle example
- Added a Makefile to build the example
- Setup the Cargo configuration necessary to target a Cortex-M3 in
.cargo/config
- Added rules to the Makefile to build a Rust
sysroot
containing a validlibcore
- Used bindgen to wrap the STM32 HAL libraries for use in Rust
- Replaced the core inner loop in
main.c
of the GPIO_IOToggle example with Rust code - Added rules to the Makefile to build the Rust code and link the resulting static library into the final binary
Running My Example
To run my example:
Grab a Rust nightly
- Install multirust fromhere if you haven’t already
- Run
multirust update nightly
Make a directory to work in
mkdir embedded_rust_experimentcd embedded_rust_experimentmultirust override nightly
Clone my embedded Rust example
git clone https://github.com/jvranish/rust-embedded-example.git
Clone Rust src into sibling directory
We need to clone the Rust repo:
git clone[email protected]:rust-lang/rust.git
And then we need to check out the commit that matches the version of our compiler. To find the commit for our current compiler you can do this:
$ rustc -vVrustc 1.11.0-nightly (ad7fe6521 2016-06-23)binary: rustccommit-hash: ad7fe6521b8a59d84102113ad660edb21de2cba6commit-date: 2016-06-23host: x86_64-apple-darwinrelease: 1.11.0-nightly
And then check out that specific commit:
cd rustgit checkout 8903c21d618fd25dca61d9bb668c5299d21feac9cd ..
Your commit-hash will almost certainly be different than what I have here. Don’t just copy what I have :)
Download ARM gcc fromhere and put it into a sibling directory. In my case, I put it in../tools/gcc-arm-none-eabi-5_3-2016q1/
Get STM32 Cube for L1 line
Get the Cube HAL fromhere and put it into sibling directory. In my case, I put it in../STM32Cube_FW_L1_V1.5.0/
Install openocd
Install my favorite debugger toolchain. On macOS, if you haveHomebrew installed, you can just do this:
brew install openocd
Run example
Open upMakefile
inembedded_rust_experiment
and make sure the variables:GCC_ARM_PATH
,STM32_CUBE_PATH
andRUST_SRC_PATH
are set to sensible values.
Then to run the example:
- In one console, run openocd.
cd rust-embedded-examplemake openocd
- In another console, build and debug.
cd rust-embedded-examplemake debug
When the gdb prompt shows up, you should be able to pressc
and enter. Then you should see blinking lights on your discovery board. That’s it!