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
STM32 Blue Pill | ST-Link V2 USB Debugger | ||
V3 | [Red] | 3.3V | (Pin 8) |
IO | [Orange] | SWDIO | (Pin 4) |
CLK | [Brown] | SWDCLK | (Pin 2) |
GND | [Black] | GND | (Pin 6) |
-
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
-
For Windows:
-
Install ARM Cross-Compiler and Linker from the ARM Developer Website:
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -
Scroll down the page till you find
Windows 32-bit File: gcc-arm-none-eabi-…-win32.exe
ClickDownload
-
Select the "Add path to environment variable" option at the last install step
-
In Windows Explorer, browse to
C:\Program Files (x86)\GNU Tools Arm Embedded\7 2018-q2-update\bin
(The7 2018-q2-update
part may be different for your installation) -
Copy the file
arm-none-eabi-ar.exe
toar.exe
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
-
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.
-
For Windows:
-
Download OpenOCD (for debugging the Blue Pill) from the unofficial OpenOCD release website:
https://github.com/gnu-mcu-eclipse/openocd/releases
Look forgnu-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: Download the ST-Link USB driver from the ST-Link Driver Website (email registration required):
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 Visual Studio 2017
(needed byrustup
) from
https://aka.ms/buildtools -
Under "Workloads", select
Visual C++ Build Tools
.
Warning: The download is 1.1 GB and you need 4.8 GB of free disk space.
-
Install
rustup
(the Rust toolchain installer) from
https://rustup.rs/ -
If you see a message about
Windows Defender SmartScreen
, clickMore Info
andRun Anyway
. -
Select the default installation option when prompted.
For Ubuntu only: Log out and log in again to update thePATH
-
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 the source files from GitHub:
(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 from
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)
https://marketplace.visualstudio.com/items?itemName=bungcip.better-toml -
C/C++ (Microsoft)
https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools -
Native Debug (WebFreak)
https://marketplace.visualstudio.com/items?itemName=webfreak.debug -
Rust (kalitaalexey)
https://marketplace.visualstudio.com/items?itemName=kalitaalexey.vscode-rust -
Rust (rls) (rust-lang)
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.
-
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.
-
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.
-
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
-
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
-
Customisation of the Visual Studio Code UI was done through the following files:
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
-
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.
-
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.
-
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
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
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.
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.