Quick Start

Before diving into the theory and concepts of how everything works, let's jump straight into action. Use this simple code to turn on the onboard LED of the ESP32 DevKit.

ESP HAL is "no_std Hardware Abstraction Layers for ESP32 microcontrollers"

Setup project

To start the project, use the esp-generate command. Run the following:

esp-generate --chip esp32 blinky

This will open a screen asking you to select options. For now, we dont need to select any options. Just save it by pressing "s" in the keyboard.

Next, navigate to the project folder:

cd blinky

Open the src/bin/main.rs file. It will contain a simple "Hello, World" code. We will modify this code to blink an LED on the board.

Blinking Code

This code creates a blinking effect by toggling an LED connected to a GPIO pin between high and low states.

Import Required Module

Additional import we need to set the LED as output pin

#![allow(unused)]
fn main() {
use esp_hal::gpio::{Io, Level, Output};
}

Initialize ESP HAL peripherals

This code is already generated by the template. You have to change the "_peripherals" variable name to "peripherals".

#![allow(unused)]
fn main() {
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
}

Setup Output

Then lets set the LED GPIO pin "GPIO2" as an output pin with an initial state "High"(LED is turned on). The GPIO2 is the pin for the onboard LED.

#![allow(unused)]
fn main() {
let mut led = Output::new(peripherals.GPIO2, Level::High, OutputConfig::default());
}

Helper function for delay

Let's write a small function to introduce a blocking delay that pauses execution for a specified duration.

#![allow(unused)]
fn main() {
fn blocking_delay(duration: Duration) {
    let delay_start = Instant::now();
    while delay_start.elapsed() < duration {}
}
}

Blinking Loop

Create a loop to toggle the LED state(between High and Low).

#![allow(unused)]
fn main() {
loop {
    led.toggle();
    blocking_delay(Duration::from_millis(500));
}
}

The full code

#![no_std]
#![no_main]

use esp_hal::clock::CpuClock;
use esp_hal::gpio::{Level, Output, OutputConfig};
use esp_hal::main;
use esp_hal::time::{Duration, Instant};

#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
    loop {}
}

#[main]
fn main() -> ! {
    // generator version: 0.3.1

    let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
    let peripherals = esp_hal::init(config);

    let mut led = Output::new(peripherals.GPIO2, Level::High, OutputConfig::default());

    loop {
        led.toggle();
        blocking_delay(Duration::from_millis(500));
    }
}

fn blocking_delay(duration: Duration) {
    let delay_start = Instant::now();
    while delay_start.elapsed() < duration {}
}

Flash - Run Rust Run

All that's left is to flash the code onto our device and watch it go! The onboard LED should start blinking.

Run the following command from your project folder:

#![allow(unused)]
fn main() {
cargo run
}

To run in release mode

#![allow(unused)]
fn main() {
cargo run --release
}