### Build and Flash Example with cargo-espflash Source: https://github.com/esp-rs/esp-idf-hal/blob/master/README.md This command demonstrates how to build and flash an example (ledc_simple) to an ESP32-C3 microcontroller using cargo-espflash. Adjust the MCU and target for different chips. ```sh $ MCU=esp32c3 cargo espflash flash --target riscv32imc-esp-espidf --example ledc_simple --monitor ``` -------------------------------- ### SPI Bus and Device Communication Example Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Demonstrates initializing an SPI bus driver and then a specific SPI device with custom configurations for baudrate and data mode. Includes examples of data transfer, write-only operations, and multi-operation transactions. ```rust use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::spi::{SpiDriver, SpiDeviceDriver, SpiDriverConfig, config}; use esp_idf_hal::units::*; fn main() -> anyhow::Result<()> { let peripherals = Peripherals::take()?; // Create SPI bus driver let spi_driver = SpiDriver::new::( peripherals.spi2, peripherals.pins.gpio15, // SCLK peripherals.pins.gpio17, // SDO (MOSI) Some(peripherals.pins.gpio16), // SDI (MISO) &SpiDriverConfig::new(), )?; // Create device with specific configuration let device_config = config::Config::new() .baudrate(26.MHz().into()) .data_mode(config::MODE_0); let mut device = SpiDeviceDriver::new( &spi_driver, Some(peripherals.pins.gpio18), // CS pin &device_config, )?; // Transfer data (simultaneous read/write) let write_buf = [0xDE, 0xAD, 0xBE, 0xEF]; let mut read_buf = [0u8; 4]; device.transfer(&mut read_buf, &write_buf)?; println!("Wrote {:x?}, read {:x?}", write_buf, read_buf); // Write-only operation device.write(&[0x01, 0x02, 0x03])?; // Multiple operations in a single transaction use esp_idf_hal::spi::Operation; let mut rx_buf = [0u8; 8]; device.transaction(&mut [ Operation::Write(&[0xAA, 0xBB]), Operation::Read(&mut rx_buf), ])?; Ok(()) } ``` -------------------------------- ### I2C Bus Configuration and Data Transfer Example Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Shows how to configure an I2C driver for master mode with a specified baudrate and enable internal pull-up resistors. Demonstrates writing data, reading data, and performing combined write-read operations, as well as using the transaction API for multiple operations. ```rust use esp_idf_hal::i2c::{I2cDriver, I2cConfig}; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::units::*; use esp_idf_hal::delay::BLOCK; fn main() -> anyhow::Result<()> { let peripherals = Peripherals::take()?; // Configure I2C with 400 kHz clock let config = I2cConfig::new() .baudrate(400.kHz().into()) .sda_enable_pullup(true) .scl_enable_pullup(true); let mut i2c = I2cDriver::new( peripherals.i2c0, peripherals.pins.gpio21, // SDA peripherals.pins.gpio22, // SCL &config, )?; let device_addr = 0x3C; // Example: SSD1306 OLED display // Write data to device i2c.write(device_addr, &[0x00, 0xAE], BLOCK)?; // Read data from device let mut read_buf = [0u8; 2]; i2c.read(device_addr, &mut read_buf, BLOCK)?; // Write then read (combined transaction) let reg_addr = [0x00]; // Register address let mut data = [0u8; 4]; i2c.write_read(device_addr, ®_addr, &mut data, BLOCK)?; // Multiple operations using transaction API use embedded_hal::i2c::Operation; let mut ops_buf = [0u8; 8]; i2c.transaction(device_addr, &mut [ Operation::Write(&[0x40]), // Set data mode Operation::Read(&mut ops_buf), ], BLOCK)?; Ok(()) } ``` -------------------------------- ### Configure GPIO Pins for Input/Output Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Demonstrates configuring GPIO pins for digital input and output operations, including pull-up resistors and basic control logic. Ensure peripherals are taken before use. ```rust use esp_idf_hal::gpio::{PinDriver, Pull, Level, InterruptType}; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::delay::FreeRtos; fn main() -> anyhow::Result<()> { let peripherals = Peripherals::take()?; // Configure GPIO4 as output for LED control let mut led = PinDriver::output(peripherals.pins.gpio4)?; // Configure GPIO5 as input with pull-up resistor for button let button = PinDriver::input(peripherals.pins.gpio5, Pull::Up)?; loop { // Read button state and control LED if button.is_low() { led.set_high()?; } else { led.set_low()?; } // Toggle LED led.toggle()?; FreeRtos::delay_ms(500); } } ``` -------------------------------- ### Configure and Use UART Driver Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Demonstrates configuring UART with custom baud rate, data bits, parity, and stop bits. Shows writing data using `fmt::Write` and raw bytes, reading with a timeout, and splitting into TX/RX drivers. ```rust use esp_idf_hal::uart::{UartDriver, UartConfig}; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::units::*; use esp_idf_hal::gpio::AnyIOPin; use esp_idf_hal::delay::BLOCK; use std::fmt::Write; fn main() -> anyhow::Result<()> { let peripherals = Peripherals::take()?; // Configure UART with 115200 baud, 8N1 let config = UartConfig::new() .baudrate(115_200.Hz().into()) .data_bits(esp_idf_hal::uart::config::DataBits::DataBits8) .parity_none() .stop_bits(esp_idf_hal::uart::config::StopBits::STOP1); let mut uart = UartDriver::new( peripherals.uart1, peripherals.pins.gpio1, // TX peripherals.pins.gpio3, // RX Option::::None, // CTS (optional) Option::::None, // RTS (optional) &config, )?; // Write data using fmt::Write trait writeln!(uart, "Hello from ESP32!")?; // Write raw bytes uart.write(b"Raw bytes\n")?; // Read data with timeout let mut buf = [0u8; 64]; match uart.read(&mut buf, BLOCK) { Ok(len) => println!("Received {} bytes: {:?}", len, &buf[..len]), Err(e) => println!("Read error: {:?}", e), } // Split into separate TX and RX drivers let (tx, rx) = uart.split(); // Now TX and RX can be used independently // tx.write(b"From TX")?; // rx.read(&mut buf, BLOCK)?; // Wait for transmission to complete uart.wait_tx_done(BLOCK)?; Ok(()) } ``` -------------------------------- ### Configure and Use LEDC/PWM Driver Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Demonstrates configuring a PWM timer and channel, setting duty cycles, fading to target values over time or steps, and using the `embedded-hal` `SetDutyCycle` trait. ```rust use esp_idf_hal::ledc::{LedcDriver, LedcTimerDriver, config::TimerConfig}; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::units::*; fn main() -> anyhow::Result<()> { let peripherals = Peripherals::take()?; // Configure timer with 25 kHz frequency let timer_config = TimerConfig::new().frequency(25.kHz().into()); let timer = LedcTimerDriver::new( peripherals.ledc.timer0, &timer_config, )?; // Create PWM channel on GPIO1 let mut pwm = LedcDriver::new( peripherals.ledc.channel0, timer, peripherals.pins.gpio1, )?; // Set duty cycle to 75% let max_duty = pwm.get_max_duty(); pwm.set_duty(max_duty * 3 / 4)?; // Fade to target duty over time pwm.fade_with_time(max_duty / 2, 1000, true)?; // 50% duty over 1 second, blocking // Fade using steps pwm.fade_with_step( max_duty, // target duty 10, // step size 50, // step time in ms false, // non-blocking )?; // Disable PWM output pwm.disable()?; // Re-enable with previous duty cycle pwm.enable()?; // Use embedded-hal trait use embedded_hal::pwm::SetDutyCycle; pwm.set_duty_cycle_percent(50)?; Ok(()) } ``` -------------------------------- ### Async GPIO Pin Waiting with Interrupts Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Shows how to use async/await with GPIO pins to wait for specific edge transitions or levels without blocking. This requires the `esp-idf-hal` crate and Rust's async runtime. ```rust use esp_idf_hal::gpio::{PinDriver, Pull, InterruptType}; use esp_idf_hal::peripherals::Peripherals; async fn wait_for_button_press() -> anyhow::Result<()> { let peripherals = Peripherals::take()?; // Configure pin as input with pull-up let mut button = PinDriver::input(peripherals.pins.gpio5, Pull::Up)?; // Async wait for falling edge (button press) button.wait_for_falling_edge().await?; println!("Button pressed!"); // Wait for rising edge (button release) button.wait_for_rising_edge().await?; println!("Button released!"); // Wait for any edge transition button.wait_for_any_edge().await?; println!("Edge detected!"); // Wait for specific level button.wait_for_low().await?; println!("Pin is now low!"); Ok(()) } ``` -------------------------------- ### Async UART for Non-Blocking Communication Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Shows how to wrap a `UartDriver` in `AsyncUartDriver` for non-blocking read and write operations using async/await. Includes async write, read, and waiting for TX completion. ```rust use esp_idf_hal::uart::{AsyncUartDriver, UartDriver, UartConfig}; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::units::*; use esp_idf_hal::gpio::AnyIOPin; async fn uart_communication() -> anyhow::Result<()> { let peripherals = Peripherals::take()?; let config = UartConfig::new().baudrate(115_200.Hz().into()); let uart = UartDriver::new( peripherals.uart1, peripherals.pins.gpio1, peripherals.pins.gpio3, Option::::None, Option::::None, &config, )?; // Wrap in async driver let async_uart = AsyncUartDriver::wrap(uart)?; // Async write async_uart.write(b"Hello async!").await?; // Async read let mut buf = [0u8; 32]; let len = async_uart.read(&mut buf).await?; println!("Received: {:?}", &buf[..len]); // Wait for TX to complete async_uart.wait_tx_done().await?; // Split into async TX and RX // let (mut async_tx, mut async_rx) = async_uart.split(); // async_tx.write(b"TX data").await?; // async_rx.read(&mut buf).await?; Ok(()) } ``` -------------------------------- ### Access ESP-IDF Peripherals in Rust Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Safely take ownership of all hardware peripherals once. Individual peripherals can then be accessed and passed to driver constructors. After a peripheral is passed to a driver, it cannot be reused. ```rust use esp_idf_hal::peripherals::Peripherals; fn main() -> anyhow::Result<()> { // Take ownership of all peripherals (can only be called once) let peripherals = Peripherals::take()?; // Access individual peripherals let gpio4 = peripherals.pins.gpio4; let spi2 = peripherals.spi2; let i2c0 = peripherals.i2c0; let uart1 = peripherals.uart1; let ledc = peripherals.ledc; // Peripherals can be passed to driver constructors // After passing to a driver, the peripheral cannot be reused // Access LEDC channels and timers let timer0 = peripherals.ledc.timer0; let channel0 = peripherals.ledc.channel0; Ok(()) } ``` -------------------------------- ### Delay Implementations in ESP-IDF HAL for Rust Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Utilize different delay mechanisms: FreeRTOS for RTOS-aware delays, Ets for microsecond-precision busy-waiting, and Delay for embedded-hal compatible non-blocking delays. Timeout constants BLOCK and NON_BLOCK are also available. ```rust use esp_idf_hal::delay::{FreeRtos, Ets, Delay, BLOCK, NON_BLOCK}; fn delay_examples() { // FreeRTOS delay (yields to other tasks) FreeRtos::delay_ms(1000); // 1 second delay // Microsecond precision delay (busy-wait) Ets::delay_us(100); // 100 microseconds // embedded-hal compatible delay use embedded_hal::delay::DelayNs; let delay = Delay::new_default(); // delay.delay_ms(500); // requires mutable reference // Timeout constants for read/write operations // BLOCK - wait indefinitely // NON_BLOCK - return immediately } ``` -------------------------------- ### Type-Safe Units for Frequency and Duration in Rust Source: https://context7.com/esp-rs/esp-idf-hal/llms.txt Create and convert frequency values using type-safe wrappers like Hertz, KiloHertz, and MegaHertz. These are useful for configuring peripherals like SPI, UART, and I2C to prevent unit confusion. ```rust use esp_idf_hal::units::*; fn example_units() { // Create frequency values let freq_hz = Hertz(1_000_000); let freq_khz: Hertz = 100.kHz().into(); let freq_mhz: Hertz = 40.MHz().into(); // Use in configuration use esp_idf_hal::spi::config::Config; let spi_config = Config::new().baudrate(10.MHz().into()); use esp_idf_hal::uart::UartConfig; let uart_config = UartConfig::new().baudrate(115_200.Hz().into()); use esp_idf_hal::i2c::I2cConfig; let i2c_config = I2cConfig::new().baudrate(400.kHz().into()); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.