Rust on Espressif chips - 15-07-2022

This is the next quarterly update of esp-rs effort, detailing the progress over Q2 2022.

Standard library

esp-rs/rust#117, failure to list file directories, has been fixed. This issue was two in one; the first applied to any filesystem, used through the libc API. The definition of the dirent structure was incorrect in esp-idf, this int definition should have been a ino_t definition. The size difference between the two types meant that the name ended up with a null terminator at the beginning, hence no output would be printed when listing a directory. The second part was specific to SPIFFS (a flash-based filesystem), listing a directory would emit an internal error number, which was interpreted as a real error, but in reality, was just a signal that the end of the listing had been reached. More details here.

esp-hal & bare-metal support

esp-hal has seen much development in the last quarter.

  • Add a serial driver for the USB-SERIAL-JTAG peripheral - esp-hal#56
  • Add RMT output support, with a implementation for smart-leds-rs - esp-hal#53
  • Use fugit time types in the HALs public API - esp-hal#64
  • Add support for the SYSTIMER on the esp32c3, esp32s2 & esp32s3 - esp-hal#76
  • Add ClockConfig to start to support customizing the chip clocks - esp-hal#77
  • Add support for most embedded-hal alpha traits - esp-hal#82
  • Add basic EFUSE reading support - esp-hal#85
  • Add DAC peripheral support - esp-hal#92
  • Add ADC peripheral support - esp-hal#97, esp-hal#98
  • Add support for using the second core on the esp32 & esp32s3 - esp-hal#96

WiFi & Bluetooth

esp-wifi has been moved to the esp-rs organization. We now also have support for WiFi on the Xtensa based esp32 which was implemented in esp-rs/esp-wifi#4. The radios inside the esp32 & esp32c3 also support Bluetooth Low Energy, which has now been implemented for the esp32c3 in esp-rs/esp-wifi#30 & the esp32 in esp-rs/esp-wifi#34, which is very exciting! esp-wifi is still experimental, so do expect some issues but it's in a good enough state that bjoernQ rewrote his temperature logging project using bare metal Rust!

Async support

On top of the PR's listed above, we have begun working on async support too! The go-to embedded executor right now is embassy, which only supported ARM until we recently added support for RISC-V in embassy#804 & support for Xtensa in embassy#805. The next step is to add an embassy::time::Driver implementation inside esp-hal after which we could create the most basic embassy demo, running on an esp32c3! What's nice about this is you get power savings for free, as soon as there are no other tasks or interrupts to process the chip goes to sleep until the next wake-up.

static EXECUTOR: Forever<Executor> = Forever::new();

#[riscv_rt::entry]
fn main() -> ! {
    let p = esp32c3_hal::embassy::init();

    let executor = EXECUTOR.put(Executor::new());
    executor.run(|spawner| {
        spawner.spawn(run1()).ok();
        spawner.spawn(run2()).ok();
    });

    loop {}
}

#[embassy::task]
async fn run1() {
    loop {
        esp_println::println!("Hello world from embassy on an esp32c3!");
        Timer::after(Duration::from_millis(1000)).await;
    }
}

#[embassy::task]
async fn run2() {
    loop {
        esp_println::println!("Bing!");
        Timer::after(Duration::from_millis(3000)).await;
    }
}

Which results in the following output:

Async support is not merged yet, but hopefully by next quarter we have something usable.

Tooling

espflash

In the last quarter we released versions 1.4.0, 1.4.1, 1.5.0, 1.5.1 and 1.6 of espflash which includes these changes:

  • Release artifacts built for additional targets, installable via cargo-binstall
  • Update the --merge option of the save-image subcommand to behave in a more expected way - esp-rs/espflash#160
  • Fixes a bug when passing multiple features, causing them to be improperly processed - esp-rs/espflash#162
  • Fix a bug where the RTC watchdog timer was not disabled on reset when using USB Serial JTAG, resulting in flashing failures - esp-rs/espflash#169
  • Add a partition-table subcommand that allows conversion between CSV/binary and viewing of partition tables on the command-line - esp-rs/espflash#172
  • Add support for flashing from WSL2 (no support for USB Serial JTAG) - esp-rs/espflash#179
  • Detect the bootloader and partition table from ESP-IDF when able - esp-rs/espflash#186
  • Add write-bin-to-flash subcommand - esp-rs/espflash#194
  • Add support for flashing the ESP32-C2 (aka ESP8684) - esp-rs/espflash#204

probe-rs

@noppej has been doing some fantastic work improving RISC-V support in probe-rs, the first big PR has already been merged, and part two is in review. These changes are huge, making debugging & producing usable stack traces viable on the RISC-V platform, which is handy for the esp32c-series which are all RISC-V based. I hope by the end of the year we would have some basic support for Xtensa too, but there is quite a bit of work to do there.

wokwi-server

wokwi is an online simulator for IoT projects, it supports many chips including most Espressif ones, the esp32, esp32s2 & esp32c3. By default, Wokwi provides an Arduino-like IDE in the browser which handles compilation and then runs the program in the browser simulator. What's cool is that Wokwi also exposes a GDB stub that can be used to debug applications, a task that can be very tricky to set up on real hardware.

Rust support (compilation in the browser) is ongoing but not ready for general use just yet, however, there is another way to use Wokwi for Rust development. Introducing wokwi-server, a way to build an application locally and then run it in the browser - no hardware required! See the cargo runner section of the README for details. Once set up, a cargo run invocation is all you need.

esp-backtrace, esp-println & esp-alloc

esp-println provides print! & println! macros for all Espressif chips currently supported, as well as a log::Log implementation too. It is a standalone crate with no dependencies (uses the ROM functions burned into the chip at the factory). esp-backtrace is a crate for generating backtraces on the chip which supports all the printing methods esp-println does. We currently have support for generating Xtensa & RISC-V backtraces which cover all Espressif chips. We also created esp-alloc which provides a bare metal allocator for all Espressif chips.

Devcontainer support

Both the esp-idf-template & the esp-template repositories now have cargo-generate options to configure Devcontainers. It's as simple as filling in the options when cloning the template with cargo-generate and you can have a functioning esp rust environment immediately, with all the tooling ready to go!

esp rust board

The esp rust board is now available for purchase! You can find purchase links on the Espressif website, it is listed as ESP32-C3-DevKit-RUST-1. Unfortunately, it sold out pretty quickly but the next batch should be available around mid-August.

Ferrous systems training

Tickets to the Ferrous training based on the esp32c3 are now available too, check out the options here. Booking the training includes an ESP32-C3-DevKit-RUST-1 board as part of the package so no need to worry about acquiring one yourself.

What's next?

Continue the rapid progress on the bare metal multi-chip HAL, esp-hal, including the new async effort. Improve the stability of esp-wifi. Continue support of our Standard library port, esp-idf version 5.0 is nearly here and has some breaking changes that we'll need to handle in libc and our esp-idf crates.

As a final note, we are seeing a big influx of community pull requests, which is great to see! Thank you to all those who have contributed so far! :)