### Initialize and Use ShaBackend for SHA-1 Hashing Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/sha/struct This example demonstrates how to initialize the ShaBackend, start the driver, create a SHA-1 context, update it with data, and finalize the hash computation. It requires the 'unstable' crate feature and assumes the availability of peripherals.SHA. ```rust use esp_hal::sha::{Sha1Context, ShaBackend}; // Assuming 'peripherals' is available and contains SHA hardware // let mut sha = ShaBackend::new(peripherals.SHA); // Start the backend, which allows processing SHA operations. // let mut _backend = sha.start(); // Create a new context to hash data with SHA-1. // let mut sha1_ctx = Sha1Context::new(); // SHA-1 outputs a 20-byte digest. // let mut digest: [u8; 20] = [0; 20]; // Process data. The `update` function returns a handle which can be used to wait // for the operation to finish. // sha1_ctx.update(b"input data").wait_blocking(); // sha1_ctx.update(b"input data").wait_blocking(); // sha1_ctx.update(b"input data").wait_blocking(); // Extract the final hash. This resets the context. // sha1_ctx.finalize(&mut digest).wait_blocking(); // 'digest' now contains the SHA-1 hash of the input. ``` -------------------------------- ### Blinky LED Example (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/lib A minimal 'blinky' example demonstrating the basic setup for a no_std Rust application on an ESP32 device. It includes necessary imports for GPIO, timing, and the main function attribute. ```rust #![no_std] #![no_main] use esp_hal:: clock::CpuClock, gpio::{Io, Level, Output, OutputConfig}, main, time::{Duration, Instant}, }; ``` -------------------------------- ### Start RSA Backend Processing Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/rsa/mod Shows the process of starting the RSA backend, which makes it ready to process RSA operations enqueued in the work queue. The `start` method returns a driver object that manages the backend's lifecycle. ```rust use esp_hal::rsa::RsaBackend; let mut rsa = RsaBackend::new(peripherals.RSA); // Start the backend, which allows processing RSA operations. let _backend = rsa.start(); ``` -------------------------------- ### SPI Slave DMA Transfer Example (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/spi/slave/index Demonstrates how to configure and perform a DMA-based SPI transfer in slave mode using the ESP-HAL library. This example requires the 'unstable' crate feature and utilizes DMA channels and buffers for efficient data transfer. It shows the setup of SPI pins, DMA, and initiating a transfer. ```rust let dma_channel = peripherals.DMA_CH0; let sclk = peripherals.GPIO0; let miso = peripherals.GPIO1; let mosi = peripherals.GPIO2; let cs = peripherals.GPIO3; let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000); let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let mut spi = Spi::new(peripherals.SPI2, Mode::_0) .with_sck(sclk) .with_mosi(mosi) .with_miso(miso) .with_cs(cs) .with_dma(dma_channel); let transfer = spi.transfer(50, dma_rx_buf, 50, dma_tx_buf)?; transfer.wait(); ``` -------------------------------- ### ESP32 SPI DMA Setup with Buffers (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/spi/master Demonstrates setting up a DMA-capable SPI instance using `SpiDma`. It involves creating DMA buffers, initializing `DmaRxBuf` and `DmaTxBuf`, and then configuring the `Spi` instance with the DMA channel and buffers. This example requires a DMA channel and peripherals available in the `esp_hal` crate. ```rust /// A DMA capable SPI instance. /// /// Using `SpiDma` is not recommended unless you wish /// to manage buffers yourself. It's recommended to use /// [`SpiDmaBus`] via `with_buffers` to get access /// to a DMA capable SPI bus that implements the /// embedded-hal traits. /// ```rust, no_run /// # { /// # use esp_hal::{ /// # dma::{DmaRxBuf, DmaTxBuf}, /// # dma_buffers, /// # spi::{ /// # Mode, /// # master::{Config, Spi}, /// # }, /// # peripherals::Peripherals, /// # clock::ClockControl, /// # system::SystemControl, /// # timer::TimerGroup, /// # R /// # }; /// # use esp_backtrace::exception; /// # /// # #[cfg_attr(feature = "exception_handler", exception) /// # ] /// # fn exception_handler(frame: esp_backtrace::ExceptionFrame) { /// # panic!("{:#?}", frame) /// # } /// # /// # #[entry] /// # fn main() -> ! { /// # let peripherals = Peripherals::take(); /// # let system = SystemControl::new(peripherals.SYSTEM); /// # let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); /// # let tg0 = TimerGroup::new(peripherals.TIMG0, &clocks); /// # let mut wdt0 = tg0.wdt0; /// # /// # let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000); /// # let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); /// # let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); /// # /// # #[cfg(any(esp32, esp32s2))] /// # let dma_channel = peripherals.DMA_SPI2; /// # #[cfg(not(any(esp32, esp32s2)))] /// # let dma_channel = peripherals.DMA_CH0; /// # /// # let mut spi = Spi::new( /// # peripherals.SPI2, /// # Config::default() /// # .with_frequency(esp_hal::units::Hertz::from_kHz(100)) /// # .with_mode(Mode::_0), /// # ) /// # .unwrap() /// # .with_dma(dma_channel) /// # .with_buffers(dma_rx_buf, dma_tx_buf); /// # /// # loop {} /// # } /// # /// # } /// # // Dummy definitions to make the example compile /// # mod esp_hal { /// # pub mod dma { /// # pub struct DmaRxBuf { _private: usize } /// # pub struct DmaTxBuf { _private: usize } /// # impl DmaRxBuf { pub fn new(a: usize, b: usize) -> Result { Ok(Self { _private: 0 }) } } /// # impl DmaTxBuf { pub fn new(a: usize, b: usize) -> Result { Ok(Self { _private: 0 }) } } /// # pub type Channel = usize; /// # pub type PeripheralDmaChannel

= usize; /// # pub enum EmptyBuf {} /// # pub struct DmaRxFuture { _private: usize } /// # pub struct DropGuard { _private: usize } /// # } /// # pub mod spi { /// # pub mod master { /// # pub struct Spi { _private: usize } /// # pub struct Config { _private: usize } /// # impl Config { pub fn default() -> Self { Self { _private: 0 } } } /// # impl Config { pub fn with_frequency(self, freq: esp_hal::units::Hertz) -> Self { self } } /// # impl Config { pub fn with_mode(self, mode: Mode) -> Self { self } } /// # impl Spi { pub fn new(spi: AnySpi, config: Config) -> Result { Ok(Self { _private: 0 }) } } /// # impl Spi { pub fn with_dma(self, channel: usize) -> Self { self } } /// # impl Spi { pub fn with_buffers(self, rx: DmaRxBuf, tx: DmaTxBuf) -> Self { self } } /// # pub enum Mode { _0 } /// # } /// # } /// # pub mod peripherals { /// # pub struct Peripherals { DMA_SPI2: usize, DMA_CH0: usize, SPI2: usize, SYSTEM: usize, TIMG0: usize } /// # impl Peripherals { pub fn take() -> Self { Peripherals { DMA_SPI2: 0, DMA_CH0: 0, SPI2: 0, SYSTEM: 0, TIMG0: 0 } } } /// # } /// # pub mod system { pub struct SystemControl { clock_control: usize } impl SystemControl { pub fn new(clk: usize) -> Self { Self { clock_control: 0 } } } } /// # pub mod clock { pub struct ClockControl { } impl ClockControl { pub fn boot_defaults(sys: Self) -> Self { Self { } } pub fn freeze(self) -> Self { self } } } } /// # pub mod timer { pub struct TimerGroup { } impl TimerGroup { pub fn new(tim: usize, clk: &ClockControl) -> Self { Self { } } pub struct Wdt {} pub fn wdt0(self) -> Wdt { Wdt {} } } } /// # pub mod units { pub struct Hertz { } impl Hertz { pub fn from_kHz(v: u32) -> Self { Self {} } } } } /// # pub struct AnySpi<'d> { _private: usize } /// # pub trait DriverMode {} /// # pub struct SpiPinGuard {} /// # pub struct ConfigError {} /// # pub enum Error { FifoSizeExeeded, Unsupported} /// # pub struct Config {} /// # pub struct Spi<'d, Dm> { spi: AnySpi<'d>, channel: usize, tx_transfer_in_progress: bool, rx_transfer_in_progress: bool, guard: PeripheralGuard, pins: SpiPinGuard } /// # pub struct PeripheralGuard {} /// # pub struct Driver { info: usize, state: usize } /// # impl Driver { pub fn info(&self) -> usize { 0 } pub fn state(&self) -> usize { 0 } } /// # impl<'d, Dm: DriverMode> Spi<'d, Dm> { pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> { Ok(()) } } /// # impl Spi<'_, Dm> where Dm: DriverMode { pub fn setup_half_duplex(&self, a: bool, b: u8, c: Address, d: bool, e: u8, f: bool, g: DriverMode) -> Result<(), Error> { Ok(()) } } /// # impl Spi<'_, Dm> where Dm: DriverMode { pub fn write(&self, buffer: &[u8]) -> Result<(), Error> { Ok(()) } } /// # impl Spi<'_, Dm> where Dm: DriverMode { pub fn start_operation(&self) { } } /// # impl Spi<'_, Dm> where Dm: DriverMode { pub fn flush(&self) -> Result<(), Error> { Ok(()) } } /// # pub enum Address { None } /// # impl Address { pub fn width(&self) -> u32 { 0 } pub fn div_ceil(&self, div: u32) -> u32 { 0 } pub fn value(&self) -> [u8; 4] { [0; 4] } pub fn is_none(&self) -> bool { true } pub fn mode(&self) -> DriverMode { } } /// # pub struct DriverMode {} /// # } /// # #[macro_export] /// # macro_rules! dma_buffers { /// # ($size:expr) => { (0, 0, 0, 0) }; /// # } /// # #[macro_export] /// # macro_rules! cfg_if { /// # ($($tt:tt)*) => { $($tt)* }; /// # } /// # #[macro_export] /// # macro_rules! doc_replace { /// # ($name:expr => $replacement:tt) => { }; /// # } /// # #[macro_export] /// # macro_rules! error { /// # ($msg:expr) => { println!($msg) }; /// # } /// # #[macro_export] /// # macro_rules! critical { /// # ($($tt:tt)*) => { $($tt)* }; /// # } /// # #[macro_export] /// # macro_rules! entry { /// # ($($tt:tt)*) => { $($tt)* }; /// # } /// # #[macro_export] /// # macro_rules! instability { /// # (unstable) => {}; /// # } /// # #[doc_cfg(feature = "defmt")] /// # #[derive(defmt::Format)] /// # pub struct SpiDma<'d, Dm> where Dm: DriverMode { pub(crate) spi: AnySpi<'d>, pub(crate) channel: Channel>>, pub(crate) tx_transfer_in_progress: bool, pub(crate) rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] pub(crate) address_buffer: DmaTxBuf, pub(crate) guard: PeripheralGuard, pub(crate) pins: SpiPinGuard, } /// # #[cfg(any(esp32, esp32s2))] /// # pub use esp_hal::peripherals::Peripherals::DMA_SPI2 as dma_channel_alias; /// # #[cfg(not(any(esp32, esp32s2)))] /// # pub use esp_hal::peripherals::Peripherals::DMA_CH0 as dma_channel_alias; /// # #[cfg(all(esp32, spi_address_workaround))] /// # pub const spi_address_workaround: bool = true; /// # #[cfg(not(all(esp32, spi_address_workaround)))] /// # pub const spi_address_workaround: bool = false; /// # mod crate { pub mod dma { pub use esp_hal::dma::*; } pub mod spi { pub mod master { pub use esp_hal::spi::master::*; } } } /// # /// use esp_hal::dma::{DmaRxBuf, DmaTxBuf}; /// use esp_hal::dma_buffers; /// use esp_hal::spi::master::{Config, Spi}; /// use esp_hal::peripherals::Peripherals; /// use esp_hal::clock::ClockControl; /// use esp_hal::system::SystemControl; /// use esp_hal::timer::TimerGroup; /// /// // Placeholder for actual entry point and device setup /// #[entry] /// fn main() -> ! { /// let peripherals = Peripherals::take(); /// let system = SystemControl::new(peripherals.SYSTEM); /// let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); /// let tg0 = TimerGroup::new(peripherals.TIMG0, &clocks); /// let mut wdt0 = tg0.wdt0; /// /// // Define DMA buffer sizes /// let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000); /// /// // Create DMA buffer instances /// let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); /// let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); /// /// // Select the appropriate DMA channel based on the target chip /// #[cfg(any(esp32, esp32s2))] /// let dma_channel = peripherals.DMA_SPI2; /// #[cfg(not(any(esp32, esp32s2)))] /// let dma_channel = peripherals.DMA_CH0; /// /// // Initialize SPI with DMA capabilities and buffers /// let mut spi = Spi::new( /// peripherals.SPI2, /// Config::default() /// .with_frequency(esp_hal::units::Hertz::from_kHz(100)) /// .with_mode(esp_hal::spi::master::Mode::_0), /// ) /// .unwrap() /// .with_dma(dma_channel) /// .with_buffers(dma_rx_buf, dma_tx_buf); /// /// // Main loop or further SPI operations /// loop {} /// } /// ``` ``` -------------------------------- ### Blinky Example Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/index A minimal example demonstrating how to blink an LED using the esp-hal crate. It configures a GPIO pin as an output, toggles its state, and introduces a delay using `Instant` and `Duration`. ```rust #![no_std] #![no_main] use esp_hal::{ clock::CpuClock, gpio::{Io, Level, Output, OutputConfig}, main, time::{Duration, Instant}, }; // You need a panic handler. Usually, you you would use esp_backtrace, panic-probe, or // something similar, but you can also bring your own like this: #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { esp_hal::system::software_reset() } #[main] fn main() -> ! { let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); // Set GPIO0 as an output, and set its state high initially. let mut led = Output::new(peripherals.GPIO0, Level::High, OutputConfig::default()); loop { led.toggle(); // Wait for half a second let delay_start = Instant::now(); while delay_start.elapsed() < Duration::from_millis(500) {} } } ``` -------------------------------- ### ESP-HAL SHA Driver Usage (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/sha/index Demonstrates how to use the `Sha` driver for cryptographic hash operations. This example initializes the SHA peripheral, starts a SHA-256 calculation, updates it with source data in blocks, and finishes the calculation to retrieve the hash output. It assumes the `unstable` crate feature is enabled. ```rust use esp_hal::sha::{Sha, Sha256}; use esp_hal::block; let mut source_data = "HELLO, ESPRESSIF!".as_bytes(); let mut sha = Sha::new(peripherals.SHA); let mut hasher = sha.start::(); // Short hashes can be created by decreasing the output buffer to the // desired length let mut output = [0u8; 32]; while !source_data.is_empty() { // All the HW Sha functions are infallible so unwrap is fine to use if // you use block! source_data = block!(hasher.update(source_data))?; } // Finish can be called as many times as desired to get multiple copies of // the output. block!(hasher.finish(output.as_mut_slice()))?; ``` -------------------------------- ### ESP-HAL ShaBackend Driver SHA-1 Hashing (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/sha/index Illustrates using the `ShaBackend` driver for SHA-1 hashing. This example initializes the SHA peripheral, starts the backend, creates a SHA-1 context, updates it with data multiple times, and then finalizes the hash calculation to produce a 20-byte digest. Each update and finalize operation is performed in a blocking manner. ```rust use esp_hal::sha::{Sha1Context, ShaBackend}; let mut sha = ShaBackend::new(peripherals.SHA); // Start the backend, which allows processing SHA operations. let _backend = sha.start(); // Create a new context to hash data with SHA-1. let mut sha1_ctx = Sha1Context::new(); // SHA-1 outputs a 20-byte digest. let mut digest: [u8; 20] = [0; 20]; // Process data. The `update` function returns a handle which can be used to wait // for the operation to finish. sha1_ctx.update(b"input data").wait_blocking(); sha1_ctx.update(b"input data").wait_blocking(); sha1_ctx.update(b"input data").wait_blocking(); // Extract the final hash. This resets the context. sha1_ctx.finalize(&mut digest).wait_blocking(); // digest now contains the SHA-1 hash of the input. ``` -------------------------------- ### Rust ESP-HAL Panic Handler and Main Function Example Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/lib Demonstrates a basic panic handler using `esp_hal::system::software_reset` and a main function that initializes the system, controls an LED on GPIO0, and toggles it with a 500ms delay. This example requires the `esp-hal` crate and its associated features. ```rust #![no_std] use esp_hal::clock::ClockControl; use esp_hal::delay::Delay; use esp_hal::gpio::Output; use esp_hal::gpio::Pin; use esp_hal::gpio::PushPull; use esp_hal::peripherals::Peripherals; use esp_hal::prelude::*; use esp_hal::system::SystemControl; #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { esp_hal::system::software_reset() } #[entry] fn main() -> ! { let peripherals = Peripherals::take(); let system = SystemControl::new(peripherals.SYSTEM); // Clock control let clocks = ClockControl::max(system.clock_control).freeze(); // Delay provider let mut delay = Delay::new(&clocks); // GPIO0 as an output, and set its state high initially. let mut led = Output::new(peripherals.GPIO0.into_push_pull_output()); led.set_high().unwrap(); loop { led.toggle().unwrap(); // Wait for half a second delay.delay_ms(500u32); } } ``` -------------------------------- ### Periodic Timer Example - Rust Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/timer/index Illustrates how to set up and use a periodic timer for recurring tasks. It involves creating a TimerGroup, instantiating a PeriodicTimer, starting it with a specific duration, and then entering a loop that waits for the timer to elapse. ```rust let timg0 = TimerGroup::new(peripherals.TIMG0); let mut periodic = PeriodicTimer::new(timg0.timer0); periodic.start(Duration::from_secs(1)); loop { periodic.wait(); } ``` -------------------------------- ### Create ShaBackend Instance Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/sha/struct This function creates a new instance of the ShaBackend. The backend must be started before it can be used to execute SHA operations. ```rust pub fn new(sha: SHA<'d>) -> Self ``` -------------------------------- ### SPI Asynchronous Transfer Setup (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/spi/master Implements a future `SpiFuture` for handling asynchronous SPI transfers. The `setup` function prepares the SPI driver by registering the waker, clearing interrupts, and enabling interrupt listening for `TransferDone`. ```rust struct SpiFuture<'a> { driver: &'a Driver, } impl<'a> SpiFuture<'a> { #[cfg_attr(place_spi_master_driver_in_ram, ram)] fn setup(driver: &'a Driver) -> impl Future { // Make sure this is called before starting an async operation. On the ESP32, // calling after may cause the interrupt to not fire. core::future::poll_fn(move |cx| { driver.state.waker.register(cx.waker()); driver.clear_interrupts(SpiInterrupt::TransferDone.into()); driver.enable_listen(SpiInterrupt::TransferDone.into(), true); Poll::Ready(Self { driver }) }) } } ``` -------------------------------- ### Initialize and Utilize DMA with SPI Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/dma/index This example demonstrates how to initialize a DMA channel and use it with the SPI peripheral for data transfers. ```APIDOC ## Initialize and utilize DMA controller in `SPI` ### Description This example shows the initialization of a DMA channel and its subsequent use with the SPI peripheral for efficient data transfer. ### Request Example ```rust let dma_channel = peripherals.DMA_CH0; let sclk = peripherals.GPIO0; let miso = peripherals.GPIO2; let mosi = peripherals.GPIO4; let cs = peripherals.GPIO5; let mut spi = Spi::new( peripherals.SPI2, Config::default() .with_frequency(Rate::from_khz(100)) .with_mode(Mode::_0), )? .with_sck(sclk) .with_mosi(mosi) .with_miso(miso) .with_cs(cs) .with_dma(dma_channel); ``` ### Notes - Descriptors should be sized as `(max_transfer_size + CHUNK_SIZE - 1) / CHUNK_SIZE`. - For chips supporting DMA to/from PSRAM (ESP32-S3), buffer addresses and sizes must be a multiple of the cache line size (32 bytes on ESP32-S3). ``` -------------------------------- ### Start One-Time ADC Sample (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/analog/adc/riscv Initiates a one-time ADC sample operation. After configuring the sample parameters using `config_onetime_sample`, this function is called to start the conversion. It sets the 'onetime_start' bit in the APB_SARADC control register. ```rust fn start_onetime_sample() { APB_SARADC::regs() .onetime_sample() .modify(|_, w| w.onetime_start().set_bit()); } ``` -------------------------------- ### System Timer ETM Event Configuration Example Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/timer/systimer Demonstrates how to configure the Event Task Matrix (ETM) for the system timer. This example shows how to create a timer event and link it to a GPIO toggle task for LED control. ```rust ```rust, no_run # { before_snippet} # use esp_hal::timer::systimer::{etm::Event, SystemTimer}; # use esp_hal::timer::PeriodicTimer; # use esp_hal::etm::Etm; # use esp_hal::gpio::{ # etm::{Channels, OutputConfig}, # Level, # Pull, # }; let syst = SystemTimer::new(peripherals.SYSTIMER); let etm = Etm::new(peripherals.ETM); let gpio_ext = Channels::new(peripherals.GPIO_SD); let alarm0 = syst.alarm0; let mut led = peripherals.GPIO1; let timer_event = Event::new(&alarm0); let led_task = gpio_ext.channel0_task.toggle( led, OutputConfig { // Configuration for the GPIO toggle task }, ); etm.connect(timer_event, led_task); ``` ``` -------------------------------- ### UART Initialization and Usage Example (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/uart/mod Demonstrates how to initialize a UART peripheral with custom RX and TX pins, and then perform a write operation. This example requires the `esp_hal` crate and specific peripheral instances. ```rust use esp_hal::uart::{Config, Uart}; // Assuming peripherals and other necessary setup are done // let mut uart = Uart::new(peripherals.UART0, Config::default())? // .with_rx(peripherals.GPIO1) // .with_tx(peripherals.GPIO2); // // uart.write(b"Hello world!")?; ``` -------------------------------- ### Rustdoc Slice and Array Search Examples Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/help Explains how to search for functions that accept or return slices and arrays using square bracket notation in the search query. ```rustdoc -> [u8] [] -> Option fn:bytes_to_string ``` -------------------------------- ### Default System Initialization in esp_hal (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/config/index Demonstrates the default system initialization using the esp_hal::init() method with default configurations. This is a straightforward way to set up the system with minimal code. ```rust let peripherals = esp_hal::init(esp_hal::Config::default()); ``` -------------------------------- ### Doctest Setup Macro - Rust Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/macros The `before_snippet` macro is used to set up the necessary context for running doctests. It includes common imports, defines placeholder macros like `println!` and `print!`, and sets up a basic panic handler and main function structure. ```rust #![no_std] use procmacros::handler; use esp_hal::{interrupt::{self, InterruptConfigurable}, time::{Duration, Instant, Rate}}; macro_rules! println { ($($tt:tt)*) => { }; } macro_rules! print { ($($tt:tt)*) => { }; } #[panic_handler] fn panic(_ : &core::panic::PanicInfo) -> ! { loop {} } fn main() { let _ = example(); } struct ExampleError {} impl From for ExampleError where T: core::fmt::Debug { fn from(_value: T) -> Self { Self{} } } async fn example() -> Result<(), ExampleError> { let mut peripherals = esp_hal::init(esp_hal::Config::default()); ``` -------------------------------- ### Getting Chip Revision (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/efuse/struct Returns the hardware revision of the chip as a u16 value. The chip version is calculated using the formula: MAJOR * 100 + MINOR. For example, a version of 1 indicates v0.1. This API is unstable. ```rust pub fn chip_revision() -> u16 ``` -------------------------------- ### Create a New RSA Backend Instance Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/rsa/mod Illustrates how to instantiate a new RsaBackend, passing the RSA peripheral instance to its constructor. This is the initial step before enabling the backend for operation. ```rust use esp_hal::rsa::RsaBackend; let mut rsa = RsaBackend::new(peripherals.RSA); ``` -------------------------------- ### Start Blocking RX DMA Transfer (esp-hal) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/dma/m2m Initiates a DMA reception into a provided buffer using the RX half of a `Mem2Mem` instance in blocking mode. It handles potential DMA errors during transfer setup and initiation. ```rust impl<'d> Mem2MemRx<'d, Blocking> { /// Convert Mem2MemRx to an async Mem2MemRx. pub fn into_async(self) -> Mem2MemRx<'d, Async> { Mem2MemRx { channel: self.channel.into_async(), peripheral: self.peripheral, } } } impl<'d, Dm> Mem2MemRx<'d, Dm> where Dm: DriverMode, { /// Start the RX half of a memory to memory transfer. pub fn receive( mut self, mut buf: BUF, ) -> Result, (DmaError, Self, BUF)> where BUF: DmaRxBuffer, { let result = unsafe { self.channel .prepare_transfer(self.peripheral, &mut buf) .and_then(|_| self.channel.start_transfer()) }; if let Err(e) = result { return Err((e, self, buf)); } Ok(Mem2MemRxTransfer { m2m: ManuallyDrop::new(self), buf_view: ManuallyDrop::new(buf.into_view()), }) } } ``` -------------------------------- ### Rustdoc Exact Name and Path Search Examples Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/help Shows how to perform exact name matches for Rust items by enclosing the query in double quotes, and how to search for items within a specific module path. ```rustdoc "HashMap" std::collections::HashMap ``` -------------------------------- ### Project Generation Tool Usage (Bash) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/lib Shows how to install and use the `esp-generate` project scaffolding tool. This command-line utility helps in creating new projects within the esp-rs ecosystem, pre-configuring them for specific ESP32 chips. ```bash cargo install esp-generate esp-generate --chip=esp32c6 your-project ``` -------------------------------- ### Perform SPI Half-Duplex Write with DMA (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/spi/master Initiates a half-duplex SPI write operation using Direct Memory Access (DMA). This function handles the setup of the SPI driver for half-duplex communication and starts the DMA transfer. It requires mutable access to a DMA transmit buffer and returns a `SpiDmaTransfer` on success or an error tuple on failure. The caller must ensure buffers are not accessed during transfer. ```rust /// Perform a half-duplex write operation using DMA. #[allow(clippy::type_complexity)] #[cfg_attr(place_spi_master_driver_in_ram, ram)] #[instability::unstable] pub fn half_duplex_write( mut self, data_mode: DataMode, cmd: Command, address: Address, dummy: u8, bytes_to_write: usize, mut buffer: TX, ) -> Result, (Error, Self, TX)> { self.wait_for_idle(); match unsafe { self.start_half_duplex_write( data_mode, cmd, address, dummy, bytes_to_write, &mut buffer, ) } { Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)), Err(e) => Err((e, self, buffer)), } } ``` -------------------------------- ### SPI Driver Initialization and Configuration Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/spi/master Provides methods for initializing and configuring the SPI driver, including setting up pins and degrading the SPI instance. ```APIDOC ## SPI Driver Initialization and Configuration ### Description This section covers the initialization and configuration of the SPI driver, including setting up pins and degrading the SPI instance for further operations. ### Methods - `new(...)` - `init()` - `apply_config(&config)?` - `with_sck(NoPin)` - `with_cs(NoPin)` - `driver().info().opt_sio_input(sio)` - `driver().info().opt_sio_output(sio)` - `connect_to(&NoPin)` ### Example (Conceptual) ```rust // Assuming spi and config are defined elsewhere // let mut spi = Spi::new(...); // let config = Config::default(); // spi.apply_config(&config)?; // let spi_instance = spi.with_sck(NoPin).with_cs(NoPin); ``` ``` -------------------------------- ### Rust: Get Current Instant Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/time Provides a function to get the current `Instant`. This uses the system's monotonic clock, which is not affected by system time changes. The timer has a 1-microsecond resolution. ```Rust pub fn now() -> Self { now() } ``` -------------------------------- ### Rustdoc Search Prefix Examples Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/help Demonstrates how to use prefixes to narrow down Rustdoc searches by item kind. This helps in quickly locating specific functions, modules, structs, enums, traits, types, macros, or constants. ```rustdoc fn:println struct:Vec mod:std::fs ``` -------------------------------- ### SPI Master Operation Start in Rust Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/spi/master Initiates an SPI operation by updating the device state and setting the user command register to start the operation. This is a foundational step before data transfer or execution. ```rust #[cfg_attr(place_spi_master_driver_in_ram, ram)] fn start_operation(&self) { self.update(); self.regs().cmd().modify(|_, w| w.usr().set_bit()); } ``` -------------------------------- ### Getting ADC Calibration Voltage (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/efuse/struct Gets the ADC reference point voltage for a specified attenuation in millivolts. This function takes an AdcCalibUnit and Attenuation as input and returns a u16 value. It references an implementation in esp-idf. ```rust pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 ``` -------------------------------- ### RSA Backend Initialization Logic Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/rsa/mod This snippet details the internal logic within the RsaBackend's `process_item` method when the state is `Initializing`. It shows the creation of an Rsa driver instance and transitions the state based on the peripheral's readiness. ```rust match core::mem::take(&mut self.state) { RsaBackendState::Idle => { let driver = Rsa { rsa: unsafe { self.peri.clone_unchecked() }, phantom: PhantomData, _guard: GenericPeripheralGuard::new(), }; self.state = RsaBackendState::Initializing(driver); work_queue::Poll::Pending(true) } RsaBackendState::Initializing(mut rsa) => { // Wait for the peripheral to finish initializing. self.state = if rsa.ready() { rsa.set_interrupt_handler(rsa_work_queue_handler); rsa.enable_disable_interrupt(true); RsaBackendState::Ready(rsa) } else { RsaBackendState::Initializing(rsa) }; work_queue::Poll::Pending(true) } ``` -------------------------------- ### ADC Driver Initialization Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/analog/adc/riscv This section describes how to initialize the ADC driver and configure its parameters. ```APIDOC ## ADC Initialization ### Description Initializes the ADC driver with the given configuration, including attenuations and interrupt handler. ### Method Associated function (constructor) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **config** (AdcConfig) - Required - The configuration for the ADC. ### Request Example ```json { "config": { ... AdcConfig details ... } } ``` ### Response #### Success Response (200) - **Adc** (Adc<'d, ADCI, Blocking>) - The initialized ADC driver instance. #### Response Example ```json { "adc_driver_instance": { ... Adc instance details ... } } ``` ``` -------------------------------- ### Rust: ESP32 Initialization Function Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/soc/mod This Rust function `esp32_init` performs essential setup after the initial reset and stack protector configuration. It calls `configure_cpu_caches` and `setup_interrupts`, which are assumed to be defined elsewhere in the crate, enabling hardware features and interrupt handling. ```rust #[cfg_attr(esp32s3, unsafe(link_section = ".rwtext"))] fn esp32_init() { unsafe { super::configure_cpu_caches(); } crate::interrupt::setup_interrupts(); } ``` -------------------------------- ### Getting Base MAC Address (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/efuse/struct Gets the base MAC address. By default, this reads the MAC address from eFuse, but it can be overridden by `set_mac_address`. This function returns a 6-byte array. It is marked as unstable and requires the `unstable` crate feature. ```rust pub fn mac_address() -> [u8; 6] ``` -------------------------------- ### Start Multiplication Operation (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/rsa/mod Starts a standard multiplication operation on the RSA peripheral. The implementation details vary slightly depending on the specific ESP32 model, utilizing conditional compilation. This is a fundamental arithmetic operation for the peripheral. ```rust fn start_multi(&self) { cfg_if::cfg_if! { if #[cfg(any(esp32, esp32s2, esp32s3))] { self.regs().mult_start().write(|w| w.mult_start().set_bit()); } else { self.regs() .set_start_mult() .write(|w| w.set_start_mult().set_bit()); } } } ``` -------------------------------- ### Get Current Instant - Rust Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/time/struct This snippet demonstrates how to get the current time using the `Instant::now()` function. This function returns the current instant, and the counter used does not measure time during sleep mode. The timer has a 1-microsecond resolution. ```rust use esp_hal::time::Instant; let now = Instant::now(); ``` -------------------------------- ### OutputConfig Methods Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/gpio/struct Methods for configuring and retrieving output pin settings. ```APIDOC ## Implementations ### impl OutputConfig #### pub fn with_drive_mode(self, drive_mode: DriveMode) -> Self Assign the given value to the `drive_mode` field. #### pub fn drive_mode(&self) -> DriveMode Output drive mode. #### pub fn with_drive_strength(self, drive_strength: DriveStrength) -> Self Assign the given value to the `drive_strength` field. #### pub fn drive_strength(&self) -> DriveStrength Pin drive strength. #### pub fn with_pull(self, pull: Pull) -> Self Assign the given value to the `pull` field. #### pub fn pull(&self) -> Pull Pin pull direction. ``` -------------------------------- ### Rustdoc Type Signature Search Examples Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/help Illustrates how to search for Rust items based on their type signatures. This includes searching for functions that return a specific type, accept a specific type, or a combination of input and output types. ```rustdoc vec -> usize -> String String, enum:Cow -> bool ``` -------------------------------- ### Get eFuse Block Address - Rust Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/efuse/esp32c2/mod This Rust code defines an enum `EfuseBlock` representing different eFuse blocks and implements a method `address` to retrieve the memory address of the first register for each block. It utilizes the `EFUSE` peripheral's register access to get the pointers. ```rust impl EfuseBlock { pub(crate) fn address(self) -> *const u32 { let efuse = EFUSE::regs(); match self { Self::Block0 => efuse.rd_wr_dis().as_ptr(), Self::Block1 => efuse.rd_blk1_data0().as_ptr(), Self::Block2 => efuse.rd_blk2_data0().as_ptr(), Self::Block3 => efuse.rd_blk3_data0().as_ptr(), } } } ``` -------------------------------- ### Initialize and Apply I2C Master Configuration Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/i2c/master/index Shows how to initialize the I2C master driver with a peripheral instance and configuration, specifying SDA and SCL pins. It also demonstrates how to apply a new configuration to an existing driver instance. ```rust use esp_hal::i2c::master::I2c; // You need to configure the driver during initialization: let mut i2c = I2c::new(peripherals.I2C0, config)? .with_sda(peripherals.GPIO2) .with_scl(peripherals.GPIO3); // You can change the configuration later: let new_config = config.with_frequency(Rate::from_khz(400)); i2c.apply_config(&new_config)?; ``` -------------------------------- ### Start Modular Multiplication Operation (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/rsa/mod Initiates a modular multiplication operation. It handles specific configurations for ESP32, ESP32-S2, and ESP32-S3, potentially reusing the standard multiplication start for ESP32 if the 'modular' aspect is handled elsewhere. This is optimized for modular arithmetic. ```rust fn start_modmulti(&self) { cfg_if::cfg_if! { if #[cfg(esp32)] { // modular-ness is encoded in the multi_mode register value self.start_multi(); } else if #[cfg(any(esp32s2, esp32s3))] { self.regs() .modmult_start() .write(|w| w.modmult_start().set_bit()); } else { self.regs() .set_start_modmult() .write(|w| w.set_start_modmult().set_bit()); } } } ``` -------------------------------- ### Initialize DMA Memory-to-Memory Transfer (Rust) Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/dma/m2m Initializes a DMA memory-to-memory transfer. It handles the setup of both transmit and receive descriptors and buffers, returning a `SimpleMem2MemTransfer` object upon successful initiation. Errors during setup will return the original error and reset the state. ```rust impl<'a, 'd, Dm: DriverMode> SimpleMem2Mem<'a, 'd, Dm> { pub fn new( rx: RxDescriptorRing<'d, Dm>, tx: TxDescriptorRing<'d, Dm>, rx_buffer: DmaBuffer<'d, Dm>, tx_buffer: DmaBuffer<'d, Dm>, config: DmaConfig, ) -> Result, DmaError> { let (rx_descriptors, _rx_buffer) = rx_buffer.split(); let (tx_descriptors, _tx_buffer) = tx_buffer.split(); let mem2mem = Mem2Mem { rx, tx }; let dma_rx_buf = unwrap!( DmaRxBuf::new_with_config(rx_descriptors, mem2mem.rx, config), "There's no way to get the descriptors back yet" ); let rx = match mem2mem.rx.receive(dma_rx_buf) { Ok(rx) => rx, Err((err, rx, buf)) => { let (rx_descriptors, _rx_buffer) = buf.split(); self.state = State::Idle( Mem2Mem { rx, tx: mem2mem.tx }, rx_descriptors, tx_descriptors, ); return Err(err); } }; let dma_tx_buf = unwrap!( DmaTxBuf::new_with_config(tx_descriptors, tx_buffer, self.config), "There's no way to get the descriptors back yet" ); let tx = match mem2mem.tx.send(dma_tx_buf) { Ok(tx) => tx, Err((err, tx, buf)) => { let (tx_descriptors, _tx_buffer) = buf.split(); let (rx, buf) = rx.stop(); let (rx_descriptors, _rx_buffer) = buf.split(); self.state = State::Idle(Mem2Mem { rx, tx }, rx_descriptors, tx_descriptors); return Err(err); } }; self.state = State::Active(rx, tx); Ok(SimpleMem2MemTransfer(self)) } } ``` -------------------------------- ### DebugAssist Driver Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/src/esp_hal/assist_debug Documentation for the main DebugAssist driver, including initialization and interrupt handling. ```APIDOC ## DebugAssist Driver ### Description Provides the main interface for interacting with the Debug Assist hardware module. This driver allows for the creation of a DebugAssist instance, setting up interrupt handlers, and managing debugging features. ### Initialization ```rust let debug_assist = DebugAssist::new(peripherals.ASSIST_DEBUG); ``` ### Methods #### `set_interrupt_handler` Registers an interrupt handler for the Debug Assist module. ##### Parameters - `handler` (InterruptHandler) - The interrupt handler to register. ##### Usage ```rust let handler = InterruptHandler::new(my_handler_function); debug_assist.set_interrupt_handler(handler); ``` ### Traits Implemented - `crate::private::Sealed` - `crate::interrupt::InterruptConfigurable` ``` -------------------------------- ### Initialize DMA Controller with SPI Source: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.1/esp32c3/esp_hal/dma/index Demonstrates how to initialize a DMA channel and configure an SPI peripheral to use it. This setup is crucial for offloading data transfer tasks from the CPU. It requires specific peripheral access and configuration for SPI frequency and mode. ```rust let dma_channel = peripherals.DMA_CH0; let sclk = peripherals.GPIO0; let miso = peripherals.GPIO2; let mosi = peripherals.GPIO4; let cs = peripherals.GPIO5; let mut spi = Spi::new( peripherals.SPI2, Config::default() .with_frequency(Rate::from_khz(100)) .with_mode(Mode::_0), )? .with_sck(sclk) .with_mosi(mosi) .with_miso(miso) .with_cs(cs) .with_dma(dma_channel); ```