Macro LL_ADC_SetChannelSingleDiff behaves incorrectly when setting a channel to single ended #53
Labels
adc
Analog-to-Digital Converter
bug
Something isn't working
hal
HAL-LL driver-related issue or pull-request.
needs clarification
Needs clarification or inputs from the user
Describe the set-up
Describe the bug
The macro function
LL_ADC_SetChannelSingleDiff
should clear bitADCx->DIFSEL[ 1 << n ]
when setting channel n to single-ended. Instead, the bit is set. This causes the channel to be incorrectly set to differential, resulting in invalid measurements.See STM32G4 Reference Manual, RM0440 Rev 8 section 21.7.21.
How To Reproduce
Indicate the global behavior of your application project.
When running the application, ADC readings are incorrect. This makes it impossible to verify that the USB Type-C PD VBUS voltage is safe.
The modules that you suspect to be the cause of the problem (Driver, BSP, MW ...).
This macro function in HAL-LL Drivers.
The use case that generates the problem.
Generate default project following link below, and measure VBUS voltage by setting a breakpoint in the relevant function.
How we can reproduce the problem.
Generate a project following this guide on the ST Wiki using Nucleo-G474RE and X-NUCLEO-SNK1M1 boards.
Run project in Debug mode. Place a breakpoint on line
*pVoltage = voltage
in functionBSP_USBPD_PWR_VBUSGetVoltage
, fileUSBPD/usbpd_pwr_user.c
. Observe that when a USB charger is plugged into the USB Type-C port, the voltage calculated does not match expectations.Because the ADC is running in continuous mode, you can also stop execution and inspect register ADC1->DR. When no USB Type-C device is plugged in, it should be close to 0x0. It will instead be much higher.
Also observe that when placing a breakpoint on the call to
LL_ADC_SetChannelSingleDiff
in fileDrivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_adc.c
(line 2885 in attached project), ADC1->DIFSEL is 0x0 before the call and 0x8000 after the call (bit 15 has been set).Additional context
The macro (in file
stm32g4xx_hal_adc.h
) currently looks like this (comment is not mine):Channel
is(1 << n)
wheren
is channel number, plus some other stuff beyond bit 24, which is masked out byADC_SINGLEDIFF_CHANNEL_MASK
ADC_SINGLEDIFF_CHANNEL_MASK
is 0x7FFFFADC_DIFSEL_DIFSEL
is 0x7FFFFADC_SINGLEDIFF_CHANNEL_SHIFT_MASK
is 24So the simplified expansion is:
In the case where n=15 and SingleDiff=0 (which should set the channel to single-ended), this expands to:
which expands to:
Bit 15 is set by this macro.
Solution
There is a project
SNK1M1_Sink
in X-CUBE-TCPP (the STM32CubeIDE project is inX-CUBE-TCPP\4.2.0\Projects\NUCLEO-G474RE\Applications\USB_PD\SNK1M1_Sink\STM32CubeIDE
). This project is very similar to the example project created by following the Wiki, but it has a different version ofstm32g4xx_ll_adc.h
. This version has a different macro that appears to work correctly:Screenshots
None.
Project
Demo project files are attached: stm32g4xx_adc_bug.zip.
The text was updated successfully, but these errors were encountered: