src/platforms/esp/32/drivers/README.md
This directory contains centralized hardware driver implementations for ESP32 platforms.
Drivers are bonafide peripheral abstractions that encapsulate ESP-IDF hardware APIs and provide:
uart_esp32.h / uart_esp32.cpp.hpp)Purpose: Buffered serial console I/O using ESP-IDF UART peripheral
⚠️ Note: This is separate from the LED UART driver (uart/ subdirectory) which uses UART for WS2812 LED control.
Features:
Usage:
#include "platforms/esp/32/drivers/uart_esp32.h"
fl::UartEsp32 uart(UART_NUM_0); // Console UART
// Output
uart.write("Hello, world!");
uart.writeln("With newline");
// Input
int available = uart.available(); // Bytes in RX buffer
int byte = uart.read(); // Read single byte (-1 if no data)
// Status
bool buffered = uart.isBuffered(); // true if driver installed, false if ROM fallback
Architecture:
uart_driver_install() with RX/TX ring buffersesp_rom_output_tx_one_char) for output onlyFiles:
uart_esp32.h - Driver interfaceuart_esp32.cpp.hpp - Driver implementationUsed by:
io_esp_idf.hpp - EspIO class delegates all I/O to UartEsp32fl::print(), fl::println(), fl::available(), fl::read()uart/ subdirectory)Purpose: WS2812 LED control using UART waveform generation
Architecture:
Key difference from console UART:
Files:
uart/iuart_peripheral.h - Virtual interface for testabilityuart/uart_peripheral_esp.h - Real hardware implementationuart/channel_engine_uart.h - LED control driverDocumentation: See uart/README.md for complete LED UART documentation
io_esp_idf.hpp uses drivers)fl::print(), etc.)When adding a new driver (SPI, I2C, Timer, etc.):
Create driver files:
<peripheral>_esp32.h - Driver interface<peripheral>_esp32.cpp.hpp - Driver implementationFollow naming conventions:
<Peripheral>Esp32 (e.g., SpiEsp32, I2cEsp32)fl::read(), write(), transfer())Include proper headers:
FL_EXTERN_C_BEGIN/END for ESP-IDF C headersfl/stl/compiler_control.h for macrosplatforms/esp/esp_version.h for version detectionDocument:
Update this README:
All drivers handle ESP-IDF version differences:
Use ESP_IDF_VERSION macros for version-dependent code:
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
uart_config.source_clk = UART_SCLK_DEFAULT;
#elif ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
uart_config.source_clk = UART_SCLK_APB;
#endif
// IDF 3.x: source_clk field doesn't exist - skip it
All drivers leverage ESP-IDF's internal thread safety:
Example (UART):
// Task 1
uart.write("Task 1\n");
// Task 2 (concurrent)
uart.write("Task 2\n");
// Result: Both writes succeed, ESP-IDF serializes them internally
Drivers use minimal heap allocation:
Stack usage:
Drivers should be testable in isolation:
isInitialized(), isBuffered(), etc.)Integration testing:
bash validate)src/fl/stl/cstdio.hsrc/platforms/esp/io_esp.cpp.hpp