ESP32S3 : adc_line_vref_to_gpio() example needed

On the ESP32S3, the ADC voltage reference Vref varies a lot from chip to chip and needs to be measured with a voltmeter. To do so, adc_line_vref_to_gpio() lets you route Vref to a GPIO pin. The problem is that I can’t figure out what arguments I should pass to this function.

I defined 9 ADC channels:

#define ADC_GPIOS   { GPIO1, GPIO2, GPIO4, GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO11 }

GPIO11 is a channel of ADC2. One must pass an ADC2 channel to adc_line_vref_to_gpio(), it seems. As its 1st or 2nd argument ?

I initialized all ADC lines, then all of them except GPIO11:

// ADC_NUM_CH = 9
for(unsigned int i=0 ; i<ADC_NUM_CH ; i++) {
    if(adc_init(ADC_LINE(i))) {
        printf("adc_init() >> ERROR: invalid ADC line i = %d, line = %d\n", i, ADC_LINE(i));
    }
}

I tried this:

if(adc_line_vref_to_gpio(ADC_LINE(8), GPIO11))
    printf("%s() >> Error: can't output Vref\n", __FUNCTION__);
// or:
if(adc_line_vref_to_gpio(ADC_LINE(8), GPIO12))
    printf("%s() >> Error: can't output Vref\n", __FUNCTION__);

but the application dies with this message: “#! exit 1: powering off”.

After inspecting the code, I think that I kind of figured out what arguments the function expects, but I think that there is a bug in the ESP SDK.

It turns out that the 1st argument of adc_line_vref_to_gpio() is only useful for checks. It is an index in the ADC_GPIOS array in the 1st post of this thread and should equal e.g. 8, the index of GPIO11, which is a channel of ADC2. The 2nd argument is really the one that is passed to the ESP32 SDK, and should also be a channel of ADC2, so GPIO11 should do.

adc_line_vref_to_gpio() calls adc_vref_to_gpio() in $RIOTBASE/build/pkg/esp32_sdk/components/driver/adc_common.c. It translates GPIO11 to channel number 0 into the ch variable, because it is the 1st line of ADC2. GPIO12 would translate to 1, etc.

Then, adc_vref_to_gpio() calls adc_hal_vref_output(ADC_NUM_2, ch, true) at line 670 of the same file. This is where the crash occurs. I couldn’t find the code of this last function.

In 2022, some guys said that adc_vref_to_gpio() was not implemented. Not sure what they meant exactly. Anyway, it looks like a SDK bug to me. As it can be mitigated by a manual calibration, I’ll stop investigating this issue.