ADC on ESP32-S3 in continouous DMA conversion delivers invalid data

arex-ebee
Posts: 10
Joined: Thu Dec 16, 2021 1:44 pm

ADC on ESP32-S3 in continouous DMA conversion delivers invalid data

Postby arex-ebee » Fri Feb 25, 2022 2:43 pm

Hi folks,

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

...
The above log shows the dma_read example application where ADC1 ch2 (GPIO3) and ADC2 ch0 (GPIO11) are connected to the same voltage.
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);
while

Code: Select all

printf("adc_ll.h:%d  sar1_patt_tab[%d] = %x\n", __LINE__, index, tab);
did not.

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é

XiangH
Posts: 3
Joined: Mon Feb 28, 2022 9:09 am

Re: ADC on ESP32-S3 in continouous DMA conversion delivers invalid data

Postby XiangH » Tue Mar 01, 2022 7:20 am

I had this problem too, but I was developing with the latest ARDUINO framework,

arex-ebee
Posts: 10
Joined: Thu Dec 16, 2021 1:44 pm

Re: ADC on ESP32-S3 in continouous DMA conversion delivers invalid data

Postby arex-ebee » Mon Mar 07, 2022 10:47 am

Hi XiangH,

thanks for your reply.
XiangH wrote:
Tue Mar 01, 2022 7:20 am
I had this problem too, but I was developing with the latest ARDUINO framework,
When you say you "had" this problem does it mean you found a solution? As the Arduino framework is "just" a further abstraction layer it may be worth if you could share your findings.

Regards
André

XiangH
Posts: 3
Joined: Mon Feb 28, 2022 9:09 am

Re: ADC on ESP32-S3 in continouous DMA conversion delivers invalid data

Postby XiangH » Thu Mar 10, 2022 5:00 am


arex-ebee
Posts: 10
Joined: Thu Dec 16, 2021 1:44 pm

Re: ADC on ESP32-S3 in continouous DMA conversion delivers invalid data

Postby arex-ebee » Thu Mar 10, 2022 9:13 am

Thanks for that hint. I guess you actually mean https://github.com/espressif/esp-idf/issues/8485, right?

felixcollins
Posts: 125
Joined: Fri May 24, 2019 2:02 am

Re: ADC on ESP32-S3 in continouous DMA conversion delivers invalid data

Postby felixcollins » Thu May 12, 2022 3:45 am

I had a very similar issue on an STM32. It turned out that the memory cache was not being invalidated, because the DMA was writing the values. The DMA writes do not go anywhere near the memory cache. My fix in that case was to use the memory cache HAL API and invalidate the entire area used as a DMA buffer. After that the CPU will read the real values from memory rather than the old cached values.

Who is online

Users browsing this forum: Google [Bot] and 137 guests