The EspSpi library provides a comprehensive SPI implementation for ESP32-C6 using ESP-IDF v5.5+.
It implements the BaseSpi interface and provides advanced features including DMA acceleration,
IOMUX optimization, multi-device management, and comprehensive error handling.
β¨ Key Features
π ESP-IDF v5.5+ Integration - Full compliance with latest ESP-IDF SPI Master driver
β‘ High-Speed Transfer - Up to 80 MHz with proper DMA configuration
ποΈ Flexible Modes - Support for all SPI modes (0, 1, 2, 3)
π DMA Support - Hardware-accelerated data transfer with configurable channels
ποΈ IOMUX Optimization - Direct pin-to-peripheral connections for maximum performance
π‘οΈ Thread-Safe Operations - RTOS mutex protection for multi-device management
π Multi-Device Support - Single bus with multiple device management
π Advanced Timing Control - Configurable CS setup/hold times and input delay compensation
π Hardware Support
Feature
ESP32-C6 Support
Description
|βββ|ββββββ|ββββ-|
SPI Hosts
SPI2_HOST (GP-SPI2)
General-purpose SPI host
Clock Sources
PLL_F80M, XTAL, RC_FAST
Configurable clock sources for power optimization
DMA Channels
0-3
Hardware DMA acceleration
IOMUX Pins
Direct connection
Up to 80 MHz operation
GPIO Matrix
Flexible routing
Up to 40 MHz operation
ποΈ Architecture
The EspSpi library follows a two-tier architecture:
boolInitialize()noexcept;// Initialize ESP-IDF SPI busboolDeinitialize()noexcept;// Clean up ESP-IDF resourcesintCreateDevice(consthf_spi_device_config_t&config);// Create device wrapperboolRemoveDevice(intdevice_id);// Remove device from busBaseSpi*GetDevice(intdevice_id);// Get device by IDboolIsInitialized()constnoexcept;// Check initialization status
EspSpiDevice
Represents a single SPI device on the bus, implementing the BaseSpi interface.
typedefstruct{hf_pin_num_tmosi_pin;// MOSI pin numberhf_pin_num_tmiso_pin;// MISO pin number hf_pin_num_tsclk_pin;// SCLK pin numberhf_host_id_thost;// SPI host ID (SPI2_HOST = 1)uint32_tclock_speed_hz;// Bus clock frequencyuint8_tdma_channel;// DMA channel (0xFF = auto, 0 = disabled)booluse_iomux;// Use IOMUX for maximum performanceuint32_ttimeout_ms;// Bus timeout in milliseconds}hf_spi_bus_config_t;
Device Configuration (hf_spi_device_config_t)
1
2
3
4
5
6
7
8
9
10
11
12
typedefstruct{uint32_tclock_speed_hz;// Device-specific clock frequencyhf_spi_mode_tmode;// SPI mode (0, 1, 2, 3)hf_pin_num_tcs_pin;// Chip select pinuint8_tqueue_size;// Transaction queue sizeuint8_tcommand_bits;// Command bits (0 = disabled)uint8_taddress_bits;// Address bits (0 = disabled)uint8_tdummy_bits;// Dummy bits between phasesuint32_tcs_ena_pretrans;// CS setup time (in SPI clock cycles)uint32_tcs_ena_posttrans;// CS hold time (in SPI clock cycles)hf_spi_clock_source_tclock_source;// Clock source selection}hf_spi_device_config_t;
// Create multiple devices on the same bushf_spi_device_config_tdevice1_config={};device1_config.clock_speed_hz=10000000;device1_config.mode=hf_spi_mode_t::HF_SPI_MODE_0;device1_config.cs_pin=21;hf_spi_device_config_tdevice2_config={};device2_config.clock_speed_hz=5000000;device2_config.mode=hf_spi_mode_t::HF_SPI_MODE_1;device2_config.cs_pin=22;intdevice1_id=spi_bus->CreateDevice(device1_config);intdevice2_id=spi_bus->CreateDevice(device2_config);BaseSpi*device1=spi_bus->GetDevice(device1_id);BaseSpi*device2=spi_bus->GetDevice(device2_id);device1->Initialize();device2->Initialize();// Use devices independentlydevice1->Transfer(tx_data1,rx_data1,4,1000);device2->Transfer(tx_data2,rx_data2,8,1000);
Use IOMUX Pins: Enable use_iomux = true for maximum performance
DMA Configuration: Use dedicated DMA channels for large transfers (>64 bytes)
Clock Source Selection: Use PLL_F80M_CLK for high-speed, XTAL_CLK for stability
Queue Size: Set appropriate queue size based on application needs
Memory Management
RAII Pattern: Use std::unique_ptr for automatic cleanup
Device Lifecycle: Always call Initialize() after CreateDevice()
Resource Cleanup: Let destructors handle cleanup automatically
Error Handling
Check Return Values: Always verify Initialize() and transfer results
Timeout Configuration: Set appropriate timeouts for your application
Error Logging: Use ESP-IDF logging for debugging
Thread Safety
Single Bus Access: The library is thread-safe, but avoid concurrent bus operations
Device Independence: Multiple devices can be used concurrently
Mutex Protection: All operations are internally protected
π Troubleshooting
Common Issues
βinvalid host_idβ Error
Cause: Incorrect host ID for ESP32-C6
Solution: Use static_cast<hf_host_id_t>(1) for SPI2_HOST
Large Transfer Failures (>256 bytes)
Cause: DMA configuration issues or memory constraints
Solution: Verify DMA channel configuration and reduce transfer size
Clock Glitches
Cause: Improper clock source or divider configuration
Solution: Use stable clock sources and verify TRM-compliant settings
Data Corruption
Cause: Small data optimization issues or timing problems
Solution: Ensure proper CS timing and verify data buffer management
Debugging Tips
Enable ESP-IDF Logging: Set log level to DEBUG for detailed information
Verify Pin Configuration: Check pin assignments and IOMUX usage
Monitor Clock Signals: Use logic analyzer to verify timing
Check DMA Status: Verify DMA channel availability and configuration
Performance Monitoring
1
2
3
4
5
6
7
// Measure transfer performanceuint64_tstart_time=esp_timer_get_time();hf_spi_err_tresult=device->Transfer(tx_data,rx_data,length,timeout);uint64_tend_time=esp_timer_get_time();uint64_ttransfer_time=end_time-start_time;ESP_LOGI(TAG,"Transfer %zu bytes in %llu ΞΌs",length,transfer_time);