Embedded Rust example for STM32F4-Discovery board.
The Rust Discovery book is an excellent introduction to embedded Rust. The book uses the slighty different STM32F3-Discovery board, whereas this project uses the STM32F4-Discovery board.
The differences are as follows:
- MCU changes from Cortex-M3 to Cortex-M4
- Version of the debugging port (ST-Link)
- Hardware Abstraction Layer (HAL)
The memory map remains the same between the two boards.
Using Ubuntu 20.04 LTS
- Install Rust using Rustup, update if required
- Add the Cortex-M4 target to the Rust compiler
$ rustup target add thumbv7em-none-eabi
- Install the multi-architecture debugger gdb and open On-Chip debugger packages using:
$ sudo apt-get install gdb-multiarch openocd
- Set udev rules for USB to enable access without root privilege
-
Create the file
/etc/udev/rules.d/99-openocd.rules
-
Add the following lines to the file
# STM32F4 - ST-Link/V2
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE:="0666"
- Reload the rules with
$ sudo udevadm control --reload-rules
- Install probe-run for debugging and programming
cargo install probe-run
Connect the discovery board ST-Link (USB mini B) port to the computer USB port and type:
$ lsusb | grep -i stm
Bus 001 Device 006: ID 0483:3748 STMicroelectronics ST-LINK/V2
Note that the Bus and Device numbers may differ, but the ID should be the same if you have a STM32F4-Discovery board.
$ ls -l /dev/bus/usb/001/006
crw-rw-rw-+ 1 root plugdev 189, 5 Aug 13 14:48 /dev/bus/usb/001/006
As above the permissions should be crw-rw-rw-
Run the command:
$ cargo build
Note that this uses the .cargo\config
file to set the target to thumbv7em-none-eabi
for the Cortex-M4 processor on the STM32F4-discovery board.
Alternatively run the command:
cargo build --target thumbv7em-none-eabi
This build uses the memory map for the STM32F4-Discovery board recorded in the file memory.x
.
You have two options here, manually: with OpenOCD, or with probe-run First open the OCD connection.
Run the command:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg
This should produce the following output:
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 2000 kHz
adapter_nsrst_delay: 100
none separate
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : clock speed 1800 kHz
Info : STLINK v2 JTAG v21 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 2.896991
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Also, one of the red LEDs, the one closest to the USB port, should start oscillating between red light and green light.
Use control-c to quit the program.
With OCD running in another terminal run the following command:
$ gdb-multiarch -q target/thumbv7em-none-eabi/debug/emb-rust
You should see:
Registered pretty printers for UE4 classes
Reading symbols from target/thumbv7em-none-eabi/debug/emb-rust...
(gdb)
Connect to OCD
(gdb) target remote :3333
Remote debugging using :3333
0x00000000 in ?? ()
(gdb)
Load the application
(gdb) load
Loading section .vector_table, size 0x1a8 lma 0x8000000
Loading section .text, size 0x4230 lma 0x80001a8
Loading section .rodata, size 0xa4c lma 0x80043e0
Start address 0x080041fe, load size 20004
Transfer rate: 14 KB/sec, 5001 bytes/write.
(gdb)
(gdb) break main
Breakpoint 1 at 0x80002d8: file src/main.rs, line 18.
(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, main () at src/main.rs:18
18 #[entry]
(gdb)
You can use standard GDB commands at this point.
$ cargo run --bin emb-rust
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `probe-run --chip STM32F407VGTx target/thumbv7em-none-eabi/debug/emb-rust`
flashing program ..
DONE
resetting device
Hello embedded Rust
^Cstack backtrace:
0: 0x08004008 - cortex_m::peripheral::syst::<impl cortex_m::peripheral::SYST>::has_wrapped
1: 0x08002686 - <stm32f4xx_hal::delay::Delay as embedded_hal::blocking::delay::DelayUs<u32>>::delay_us
2: 0x080025b4 - <stm32f4xx_hal::delay::Delay as embedded_hal::blocking::delay::DelayMs<u32>>::delay_ms
3: 0x080025f0 - <stm32f4xx_hal::delay::Delay as embedded_hal::blocking::delay::DelayMs<u16>>::delay_ms
4: 0x08000650 - emb_rust::__cortex_m_rt_main
5: 0x0800034e - main
6: 0x08004e88 - Reset
Disconnect the board from the computer, and attach the board to a power source. The application will be automatically copied from flash and start running.