This tutorial details the setup of a Rust development environment on the ESP32C3 RISC-V microcontroller in under an hour, enabling the use of the Rust Standard Library ("std") as well as the MCU's Wi-Fi and Bluetooth capabilities.
CC-BY-SA-4.0 License
Today, I'll be showing you how to use the Rust programming language on a Rust ESP board, a recent embedded platform packed with Wi-Fi and Bluetooth capabilities.
We won't go through the details of no_std
vs std
development, just know that the latter allows us to use full Wi-Fi and Bluetooth capabilities along with the actual entire Rust Standard Library with ease which is usually NOT straightforward but hey, this is 2023, enjoy!
The original article and associated examples are available in my Rust ESP Quickstart GitLab repository.
If you are already running Linux and just want to flash your ESP board with a fully configured Rust "Hello, World!" project, see the script/setup.sh
script, it should help you get started in no time. Be aware, though, that it has been made for a freshly installed 22.10 Ubuntu distribution and is untested on any other platform yet (i.e. use it at your own risks). On the other hand, please read on if you intend to walk the learning path instead.
[[TOC]]
Here's everything we are going to need during our little adventure:
We'll be using a live 22.10 Ubuntu distribution so that:
One drawback of this solution is that each reboot will wipe the environment but feel free to actually install linux if persistence across said reboots is required.
usb-creator-gtk
if running Linux or Win32DiskImager
if running Windowsusb-creator-gtk
on LinuxOpen a terminal (the default shortcut is Ctrl
+Alt
+T
on Ubuntu) and run those commands:
sudo apt update
sudo apt install --yes usb-creator-gtk
Win32DiskImager
on WindowsDownload the installer from the project's page and run it.
In both cases, we will need to select the ISO image we want to flash and the device we want to use then click the Write or Make startup disk button. The process should complete within a few minutes.
Let's ask ChatGPT how to do that:
Thank you ChatGPT ! Finally, hit that Try Ubuntu button to be greeted with a GNOME desktop.
The next steps require internet access so connect to a Wi-Fi (see the top-right corner menu) or wired network if you want to go old-school.
Here, we are going to make heavy use of a terminal. On Ubuntu, you can open one by pressing Ctrl
+Alt
+T
. You might want to copy/paste the following commands to avoid typos but suit yourself!
We need a few more packages than Ubuntu provides by default. Please bear with the trauma of installing them:
sudo add-apt-repository --yes universe
sudo apt install --yes clang curl git libssl-dev libudev-dev=251.4-1ubuntu7 pkg-config python3-pip
(installing version 251.4-1ubuntu7.1
of libudev-dev
induces a crash on my machine so I'm using version 251.4-1ubuntu7
instead)
We'll now use Rustup to install both Rust and Cargo (Rust's package manager):
curl --proto '=https' --tlsv1.2 --fail --show-error --silent https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
rustup toolchain install nightly --component rust-src
Moreover, we need a few additional Cargo modules:
espflash
to flash the device (see espflash)ldproxy
to forward linker arguments (see ldproxy)cargo-generate
to generate projects according to a template (see cargo-generate)cargo install espflash ldproxy cargo-generate
The awesome ESP IDF Template will save us the pain of configuring a fully functional project ourselves, use it like so:
cargo generate --git https://github.com/esp-rs/esp-idf-template cargo
During the process, you will be asked a few things:
You might like "Permission Denied" errors. If not, those commands will create a udev rule to avoid that when accessing our board through USB:
echo "SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"303a\", ATTRS{idProduct}==\"1001\", MODE=\"0660\", GROUP=\"plugdev\"" | sudo tee /etc/udev/rules.d/99-esp-rust-board.rules > /dev/null
sudo udevadm control --reload-rules && sudo udevadm trigger
Now make use of that USB cable and connect the board to your computer, then run this simple yet elegant command:
cargo run
If everything goes smoothly, Cargo should build the project, flash it on the MCU and finally run it, meaning that a line reading "Hello, World!" should be displayed in the terminal. Hit Ctrl
+R
to restart the program (not very useful at that point but it might be later) or Ctrl
+C
to quit monitoring it.
Congratulations, you are officially programming Rust on your ESP board !
We could configure Vim, Emacs or any other terminal-based IDE, but the low-friction solution is to use Visual Studio Code with the appropriate extensions. This way, we are only a few clicks away from syntax highlighting, code completion and much more.
It is the exact same as VSCode but without telemetry/tracking stuff, plus it uses MIT license (see the official website). Install and run it like so:
snap install codium --classic
codium
An Open Folder button should be visible in the explorer tab on the left. Click it to add our project to the workspace. We are now able to edit source code way more handily than in a terminal.
Go to the extensions tab and type "rust analyzer" in the search bar, then click the install button ("Rust language support for Visual Studio Code"). That's it! You can find more information about it on the official website. The Even Better TOML and crates extensions might also be of interest to you.
The examples folder of this repository contains three projects:
WIFI_SSID
and WIFI_PWD
environment variables at the bottom of .cargo/config.toml
As a kid, I used to boot my sister's laptop from a live 8.04 "Hardy Heron" Ubuntu CD (you could order one for free back then!) to bypass her password protection. This way, no one ever knew what I was doing (meerely looking for cheat codes for the games I used to play at the time ). Today, I still believe this technique is of great value to anyone wishing to try something out without breaking anything.
Growing up, I then had the pleasure to learn how embedded development can sometimes be a pain: messy setup, weird and abstruse error messages... But hopefully, it has been less than an hour since you began reading this article and you are now able to use a modern language with std
support on a recent Wi-Fi-enabled microcontroller. Ain't that marvelous ?
I hope you enjoyed it as much as I do, especially when considering the tremendous amount of work that was needed to make this so easy for us.
Cheers!
no_std
Hardware Abstraction Layerstd
Hardware Abstraction Layeresp-template
: no_std
project templateesp-idf-template
: std
-enabled project templateembedded-svc
: service-related traitsesp-idf-svc
: embedded-svc
implementationshared-bus
: share I2C/SPI/ADC buses between peripherals (namely: sensors)shtcx
: access the SHTC3 embedded temperature+humidity I2C sensoricm42670
: access the ICM42670 embedded temperature+accelerometer+gyroscope I2C sensorMy name is Cyril Marpaud, I'm an embedded systems freelance engineer and a Rust enthusiast I have nearly 10 years experience and am currently living in Lyon (France).