My work-through1 of The Embedded Rust Book.
The key difference between what I've done in this repo and what is described in the The Embedded Rust Book is I've used my own framework for containerizing build environments to keep everything decoupled from my workstation machine and easily reproducible.
Some additional work has been done aside from working through the examples in the book. All of the info in this README applies to the additonal examples unless otherwise noted.
Additional examples include:
blinky: A minimal example of blinking LEDs.
-
nucleo-f767zi: Blips LEDs LD1, LD2, and LD3, based on the example in thestm32f7xx-halcrate since a current board crate is not available. -
stm32f3-disco: Blinks LEDs LD3 through LD10, based on the example in thestm32f3-discoveryboard crate.
uart: A minimal UART comms example of writing out "Hello World!".
stm32f3-disco: Writes "Hello World!" out via UART4 (PC10/PC11, TX/RX) at 0.5 Hz, based on the UART example in Section 2.3 Memory-mapped Registers of the book using the stm32f3xx-hal crate directly rather than through the board support crate.
This repo depends on the build-systems repo to provide its build environment. It is included as a submodule in the root of the repo. Clone this repo with submodules included recursively to pull in everything needed to build in a Docker container.
The issue with developing with tools like OpenOCD and gdb that use hardware ports on macOS is they can't be passed through to a Docker container as is possible with Linux. This means using a Mac requires OpenOCD and gdb be installed and run directly on the machine. Two easy workarounds for this are possible (if Homebrew and Anaconda are already installed). Both of these solutions worked fine when I worked through the book.
OpenOCD can be installed using Homebrew.
> brew install openocdMemfault has created an Anaconda package for installing gdb-multiarch on a macOS machine. See the Conda section of their blog post on installing gdb. The environment file recommended in the article is included in the root of the repo, so as long as Anaconda is already installed gdb-multiarch can be installed by creating a Conda environment from the root of the repo.
> conda env create -f environment.yml The Docker images provided by the build-systems submodule have the necessary environment configured to build the ARMv7-M (Cortex-M3) and ARMv7-EM (Cortex-M4F) examples in this repo.
To open a shell in a build environment container, run the shell script from the root of the repo with the details for the image to use.
> ./build-systems/scripts/shell.sh ORG_NAME:IMAGE_NAME:VERSIONYou should get a similar response to this confirming the input.
Open Shell in Docker Image
============================================================
Org: ORG_NAME
Image: IMAGE_NAME
Version: VERSION
root@ca5eda15a2f0:/#Notes, tips, and tricks.
If the $USER is not set in the container, cargo-generate will fail with the error,
Error: could not determine the current user, please set $USER.
A quick fix is to set the user in the container.
root@6106dcaa0b0c:/repo# export USER=auser
root@6106dcaa0b0c:/repo# cargo generate -n hardware-example --git https://github.com/rust-embedded/cortex-m-quickstart
Destination: /repo/hardware-example ...
project-name: hardware-example ...
Generating template ...
Moving generated files into: `/repo/hardware-example`...
Initializing a fresh Git repositoryAn odd warning is generated by QEMU when running the hello.rs example but it
doesn't seem to interfere with the simulation.
root@ca5eda15a2f0:/repo/qemu-example# cargo run --example hello --release
Compiling typenum v1.17.0
Compiling generic-array v0.14.7
Compiling generic-array v0.12.4
Compiling generic-array v0.13.3
Compiling as-slice v0.1.5
Compiling aligned v0.3.5
Compiling cortex-m v0.6.7
Compiling qemu-example v0.1.0 (/repo/qemu-example)
Finished `release` profile [optimized + debuginfo] target(s) in 1.51s
Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel target/thumbv7m-none-eabi/release/examples/hello`
Timer with period zero, disabling
Hello, world!To debug the applications in QEMU running in a Docker container:
- Run QEMU in a container to wait for a connection from
gdb. - Open a second terminal window, then open a second shell in the running container.
- Connect to the running instance of QEMU using
gdb.
The rust-analyzer extension seems to look for Cargo.toml files only in the
root of the VS Code project, so it has to be informed of the locations of the
files if they are elsewhere, it seems. This
stackoverflow answer worked - adding a
rust-analyzer.linkedProjects entry to the VS Code settings in the project
root.
"rust-analyzer.linkedProjects": [
"./examples/blinky/nucleo-f767zi/Cargo.toml",
"./examples/blinky/stm32f3-disco/Cargo.toml",
...
]Footnotes
-
The term "work-through" is what I've come up with for instances of my practice of working through examples, books, tutorials, etc., to keep up with the software industry and continuously improve my skills and knowledge. ↩