$ show esp-rs/esp-hal
This is a bare-metal (no_std) hardware abstraction layer (HAL) for Espressif ESP32 microcontrollers, supporting RISC-V and Xtensa cores. It provides low-level drivers for GPIO, SPI, I2C, UART, ADC, DAC, PWM, timer, USB, Ethernet, Wi-Fi, BLE, IEEE 802.15.4, and many other peripherals across a dozen+ chip families (ESP32, ESP32-C2/C3/C5/C6/C61, ESP32-H2/H4, ESP32-P4, ESP32-S2/S3/S31). The repository is a monorepo containing multiple independently versioned crates: esp-hal (core HAL), esp-radio (wireless radio stacks), esp-alloc (heap allocator), esp-storage (flash storage), esp-backtrace, esp-println, esp-sync (synchronization primitives), esp-rom-sys (ROM function bindings), esp-rtos (lightweight RTOS with async/embassy integration), esp-lp-hal (low-power core HAL), esp-config (build-time configuration), esp-metadata (chip property code generation), xtask (build/release tooling), and bootloader/OTA support. The architecture is built on extensive use of compile-time chip selection via macros (cfg_select!, for_each_*), versioned low-level driver modules per peripheral, and type-erased patterns for unified APIs across chip variants. Async support is first-class via embassy executor integration. The codebase demonstrates high engineering quality with clear abstractions, comprehensive hardware-in-the-loop testing (hil-test, hil-test-radio), and mature CI/CD workflows.
The LLM identified 4 files worth highlighting for reuse:
Provides `heap_allocator!` and `psram_allocator!` macros that instantiate custom heap allocators (e.g., Internal, External, DMA-capable) with memory capability tagging. These macros encapsulate the complex initialization of the TLSF (Two-Level Segregated Fit) or LLFF (Linked List First Fit) allocator, with optional C `malloc`/`free` compatibility. The pattern is self-contained and directly reusable in any embedded Rust project needing multi-region allocation without pulling in the full esp-hal.
Implements `RawMutex` and `NonReentrantMutex` using interrupt masking (RISC-V mstatus or Xtensa PS), with reentrancy tracking and both single-core and multi-core safe variants. The `GenericRawMutex<LOCK>` abstraction allows swapping interrupt strategies at compile time. This is a small, dependency-free synchronization primitive extracted and reusable across any no_std embedded project on RISC-V or Xtensa, solving a common need without relying on external critical-section crates.
Defines unified `trace!`, `debug!`, `info!`, `warn!`, `error!` macros that seamlessly switch between `defmt`, `log`, or no-op backends based on feature flags. Also includes `unwrap!` leveraging `Try` trait for clean error handling. This is a classic conditional logging abstraction, reusable in any embedded Rust crate that wants to support multiple logging frameworks without coupling to a specific one. It is isolated and demonstrates careful macro hygiene (use statement control, no internal crate imports).
Provides `VolatileCell` for safe volatile access to hardware registers (used in DMA descriptors and peripheral registers), along with `AlignmentHelper` for aligned, buffered u32 register writes with endianness conversion and flush operations. This is a tiny, self-contained utility for register-level I/O that can be extracted into any embedded project needing safe volatile memory access without pulling in entire peripheral drivers. Demonstrates non-obvious skill in handling alignment and volatile semantics correctly.