Some time ago, I was reading the Rust book to learn the differences between Rust and other programming languages. Because Rust is getting popular also in embedded systems, I wanted to setup an environment to practice programming embedded devices by using the Rust language. I had already browsed through the embedded Rust book and noticed that I had a similar development board that was used as an example in that book. This post covers setting up the environment to build and debug embedded Rust applications using STM32F0 discovery kit and vscode.
I won't cover the whole installation process here, I followed the instructions mentioned in the embedded Rust book to install Rust, ARM embedded toolchain and OpenOCD for Windows. I had STLink driver already installed. Because I was cross compiling for STM32F072 ARM Cortex-M0, I added the thumbv6m-none-eabi compilation target with rustup command.
Now I had tools installed and I was ready to verify OpenOCD connection to the board and the compiler version:
I took the cortex-m-quickstart project as a basis for my trials and used the app name for that to make sure I could follow the Rust book examples:
I modified .cargo/config.toml to select correct toolchain for ARM Cortex-M0. Then, I checked the microcontroller (MCU) reference manual to find out the memory organization and changed the memory sections in memory.x to match the memory layout and the sizes of my MCU.
I used the following settings in openocd.cfg:
Now I had configured everything and I was ready to follow the Rust book to build hello world example and start debugging that:
After getting debugging working with the OpenOCD and GDB I wanted to have the same functionality working in the Integrated Development Environment (IDE) so I installed vscode. After opening the project folder with vscode, it suggested automatically to install necessary extensions, rust-analyzer and Cortex-Debug. After this, the only thing I needed to do, was to modify .vscode/launch.json to match my settings.
With these settings, I was able to start a debug session from a Run and Debug tab:
The README.md in .vscode folder also instructs to install System View Description file to describe the MCU register contents. I downloaded the file from the ST website, copied it to .vscode folder and added that to the launch configuration with the following code:
Now I had a working debugging environment and I was able to see MCU peripherals registers directly on the IDE:
Before writing my own code I needed to get familiar with the embedded Rust. Rust offers different abstraction levels of the microcontroller. The lowest level include Micro-architecture Crate (including general ARM functionalities) and Peripheral Access Crate (PAC, including various memory wrapper registers). Above these are the Hardware Abstraction layer and the board specific layers. In other words, there are multiple ways of accessing MCU resources. Because I felt being more familiar with the MCU resoures than Rust, I started from the lowest level of abstraction.
As usual, I will practise debugging with the LEDs. STM32F0 discovery kit has 4 user controlled LEDs connected to I/O pims PC6 .. PC9. I needed to find a way to access these LEDs from Rust. Here is a function to set blue LED (PC7) on by using core library to write memory mapped I/O registers. Note that this will overwrite the current register value without reading it first.
If I want to use higher abstraction level, the next option would be to use PAC crate. To use it, I added the following code to the Cargo.toml which will also enable features for my MCU variant:
Then I added a function to set red LED (PC6) on. Note that I used modify function here to update register value and to keep other LEDs also on (and not to overwrite the existing register value).
The last thing I will try is to use the board level crate stm32f072b-disco. The following code is a clip from the board crate example code, I modified the code to control the green LED only instead of toggling all LEDs in turn.
I have to admit that I need more practise with Rust before being very efficient. For me, I think those lower level crates were the most fluent way to access MCU resources. But now I have a working development environment to continue learning and developing rusty embedded applications.