2023-09-13 11:54 AM
Using HAL_ADCEx_Calibration_Start() to calibrate the ADC. This function always returns HAL_ERROR.
Debugging shows its failing after it collects the 8 samples and attempting to disable the ADC is timing out. (ie. if ((HAL_GetTick() - tickstart) > ADC_DISABLE_TIMEOUT) is TRUE.)
Using CubeMX to generate drivers. CubeMX version 6.8.1
Note: ADC conversion are working IF I don't calibrate.
Thanks for your help.
Solved! Go to Solution.
2023-09-14 07:28 AM - edited 2023-09-14 07:35 AM
Hello @BrianB,
There is an issue on STM32G0 ADC during calibration due to delay needed between ADC enable and disable.
As a work-around: A minimum delay must be implemented between ADC enable and ADC disable.
The Fix proposal is to wait for 2 ADC clock cycles between ADC enable and disable (worst case: 256 CPU cycles) .
Our development team is very aware of this issue and working to resolve this, and the fix will be available in the next release of STM32CubeG0 firmware package.
Thank you for your understanding while we work on this.
Imen
2023-09-13 12:51 PM
Hello @BrianB and welcome to the Community,
Thank you for having reported this issue.
I check this and come back to you soon with update.
Imen
2023-09-13 01:33 PM - edited 2023-09-14 05:12 AM
Hello @BrianB
Have you ensured that the ADC is off because as you can see in the user manual of the STM32CUBEG0:
Also, in other boards, if the ADC work in a low frequency that can be a cause of error for HAL_ADCEx_Calibration_Start().
Best regards.
II
2023-09-14 07:28 AM - edited 2023-09-14 07:35 AM
Hello @BrianB,
There is an issue on STM32G0 ADC during calibration due to delay needed between ADC enable and disable.
As a work-around: A minimum delay must be implemented between ADC enable and ADC disable.
The Fix proposal is to wait for 2 ADC clock cycles between ADC enable and disable (worst case: 256 CPU cycles) .
Our development team is very aware of this issue and working to resolve this, and the fix will be available in the next release of STM32CubeG0 firmware package.
Thank you for your understanding while we work on this.
Imen
2023-09-14 12:11 PM
Hi,
The problem was low ADC frequency. It was 2 Mhz. I increased the ADC frequency to 8 MHz and the ADC calibration is working correctly.
Thanks for your help.
2023-09-15 09:34 AM
Really glad to know you overcame this problem.
Thank you once more for your understanding and contribution.
2024-01-29 02:22 PM
Thanks @Imen.D
This really needs to be in the errata; not everyone uses the Cube firmware packages or even HAL.
I spent hours chasing this: ADC calibration often hung after hw reset without this magic delay. Inserting a small (10uS or less) delay after disabling the ADC and before starting calibration reliably cures the problem.
// Disable ADC prior to calibration
ADC1->CR = ADC_CR_ADDIS;
// Wait for ADC disabled
while (ADC1->CR & (ADC_CR_ADCAL | ADC_CR_ADSTART |
ADC_CR_ADSTP | ADC_CR_ADDIS |
ADC_CR_ADEN));
// A minimum delay is required after enabling or disabling the ADC
delay_us(10);
// Begin calibration process
ADC1->CR = ADC_CR_ADCAL;
// Wait for calibration to finish
while ((ADC1->CR & ADC_CR_ADCAL)) ;
// Clear end-of-calibration and ready flags
ADC1->ISR |= (ADC_ISR_EOCAL | ADC_ISR_ADRDY);
// Enable ADC
ADC1->CR = ADC_CR_ADEN;
// Wait for ADC ready
while (!(ADC1->ISR & ADC_ISR_ADRDY));
2024-03-23 02:11 AM
Hi @Imen.D ,
We surely can agree on that "fixing" this issue in Cube is irrelevant, and it outght to be properly documented, as an erratum together with a correctly and completely described workaround.
Since you've posted above, several 'G0 Errata have been published, e.g. ES0418 for 'G071, and I can't see mentioned issue in those.
So naturally, several questions arise:
- is this issue related to all 'G0 or only to 'G0B0/'G0B1/'G0C1?
- is this issue related to any other STM32 family, or is it 'G0-specific only?
- in the workaround you write "maximum 256 processor cycles worst case" yet 2 ADC cycles with 256 prescaler that would be 512 processor cycles (also see next item), wouldn't it?
- given flexibility of ADC source, talking about "processor cycles" in workaround is IMO entirely incorrect. ADC clock may be asynchronous to processor/system clock (btw. the description of what PCLK is in context of ADC, is a real mess at various points of RM and would really need thorough revision).
- is any workaround available which would be based entirely on ADC registers reads/writes and would ensure the required delay? This would make the clocking discussion above less important.
- @DAlbe.3 above mentions a need for delay *not* between ADC enable and disable, as you've said, but between ADC disable and calibration. So, does the problem pertain to this combination of operations, too? And also to any other combination of operations?
Can you please comment on these?
Thanks,
JW
2024-03-26 04:44 PM
Hello @DAlbe.3 , @waclawek.jan ,
Thank you for sharing your feedback. Please find below more clarification:
So naturally, several questions arise:
- is this issue related to all 'G0 or only to 'G0B0/'G0B1/'G0C1?
- is this issue related to any other STM32 family, or is it 'G0-specific only?
This issue is related to a specific ADC peripheral version present on STM32G0, STM32WL, STM32C0 (all products within these series).
- in the workaround you write "maximum 256 processor cycles worst case" yet 2 ADC cycles with 256 prescaler that would be 512 processor cycles (also see next item), wouldn't it?
You're right, it's a typo error with number 256 in my previous post, which should be 512.
- given flexibility of ADC source, talking about "processor cycles" in workaround is IMO entirely incorrect. ADC clock may be asynchronous to processor/system clock (btw. the description of what PCLK is in context of ADC, is a real mess at various points of RM and would really need thorough revision).
This is correct, the delay unit is ADC kernel clock cycles (2 cycles).
- The delay implemented in HAL driver is based on code execution loop, therefore count in CPU cycles.
- An alternate solution could be a delay based on a timer (SysTick, timer peripheral, …)
About PLCK: this is clock of bus APB (The reference manual mentions:
" The HCLK clock and PCLK clock are used for clocking the AHB and the APB domains, respectively.
The peripherals are clocked with the clocks from the bus they are attached to (HCLK for AHB, PCLK for APB) except:"
So, ADC kernel clock can be derived from PCLK or other clock source, with frequency divided through a prescaler.
- is any workaround available which would be based entirely on ADC registers reads/writes and would ensure the required delay? This would make the clocking discussion above less important.
The timing constraint comes from interface between bus clock (APB) and ADC peripheral (synchronization constraint). Since upstream of ADC, status based on ADC registers is not possible.
- @DAlbe.3 above mentions a need for delay *not* between ADC enable and disable, as you've said, but between ADC disable and calibration. So, does the problem pertain to this combination of operations, too? And also to any other combination of operations?
In fact, the delay is required for ADC disable to be effective (therefore, applicable between ADC disable and calibration start, or between ADC disable and calibration factor set).
Based on your feedback, a request is ongoing to update the impacted Reference manuals with the missing information about delay.
@waclawek.jan Thank you again for the continued feedback; it is much appreciated!
Hope I answered your questions.
2024-03-27 08:51 AM