Trying Rust on ESP32

Hi there!

I'm currently trying to get started with Rust on ESP32 controllers. In the past I've played around a little with Rust and long before I put together a few little projects with ESP32 controllers using the Arduino libraries.

The best resource to get started from what I've found is the esp-rs book.

Another nice hub for information is the awesome-esp-rust collection.

So far I've managed to install the pre-built esp rust fork & generate a playground from their template:

curl -LO https://raw.githubusercontent.com/esp-rs/rust-build/main/install-rust-toolchain.sh
chmod +x install-rust-toolchain.sh
./install-rust-toolchain.sh
source export-esp.sh
cargo install cargo-generate
cargo generate --git https://github.com/esp-rs/esp-idf-template cargo

After installing a few more dependencies I managed to have this playground run on an ESP32 board by clicking the "Run" link showing above the fn main() { line:

cargo install ldproxy
cargo install espflash
cargo install cargo-espflash
cargo install cargo-espmonitor
cd esp32-rust-playground
code .

Here I found a sample that pauses execution, and that actually still works in the environment provided by the current esp-rs/rust-build, unlike the code found here & here).

Next I found the watchdog process was unhappy with my code, which I resolved by copying code from this github issue.

So my playground now contains this code:

use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported

use embedded_hal::blocking::delay::DelayMs;
use esp_idf_hal::delay;

fn main() {
    // Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
    // or else some patches to the runtime implemented by esp-idf-sys might not link properly.
    esp_idf_sys::link_patches();

    unsafe {
        // Disable IDLE task WatchDogTask on this CPU.
        esp_idf_sys::esp_task_wdt_delete(esp_idf_sys::xTaskGetIdleTaskHandleForCPU(esp_idf_hal::cpu::core() as u32));

        // Enable WatchDogTask on the main (=this) task.
        esp_idf_sys::esp_task_wdt_add(esp_idf_sys::xTaskGetCurrentTaskHandle());
    };
    
    let mut delay = delay::Ets;

    let mut i: u128 = 0;
    loop {
        println!("loop pass #{i}");
        delay.delay_ms(100 as u32);
        
        // Feed WatchDogTask.
        unsafe {esp_idf_sys::esp_task_wdt_reset();}
        i=i+1;
    }   
}

Next tasks on my list:

  • connect to Wifi (should be easy, seen lot's of samples I can copy from)
  • get OTA to work (this is gonna be hard, found some issues but no sample code as of yet)
  • find an equivalent for millis() from the Arduino envrionment to tell the uptime of the board

The most active community talking about Rust on the ESP32 seems to be this matrix chat channel.

Looking at past topics concerning embedded development on Espriff boards on here doesn't make me too hopeful that I'll get helpful replies, but at least now I've collected & documented my thoughts / experiences so far for myself here :wink:

3 Likes

I also try to do some demos on the c3 device. The information I'm currently looking at is esp-rs and discovery

1 Like

I'm trying to learn Rust by programming a few ESP32 boards, currently the ESP32-C3. Here's my repo with some example code and links to various resources.

I'm not very good at Rust yet but I'd love to collaborate and learn. I'm trying to get all these peripherals working on the ESP32-C3:

  • Cloud

    • MQTT upload data
    • OTA
  • Peripherals

    • ADC
    • SPI
    • I2C
    • WIFI
    • GPIO
    • Interrupt
    • DMA
  • General

    • Unit tests
    • Multi-Threading
2 Likes

I've just found this link on the esp-rs matrix channel while searching for "OTA":
https://crates.io/crates/esp-ota

I will try to see if I can get this to work on one of my ESP32 boards :slight_smile:

My old playground stopped working, and it seems there have been some updates in the available tools. So I'll start over.

The ESP-RS Book, Installation Chapter says that Xtensa targets require the esp-rs/rust fork. If I read the Wikipedia article correctly, my ESP-WROOM-32 modules do feature Xtensa CPUs. The instructions to install the esp-rs/rust fork changed:

cargo install espup
rm -R ~/.rustup/toolchains/esp # delete old version
espup install
source ~/export-esp.sh
echo "source ~/export-esp.sh" >> ~/.profile # make it permanent
cargo install cargo-generate
cargo generate --git https://github.com/esp-rs/esp-idf-template cargo

The sample that counts in a loop with a 100ms delay now looks a bit different:

use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use esp_idf_hal::delay;

fn main() -> ! {
    // It is necessary to call this function once. Otherwise some patches to the runtime
    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
    esp_idf_sys::link_patches();

    // copied code snippets from https://github.com/esp-rs/esp-idf-hal/issues/124
    unsafe {
        // Disable IDLE task WatchDogTask on this CPU.
        esp_idf_sys::esp_task_wdt_delete(esp_idf_sys::xTaskGetIdleTaskHandleForCPU(esp_idf_hal::cpu::core() as u32));

        // Enable WatchDogTask on the main (=this) task.
        esp_idf_sys::esp_task_wdt_add(esp_idf_sys::xTaskGetCurrentTaskHandle());
    };

    let mut i: u128 = 0;
    loop {
        println!("loop pass #{i}");

        delay::Ets::delay_ms(100 as u32);

        // Feed WatchDogTask.
        unsafe {esp_idf_sys::esp_task_wdt_reset();}

        i=i+1;
    }
}

I've found a few esp32-rust projects that seem to have OTA already implemented, I'm gonna have a close look at those to see if I can copy some code from them or even fork one of those projects and adept it to my needs:

So I managed to get OTA working now :partying_face:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.