feat(esp32): digital ADC + DMA for MCPWM low-side current sense#543
feat(esp32): digital ADC + DMA for MCPWM low-side current sense#543uLipe wants to merge 7 commits into
Conversation
Port chip-specific DMA shims (I2S on ESP32, SPI3 on S2, GDMA on S3/C6) and shared timing constants aligned with espFoC isensor_adc.
Wire MCPWM timer TEZ/TEP to ADC_TASK_START0 so conversions are not kicked from CPU ISRs on chips that lack ETM (ESP32, ESP32-S2).
Configure adc_hal digi pattern/DMA, process frames into a shared buffer, and re-arm after each conversion without blocking MCPWM callbacks.
Select LEGACY, DIGI_SW, or DIGI_ETM paths and keep MCPWM sync logic out of the core driver files.
Prefer digi+DMA on init; use ETM on S3/C6 or MCPWM ISR software trigger on ESP32/S2, with legacy adcRead() as fallback.
Link adc_hal DMA directly to ESP32CurrentSenseParams::adc_buffer, trim the EOF ISR to cache sync and rearm only, and decode samples on read. Allocate params from DMA-capable heap.
|
@askuric @runger1101001 PTAL this is something that resulted in a HUGE reduction of CPU busy since mostly of the PWM->ADC pipeline is handled by the hardware, PWM generate event to ETM to start the ADC conversion and the DMA stores the channels converted directly in the adc_buffer. with a single interrupt. Also the ADC Digi is used, allowing faster sample rates and compatibillity across all esp32. |
8e1e93c to
c3c6407
Compare
Wrap ESP32 digi ADC sources in ARDUINO_ARCH_ESP32 guards so AVR CI builds do not pull sdkconfig.h. Select DMA backend per chip (I2S / SPI3 / GDMA) via internal.h so classic ESP32 and S2 do not compile GDMA. Include esp32_mcu.h before MCPWM guard in lowside.cpp.
c3c6407 to
a76ec58
Compare
|
@askuric @runger1101001 CI is happy now! Happy to hear your comments, I hope with this modification to extract the maximum efficiency from ESP32 ADC infrastructure. Even though it not imply higher sample rates (> 100K, except on esp32 and esp32c5 which is possible to achieve 2MSPS), it will push the ADC to the maximum supported while
Exceptions apply to esp32 and s2 which uses two interrupts MCPWM fires the scan ADC but the rest of the chain is done via DMA. AS the PR description says the idea is block the CPU at minimum for the hard real time things while guarantee the timings and sample point of the current measurement. |
Summary
Adds digital SAR ADC + DMA for ESP32 MCPWM low-side current sensing (ported from espFoC
isensor_adc), integrated into existingLowsideCurrentSensewithout API changes.Three backends, selected at init:
adcRead(), one phase per ISR (~10 µs each)esp32_adc_digi_trigger_software()— digi pattern + DMAADC_TASK_START0)DMA shims: I2S (ESP32), SPI3 (S2), GDMA (S3/C6+). Pattern rate 80 kHz, 2 channels,
convert_limit = 2(aligned with espFoC).Why this approach
Low-side FOC needs currents at a fixed PWM phase. The default ADC_READ path uses MCPWM callbacks +
adcRead(), which:i_a/i_b)DIGI_* modes run the hardware pattern sequencer and move results by DMA. On S3/C6, ETM starts the ADC without a CPU ISR on the trigger edge.
Zero-copy DMA path
For
DIGI_SW/DIGI_ETM, DMA writesadc_digi_output_data_t[]directly intoESP32CurrentSenseParams::adc_buffer(DMA-capableheap_capsalloc). The EOF ISR only:with no per-sample copy loop.
_readADCVoltageLowSide()decodes the 12-bit field from the digi format on access.Problems addressed
adcReadbusy-wait in the trigger ISR on ETM; SW trigger only kicks the controller)Limitations
adc_bufferlayout differs between ADC_READ (plainint) and DIGI_* (adc_digi_output_data_toverlay)Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Test Configuration/Setup: