Awesome
stm32-blue-pill-rust
Rust for STM32 Blue Pill with Visual Studio Code.
Read the article: https://medium.com/@ly.lee/coding-the-stm32-blue-pill-with-rust-and-visual-studio-code-b21615d8a20
Based on:
-
Jorge Aparicio's Discovery book: https://japaric.github.io/discovery/
-
Jorge Aparicio's HAL for Blue Pill: https://japaric.github.io/stm32f103xx-hal/stm32f103xx_hal/
-
Jorge Aparicio's Cortex-M Quickstart: https://docs.rs/cortex-m-quickstart/0.2.7/cortex_m_quickstart/
-
Nerijus Arlauskas's Embedded Rust blog: http://nercury.github.io/rust/embedded/experiments/2018/04/29/rust-embedded-01-discovery-vl-flipping-bits.html
Connecting the STM32 Blue Pill to ST-Link V2 USB Debugger
<table> <thead> <td colspan="2"> <b> STM32 Blue Pill </b> </td> <td colspan="2"> <b> ST-Link V2 USB Debugger </b> </td> </thead> <tbody> <tr> <td> V3 </td><td> [Red] </td> <td> 3.3V </td><td> (Pin 8) </td> </tr> <tr> <td> IO </td><td> [Orange] </td> <td> SWDIO </td><td> (Pin 4) </td> </tr> <tr> <td> CLK </td><td> [Brown] </td> <td> SWDCLK </td><td> (Pin 2) </td> </tr> <tr> <td> GND </td><td> [Black] </td> <td> GND </td><td> (Pin 6) </td> </tr> </tbody> </table>Installation and Usage
Install Prerequisites
-
For Ubuntu only: Install required packages (
arm-none-eabi-gdb
is obsolete)sudo apt install pkg-config cmake libssl-dev zlib1g-dev gdb-multiarch curl git sudo ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb
Install ARM Cross-Compiler and Linker
-
For Windows:
-
Install ARM Cross-Compiler and Linker from the ARM Developer Website: <br> https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
-
Scroll down the page till you find <br>
Windows 32-bit File: gcc-arm-none-eabi-…-win32.exe
<br> ClickDownload
<br> -
Select the "Add path to environment variable" option at the last install step
-
In Windows Explorer, browse to <br>
C:\Program Files (x86)\GNU Tools Arm Embedded\7 2018-q2-update\bin
<br> (The7 2018-q2-update
part may be different for your installation) -
Copy the file
arm-none-eabi-ar.exe
toar.exe
<br> Thisar.exe
workaround is temporary until we find a fix for the Windows Rust build
-
-
For Ubuntu:
sudo apt install binutils-arm-none-eabi gcc-arm-none-eabi
Check ARM Cross-Compiler Installation
-
Open a new Windows or Ubuntu command prompt (not Windows Bash) and enter
arm-none-eabi-gcc -v
-
You should see something like
version 5.4.1 20160919 (release)
-
If you see no errors, close the command prompt.
-
If you see an error, update your PATH environment variable so that it includes the folder for the ARM ".exe" files.
Install OpenOCD For Debugging Blue Pill
-
For Windows:
-
Download OpenOCD (for debugging the Blue Pill) from the unofficial OpenOCD release website: <br> https://github.com/gnu-mcu-eclipse/openocd/releases <br> Look for
gnu-mcu-eclipse-openocd-…-win64.zip
-
Unzip the OpenOCD download and copy the OpenOCD files into
c:\openocd
such thatopencd.exe
is located in the folderc:\openocd\bin
-
-
For Ubuntu:
sudo apt install openocd
For Windows only: Install ST-Link USB Driver
-
For Windows only: Download the ST-Link USB driver from the ST-Link Driver Website (email registration required): <br> http://www.st.com/en/embedded-software/stsw-link009.html
-
Scroll down and click the
Get Software
button -
Unzip the ST-Link download. Double-click the
dpinst_amd64.exe
installer.
For Windows only: Install Build Tools
-
For Windows only: Install
Build Tools for Visual Studio 2017
(needed byrustup
) from <br> https://aka.ms/buildtools -
Under "Workloads", select
Visual C++ Build Tools
. <br> Warning: The download is 1.1 GB and you need 4.8 GB of free disk space.
Install rustup
-
Install
rustup
(the Rust toolchain installer) from <br> https://rustup.rs/ -
If you see a message about
Windows Defender SmartScreen
, clickMore Info
andRun Anyway
. -
Select the default installation option when prompted. <br> For Ubuntu only: Log out and log in again to update the
PATH
-
Switch to the nightly Rust toolchain (instead of stable or beta). Open a new Windows or Ubuntu command prompt (not Windows Bash) and enter:
rustup default nightly
-
Install the
rust-std
componentthumbv7m-none-eabi
to cross-compile for ARM Cortex-M3 (the processor used in the Blue Pill):rustup target add thumbv7m-none-eabi
Download stm32-blue-pill-rust
Source Files
-
Download the source files from GitHub: <br> (You may install git from https://gitforwindows.org)
git clone https://github.com/lupyuen/stm32-blue-pill-rust.git cd stm32-blue-pill-rust
Install Visual Studio Code
-
Install Visual Studio Code from <br> https://code.visualstudio.com/download
-
Launch Visual Studio Code and install the following extensions (just click the links below followed by the
Install
button andOpen Visual Studio Code
):-
Better TOML (bungcip) <br> https://marketplace.visualstudio.com/items?itemName=bungcip.better-toml
-
C/C++ (Microsoft) <br> https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools
-
Native Debug (WebFreak) <br> https://marketplace.visualstudio.com/items?itemName=webfreak.debug
-
Rust (kalitaalexey) <br> https://marketplace.visualstudio.com/items?itemName=kalitaalexey.vscode-rust
-
Rust (rls) (rust-lang) <br> https://marketplace.visualstudio.com/items?itemName=rust-lang.rust
-
-
In Visual Studio Code, click
Install
when prompted to install the above extensions -
Restart Visual Studio Code
-
Click
File → Open Workspace
-
Browse to the
stm32-blue-pill-rust
folder and selectworkspace.code-workspace
-
In the
Explorer → Workspace
pane at left, browse to the source foldersrc
and select the Rust source filemain.rs
-
When prompted, install the Rust Language Service (RLS), which provides Autocomplete and "Go To Definition" features for Rust.
Compiling the Rust program in Visual Studio Code
-
In Visual Studio Code, click
Tasks → Run
Build Task. -
Wait a while for the Rust program to be compiled.
-
Check the log in the Terminal window at the bottom of the Visual Studio Code screen.
-
When you see
Finished released [optimized + debuginfo] target(s)
, that means the Rust program has been compiled successfully. -
We'll proceed to the next step to run the program.
-
But if you see an error, you'll have to fix the error and recompile the program. Just mouse over the filename and line number in the log, and press Ctrl-click to jump to the offending line of code.
Running the Rust program in Visual Studio Code
-
Click
Tasks → Run Task
-
Select
Connect To STM32 Blue Pill
-
Check the messages from OpenOCD in the Terminal window at the bottom of Visual Studio Code.
-
When you see
Listening on port 3333 for gdb connections
, our program is ready to be started on the Blue Pill. -
Click
Debug → Start Debugging
-
Note: There is a bug in the debugger for Ubuntu: gdb stops with an error. To be fixed. Meanwhile you can use the command-line debugger in Ubuntu.
Building from the Command Line
-
Build the application:
cargo clean cargo check --release cargo build --release
-
You should see something like:
Finished release [optimized + debuginfo] target(s) in 1.43s
-
Sanity check for the built application
arm-none-eabi-readelf -h target/thumbv7m-none-eabi/release/stm32-blue-pill-rust
-
You should see something like:
ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX 1. System V ABI Version: 0 Type: EXEC (Executable file) Machine: ARM Version: 0x1 Entry point address: 0x8000cfb Start of program headers: 52 (bytes into file) Start of section headers: 258948 (bytes into file) Flags: 0x5000200, Version5 EABI, soft-float ABI Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 3 Size of section headers: 40 (bytes) Number of section headers: 21 Section header string table index: 20
Debugging from the Command Line
-
Launch OpenOCD on a terminal. Scripts are located at
/usr/share/openocd/scripts
-
For Windows:
c:\openocd\bin\openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
-
For Ubuntu:
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
-
-
You should see something like:
GNU MCU Eclipse 64-bits Open On-Chip Debugger 0.10.0+dev-00487-gaf359c18 (2018-05-12-19:30) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html WARNING: interface/stlink-v2.cfg is deprecated, please switch to interface/stlink.cfg 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: 1000 kHz adapter_nsrst_delay: 100 none separate Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : Unable to match requested speed 1000 kHz, using 950 kHz Info : clock speed 950 kHz Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748 Info : using stlink api v2 Info : Target voltage: 3.225397 Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints Info : Listening on port 3333 for gdb connections
-
Start a debug session in another command window:
arm-none-eabi-gdb -x loader.gdb target/thumbv7m-none-eabi/release/stm32-blue-pill-rust
-
Common GDB commands:
-
step:
Execute the current source line, step into functions if present. Same as the step into command in Visual Studio Code. -
next:
Execute the current source line, don't step into functions. Same as the step over command in Visual Studio Code. -
where:
Show stack trace. -
where full:
Show stack trace with local variables.
More commands: https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf
-
Visual Studio Code Configuration
Customisation of the Visual Studio Code UI was done through the following files:
Task configuration - .vscode/tasks.json
Defines the following tasks:
-
Connect: Launches OpenOCD. Uses different commands for Ubuntu and Windows (
opencd
vsc:\opencd\bin\opencd
). -
Build: Executes
cargo build --release
. Configured as the default build task. -
Remove: Executes
cargo clean
-
Check: Executes
cargo check --release
Debugger configuration - .vscode/launch.json
-
Launches the following command when the debugger is started:
arm-none-eabi-gdb -x loader.gdb target/thumbv7m-none-eabi/release/stm32-blue-pill-rust
-
This command causes
gdb
to execute theloader.gdb
script at the start of debugging. -
The mandatory parameter
target/thumbv7m-none-eabi/release/stm32-blue-pill-rust
is redundant. The target is specified again inloader.gdb.
Debugger script - loader.gdb
-
This is the GDB script for loading and running programs in STM32 Blue Pill.
-
Called when debugging begins. Defined in
.vscode/launch.json
-
This file used to be
.gdbinit,
which could not be autoloaded due to autoloading security in GDB. -
Set architecture to ARM 32-bit. Needed for
gdb-multiarch
on Ubuntu. -
Send GDB commands to OpenOCD, which listens on port 3333. Extend the timeout.
-
Disable all messages.
-
Enable ARM semihosting to show debug console output in OpenOCD console.
-
Reset the device.
-
Specify
target/thumbv7m-none-eabi/release/stm32-blue-pill-rust
as the target program to be debugged. Must be specified here (not the command line) because the VSCode debugger will fail without it. -
Load the program into device memory.
-
Set breakpoint at the
main()
function. -
Run the program and stop at the
main()
function. -
Remove the breakpoint at the
main()
function. -
Step into the first line of the
main()
function. Else gdb will complain aboutentry macros
file missing. -
TODO: Write program to flash memory so that it becomes permanent.
How This Rust Crate Was Created
-
Install Cargo
clone
andadd
subcommands:cargo install cargo-clone cargo install cargo-edit
-
Clone the quickstart crate
cargo clone cortex-m-quickstart && cd $_
-
Change the crate name, author and version in Cargo.toml:
[package] authors = ["Jorge Aparicio <jorge@japaric.io>"] name = "demo" version = "0.1.0"
-
Specify the memory layout of the target device. Since board support crate for stm32f103xx provides this file, we remove both the memory.x and build.rs files.
rm memory.x build.rs
-
Set a default build target
cat >>.cargo/config <<'EOF' [build] target = "thumbv7m-none-eabi" EOF
-
Depend on a HAL implementation.
cargo add https://github.com/japaric/stm32f103xx cargo add https://github.com/japaric/stm32f103xx-hal
-
Copy the
delay
sample application from https://github.com/japaric/stm32f103xx-hal intosrc\main.rs
rm -r src/* && cp ../stm32f103xx_hal/examples/delay.rs src/main.rs
References
Windows Setup for Embedded Rust: https://japaric.github.io/discovery/03-setup/windows.html
Peripheral I/O with Embedded HAL: http://blog.japaric.io/brave-new-io/
Embedded Rust Blog: http://blog.japaric.io/
Embedded Rust Book (work in progress): https://github.com/rust-lang-nursery/embedded-wg/tree/master/books/embedded-rust-book
Rust RTFM Docs and Book (work in progress): https://github.com/japaric/cortex-m-rtfm/tree/gh-pages
Awesome Embedded Rust (covers other hardware platforms): https://github.com/rust-embedded/awesome-embedded-rust
Details of rustup
: https://github.com/rust-lang-nursery/rustup.rs
STM32F103C8 Website: https://www.st.com/en/microcontrollers/stm32f103c8.html
STM32F103C8 Datasheet: https://www.st.com/resource/en/datasheet/stm32f103c8.pdf
STM32F103C8 Reference Manual: https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf
STM32F103C8 Flash Programming: https://www.st.com/content/ccc/resource/technical/document/programming_manual/10/98/e8/d4/2b/51/4b/f5/CD00283419.pdf/files/CD00283419.pdf/jcr:content/translations/en.CD00283419.pdf
STM32F103C8 ARM Cortex M3 Programming: https://www.st.com/content/ccc/resource/technical/document/programming_manual/5b/ca/8d/83/56/7f/40/08/CD00228163.pdf/files/CD00228163.pdf/jcr:content/translations/en.CD00228163.pdf
License
Licensed under either of
-
Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
-
MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.