Setup:
Module: ESP32-S3 WROOM-1
Dev-Board: ESP32-S3-DevKitC-1 v1.6
IDF: master (up to commit 0a64094a60194db3a4bf0ce87ad180999d538c49)
Host: Ubuntu 20.04
I'm currently evaluating the ESP32-S3 on WROOM board (ESP32-S3-DevKitC-1 v1.6). My use case requires the ADC to continuously convert several channels at higher, constant sampling rates. This has been previously achieved with an ESP32-S2 and "hand-made" usage of its SPI3-DMA ("hand-made" because ealier IDF versions did not provide an appropriate API for that and hence I built up a mechanism just like in the unit test code in components/driver/test/adc_dma_test).
With current IDF master the ADC API has fairly changed - just as the ADC HW inside ESP32-S3 (compared to S2). While trying to get used to the new API I was not able to reliably run the dma_read example from examples/peripherals/adc. Realiably means that often ADC1 did not provide any data on its configured channels (2 an 3 in the example). The HW obviously fires interrupts as the internal ring buffer is filled with elements. But some of them are completely empty:
Code: Select all
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd0108,len:0x1700
load:0x403b6000,len:0xbb8
load:0x403ba000,len:0x2f90
entry 0x403b6254
I (24) boot: ESP-IDF v5.0-dev-1712-g4a553510b7-dirty 2nd stage bootloader
I (25) boot: compile time 10:30:02
I (25) boot: chip revision: 0
I (28) boot.esp32s3: Boot SPI Speed : 80MHz
I (33) boot.esp32s3: SPI Mode : DIO
I (38) boot.esp32s3: SPI Flash Size : 2MB
I (43) boot: Enabling RNG early entropy source...
I (48) boot: Partition Table:
I (52) boot: ## Label Usage Type ST Offset Length
I (59) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (66) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (74) boot: 2 factory factory app 00 00 00010000 00100000
I (81) boot: End of partition table
I (86) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=09438h ( 37944) map
I (101) esp_image: segment 1: paddr=00019460 vaddr=3fc91320 size=0282ch ( 10284) load
I (105) esp_image: segment 2: paddr=0001bc94 vaddr=40374000 size=04384h ( 17284) load
I (115) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=1a2d4h (107220) map
I (139) esp_image: segment 4: paddr=0003a2fc vaddr=40378384 size=08f90h ( 36752) load
I (147) esp_image: segment 5: paddr=00043294 vaddr=50000000 size=00010h ( 16) load
I (153) boot: Loaded app from partition at offset 0x10000
I (153) boot: Disabling RNG early entropy source...
I (167) cpu_start: Pro cpu up.
I (167) cpu_start: Starting app cpu, entry point is 0x403751b8
0x403751b8: call_start_cpu1 at /home/andre.rex/build/esp/esp-idf/components/esp_system/port/cpu_start.c:152
I (0) cpu_start: App cpu up.
I (181) cpu_start: Pro cpu start user code
I (181) cpu_start: cpu freq: 160000000 Hz
I (181) cpu_start: Application information:
I (184) cpu_start: Project name: adc
I (189) cpu_start: App version: v5.0-dev-1712-g4a553510b7-dirty
I (196) cpu_start: Compile time: Feb 25 2022 10:29:58
I (202) cpu_start: ELF file SHA256: 366016325cfb3b75...
I (208) cpu_start: ESP-IDF: v5.0-dev-1712-g4a553510b7-dirty
I (215) heap_init: Initializing. RAM available for dynamic allocation:
I (222) heap_init: At 3FC94560 len 0004BAA0 (302 KiB): D/IRAM
I (229) heap_init: At 3FCE0000 len 0000EE34 (59 KiB): STACK/DRAM
I (235) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (242) heap_init: At 600FE000 len 00002000 (8 KiB): RTCRAM
I (248) spi_flash: detected chip: gd
I (252) spi_flash: flash io: dio
W (256) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (270) sleep: Configure to isolate all GPIO pins in sleep state
I (276) sleep: Enable automatic switching of GPIO sleep configuration
I (284) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (304) gpio: GPIO[3]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (304) gpio: GPIO[4]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (314) gpio: GPIO[11]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (324) ADC DMA: adc_pattern[0].atten is :0
I (334) ADC DMA: adc_pattern[0].channel is :2
I (334) ADC DMA: adc_pattern[0].unit is :0
I (344) ADC DMA: adc_pattern[1].atten is :0
I (344) ADC DMA: adc_pattern[1].channel is :3
I (354) ADC DMA: adc_pattern[1].unit is :0
I (354) ADC DMA: adc_pattern[2].atten is :2
I (364) ADC DMA: adc_pattern[2].channel is :0
I (364) ADC DMA: adc_pattern[2].unit is :1
I (374) TASK:: ret is 0, ret_num is 256
I (374) ADC DMA: Unit: 1,_Channel: 0, Value: 0
I (384) ADC DMA: Unit: 2,_Channel: 0, Value: 23f
I (384) ADC DMA: Unit: 1,_Channel: 0, Value: 0
I (394) ADC DMA: Unit: 2,_Channel: 0, Value: 23f
I (394) ADC DMA: Unit: 1,_Channel: 0, Value: 0
I (404) ADC DMA: Unit: 2,_Channel: 0, Value: 23f
I (404) ADC DMA: Unit: 1,_Channel: 0, Value: 0
I (414) ADC DMA: Unit: 2,_Channel: 0, Value: 23d
I (414) ADC DMA: Unit: 1,_Channel: 0, Value: 0
I (424) ADC DMA: Unit: 2,_Channel: 0, Value: 23f
I (424) ADC DMA: Unit: 1,_Channel: 0, Value: 0
I (434) ADC DMA: Unit: 2,_Channel: 0, Value: 23f
I (434) ADC DMA: Unit: 1,_Channel: 0, Value: 0
...
From the above log one can see that, although ADC1 channel 2 and 3 are added to pattern table, the result entry for ADC1 only contains single values 'Unit: 1,_Channel: 0, Value: 0'. Transferring it to the raw data it equals 0x0000'0000 and is obviously wrong.
Unfortunately the currently available Technical Reference Manual of ESP32-S3 (v0.4 just release yesterday) still lacks the section about ADC (any references to it are marked as "[to be added later]"). So I reverse-engineered the IDF code trying to understand how it may work. While doing this and adding a few printf's the example suddenly provided valid ADC1 data (even for both channels!) - although there was no functional change!
Example: Only adding following line to adc_ll.h:adc_ll_digi_set_pattern_table() (in components/hal/esp32s3/include/hal) after writing sar1_tab_patt register entry made the example "work":
Code: Select all
printf("adc_ll.h:%d sar1_patt_tab[%d] = %x\n", __LINE__, index, APB_SARADC.sar1_patt_tab[index].sar1_patt_tab);
Code: Select all
printf("adc_ll.h:%d sar1_patt_tab[%d] = %x\n", __LINE__, index, tab);
The first one actually introduced a physical read from the SAR1_PATT_TAB HW register (while the second one only dumps the previously calculated value tab). But I wouldn't expect any behavioral differences between both calls.
Unfortunately all ADC DMA related unit tests have been disabled somewhere between IDF 4.4 release and current master HEAD so I'm not sure at all whether this use case is actually functional with current IDF state.
The magic question now is: Might there be any bug in IDF interacting with ESP32-S3 HW (e.g. providing wrong DMA link list descriptors) or is there any additional, specific requirement for the ESP32-S3 ADC - or even any known HW issue? I know these are very vague questions but I'm actually stuck in digging further into this issue. Maybe there is any one who got such use case reliably working.
Best regards
André