cancel
Showing results for 
Search instead for 
Did you mean: 

ADC calibration problem for Stm32CubeIde?

adaniel
Associate III

 Chip:   STM32L030

 Trying to calibrate the ADC at startup with the following code into the initialization procedure:

   ADC1->CR |= 0X80000000;      // calibration started

   while (!(ADC1->ISR & 0X800));   // waiting for the calibration to finish

 When compiled with Atollic, version 9.2.0, this code works perfectly. But when compiled with Stm32CubeIde, it gets trapped into the calibration command which never finish!

11 REPLIES 11
TDK
Guru

EOCAL is set at the end of the calibration. You're waiting until it's set. This is a race condition. So either the loop will immediately pass (if calibration isn't done yet), or it will never exit.

This is a software bug, not a CubeIDE issue.

0693W000006Gd98QAC.png

If you feel a post has answered your question, please click "Accept as Solution".
adaniel
Associate III

This is exactly what my code does! If it is not a CubeIDE issue, how do you explain that Atollic 9.2.0 compiles successfully?

Yeah, you're right. I misread what was going on at first.
Still think it's a software bug, but you didn't include much of the code. It could also be a silicon bug that may be addressed in an errata.
STM32CubeIDE uses the GCC compiler under the hood which is quite mature. Unlikely the compiler is the issue. The IDE is just the UI. You could examine the assembly instructions that each one of them generates if you wanted to investigate that lead further.
If you feel a post has answered your question, please click "Accept as Solution".

At your request, here is my complete initialization code. I don't think it is very enlighting.

int   adsetup() {

   int   n = 10000;       // timeout

   RCC->IOPENR |= 1;       // port A enabled

   GPIOA->MODER &= 0XFFFFFFFC;    // Analog input at PA0

   GPIOA->PUPDR &= 0XFFFFFFFC;     // No pull-up at PA0

   RCC->APB2ENR |= 0X200;        // ADC clock started

   if (ADC1->CR & 1) ADC1->CR |= 2;  // ADC setup

   ADC1->CR |= 0X80000000;       // ADC calibration started

   while (!(ADC1->ISR & 0X800)) { // waiting for the calibration to finish

      watchdog();       // macro to refresh the watchdog

      if (!--n) return FALSE;    // failure exit

   }

   ADC1->ISR |= 0X800;       // clearing EOCAL

   ADC1->CHSELR = 1;       // Channel 0 selected

   ADC1->SMPR |= 7;       // 160 ADC cycles sampling time (320usec)

   ADC1->CFGR1 = 0XC0A000;       // continuous conversion, analog watchdog enabled

   ADC1->IER = 0X80;       // analog watchdog interrupt enabled

   ADC1->TR = 0XA000600;       // analog watchdog window setup

   ADC1->CFGR2 |= 0X8000009D;    // ADC clock setup, over-sample = 16, shift = 4

   ADC1->CR |= 5;          // ADC started

   return TRUE;          // successfull initialization

}

Piranha
Chief II

> Chip:   STM32L030

There is no such chip...

Use code tags when posting code. And use the readable CMSIS defined bit field names.

if (ADC1->CR & 1) ADC1->CR |= 2;  // ADC setup
   ADC1->CR |= 0X80000000;       // ADC calibration started
   while (!(ADC1->ISR & 0X800)) { // waiting for the calibration to finish
      watchdog();       // macro to refresh the watchdog
      if (!--n) return FALSE;    // failure exit
   }
   ADC1->ISR |= 0X800;       // clearing EOCAL

Do not use read-modify-write on ISR register and be careful with CR as it also has "rs" bits like ISR. Probably the most important - you are not waiting for ADDIS command to complete. And ultimately I would want the watchdog to act if the code gets stuck in that loop...

adaniel
Associate III

Thanks Piranha for your attention, but it doesn't help:

1 - STM32L030F4P6 chip on my desk, and on my board!

2 - Read-modify-write instructions? there is no such a warning in the datasheet. I also have separated them in 2 parts with no avail.

3 - ADDIS: I added a waiting loop with no result

4 - You ignore the fact that Atollic 9.2.0 compiles successfully!

5 - The watchdog works and the loop exits FALSE.

Hard to admit that you have a problem? I don't, I completed my project without ADC calibration.

My question is definitely not answered.

TDK
Guru

> 1 - STM32L030F4P6 chip on my desk, and on my board!

Can you link the product page to prove that it does exist? Google shows no hits. Maybe you have a counterfeit part. Hard to prove a negative.

> 2 - Read-modify-write instructions? there is no such a warning in the datasheet. I also have separated them in 2 parts with no avail.

> ADC1->ISR |= 0X800; // clearing EOCAL

This clears ALL flags, not just EOCAL. This is covered in the reference manual (for STM32L0X0). To clear only EOCAL:

ADC1->ISR = ADC_ISR_EOCAL;

There are other requirements for starting calibration and you're not checking for them all. From the reference manual (for STM32L0X0):

The software is allowed to set ADCAL only when the ADC is disabled (ADCAL=0, ADSTART=0, ADSTP=0, ADDIS=0 and ADEN=0).

If you feel a post has answered your question, please click "Accept as Solution".
adaniel
Associate III

> 1 - Sorry, my mistake, the chip is STM32L010F4P6

> 2 - Clearing all flags? good, this is what I want

> 3 - ADCAL=0, ADSTART=0, ADSTP=0, ADDIS=0 and ADEN=0.: this is the RESET state

> 4 - Please stop seeking what is wrong in the code: it works fine with ATOLLIC. STM32CUBE has a problem!

> 5 - In the past, you gave me an excellent advice: to look at the generated assembler code. I would like to do that. I cannot find any assembler window.

TDK
Guru

> 4 - Please stop seeking what is wrong in the code: it works fine with ATOLLIC. STM32CUBE has a problem!

Okay, must be an STM32CubeIDE issue then if you say the code is right. Use ATOLLIC instead.

Good luck.

If you feel a post has answered your question, please click "Accept as Solution".