ESP32 with Rust

Since Embassy only support ESP32C3 and I only have old ESP32 lying around I have to use a different toolchain than last week. As last week with the Pico this time I want to get a Rust program installed on an ESP32. I did not use probe-rs as last time, but cargo espflash.

First we need to install some Rust prerequisites listed in the ESP Rust book. We need Rust obviously. Best to install via rustup and not your system package. Then some ESP specific things:

cargo install espup
# install toolchain
~/.cargo/bin/espup install
# source the environment variables needed
. ~/export-esp.sh
# install ldproxy
cargo install ldproxy
# install cargo-espflash (binstall if you can)
cargo install cargo-espflash

To get which chip you have cargo-espflash can help:

$ cargo espflash board-info

Returns for my old ESP32:

Chip type:         esp32 (revision v1.0)
Crystal frequency: 40 MHz
Flash size:        4MB
Features:          WiFi, BT, Dual Core, 240MHz, Coding Scheme None
MAC address:       b4:e6:2d:97:d2:79

Next we need an example. To generate one we generate a new project based on a template:

# install generate
cargo install cargo-generate
# use generate to get a minimal example with a working cargo.toml
cargo generate esp-rs/esp-template -n blinky
# I chose "esp32" as MCU; without advanced options

Plugin the ESP32 on any USB port. To have write permissions you may need to add your user to a group that is allowed to write. I described this in a previous blog post.

Then build and install:

cargo build
# flash using cargo-espflash
cargo espflash flash --monitor

The code should now run on the ESP32 and printing first "Hello world!" and then "Loop..." until Ctrl-C is pressed.

Now to the actual blinking (of an LED). The blue LED of my ESP-WROOM-32 is GPIO2. If your ESP32 doesn't have an LED you can connect one to a GPIO pin with a resistor (i.e. red LED and 330Ω) and connect the other side to ground. I used GPIO 23 for the example below because it is at the end of the ESP32.

Change the src/main.rs to:

#![no_std]
#![no_main]

use esp_backtrace as _;
use esp_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, Delay, IO};

#[entry]
fn main() -> ! {
    let peripherals = Peripherals::take();
    let system = peripherals.SYSTEM.split();

    let clocks = ClockControl::max(system.clock_control).freeze();
    let mut delay = Delay::new(&clocks);

    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
    // change to the GPIO you used, GPIO2 for onboard blue LED (if you have)
    let mut led = io.pins.gpio23.into_push_pull_output();

    loop {
        delay.delay_ms(500u32);
        led.toggle().unwrap();
    }
}

Using GPIO2 on an ESP-WROOM-32:

img1

and using an external LED with a resistor:

img2