cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U599 Fail extended calibration when using HAL_ADCEx_Calibration_Start() API

desmond
Associate II

Hello, 

I am facing an issue when trying to calibrate the STM32U5. 

I am using the API call `HAL_ADCEx_Calibration_Start()`, SDK Version: 1.3.0.

When I run the `HAL_ADCEx_Calibration_Start()` the board hangs and goes off into a limbo state. Even the debugger has a hard time reconnecting. 

I've noticed the issue is directly related to the code snippet below in `HAL_ADCEx_Calibration_Start()` 

# Original code at line 213 of `stm32u5xx_hal_adc_ex.c`

```

MODIFY_REG(hadc->Instance->CR, ADC_CR_CALINDEX, 0x9UL << ADC_CR_CALINDEX_Pos);
MODIFY_REG(hadc->Instance->CALFACT2, 0x00FF0000UL, 0x00020000UL);
SET_BIT(hadc->Instance->CALFACT, ADC_CALFACT_LATCH_COEF);

```

 

The code that works

```

MODIFY_REG(hadc->Instance->CR, ADC_CR_CALINDEX, 0x9UL << ADC_CR_CALINDEX_Pos);
HAL_Delay(1);
MODIFY_REG(hadc->Instance->CALFACT2, 0x00FF0000UL, 0x00020000UL);
HAL_Delay(1);
SET_BIT(hadc->Instance->CALFACT, ADC_CALFACT_LATCH_COEF);
HAL_Delay(1);

```

 

3 REPLIES 3
Issamos
Lead II

Hello @desmond 

I suggest you to take a look at the post1 and post2. They may help you.

Best regards.

II

Everything in post 1 I am already doing: 

```

static inline void enableVoltageScaling(void)
{
/*These have no effect if already enabled*/
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWR_EnableBkUpAccess();
HAL_PWREx_EnableVddA();
__HAL_RCC_LSI_ENABLE();
while (READ_BIT(RCC->BDCR, RCC_BDCR_LSIRDY) == 0){};

const HAL_StatusTypeDef rc = HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
assert(rc == HAL_OK);
}

void msp_clocksInit(void)
{
msp_updateSystemCoreClock();
HAL_Init();
enableVoltageScaling();

/* Require to active some clocks.
* Clocks running PORTG onwards require this.*/
HAL_PWREx_EnableVddIO2();

```

Post 2 is onto something however this has nothing with enabling and disable the ADC because if it did I could add a delay after line 209 when the ADC enables but before setting up the registers and it would work. But it doesn't.

The issue is I have delay between each one of the register setup that I illustrated above. Otherwise the board hangs and causes issues.

Please let me know the correct procedure for enabled extended calibration the reference manual is not clear as to all the prerequisites needed. Additionally the SDK code appears to be doing a few things differently than what is described in the reference manual. 

I have done more digging and found the following.

The assembly below are related to the C code below

```
MODIFY_REG(hadc->Instance->CR, ADC_CR_CALINDEX, 0x9UL << ADC_CR_CALINDEX_Pos);
MODIFY_REG(hadc->Instance->CALFACT2, 0x00FF0000UL, 0x00020000UL);
SET_BIT(hadc->Instance->CALFACT, ADC_CALFACT_LATCH_COEF);
```

The code with no optimization works and it's likely because the number instruction are more giving the ADC time to latch the values written into the registers. So this is a clear indication that a race condition exist with the hardware and the C code is not deterministic enough to handle it. I think a certain number cycles are required for the ADC to correctly latch the data written into the register.


# ASM with `-o0 -g3` optimization
No optimization. This works


```
MODIFY_REG(hadc->Instance->CR, ADC_CR_CALINDEX, 0x9UL << ADC_CR_CALINDEX_Pos);
800fa6c: 68fb ldr r3, [r7, #12]
800fa6e: 681b ldr r3, [r3, #0]
800fa70: 689b ldr r3, [r3, #8]
800fa72: f023 6270 bic.w r2, r3, #251658240 ; 0xf000000
800fa76: 68fb ldr r3, [r7, #12]
800fa78: 681b ldr r3, [r3, #0]
800fa7a: f042 6210 orr.w r2, r2, #150994944 ; 0x9000000
800fa7e: 609a str r2, [r3, #8]
MODIFY_REG(hadc->Instance->CALFACT2, 0x00FF0000UL, 0x00020000UL);
800fa80: 68fb ldr r3, [r7, #12]
800fa82: 681b ldr r3, [r3, #0]
800fa84: f8d3 30c8 ldr.w r3, [r3, #200] ; 0xc8
800fa88: f423 027f bic.w r2, r3, #16711680 ; 0xff0000
800fa8c: 68fb ldr r3, [r7, #12]
800fa8e: 681b ldr r3, [r3, #0]
800fa90: f442 3200 orr.w r2, r2, #131072 ; 0x20000
800fa94: f8c3 20c8 str.w r2, [r3, #200] ; 0xc8
SET_BIT(hadc->Instance->CALFACT, ADC_CALFACT_LATCH_COEF);
800fa98: 68fb ldr r3, [r7, #12]
800fa9a: 681b ldr r3, [r3, #0]
800fa9c: f8d3 20c4 ldr.w r2, [r3, #196] ; 0xc4
800faa0: 68fb ldr r3, [r7, #12]
800faa2: 681b ldr r3, [r3, #0]
800faa4: f042 7280 orr.w r2, r2, #16777216 ; 0x1000000
800faa8: f8c3 20c4 str.w r2, [r3, #196] ; 0xc4

tmp_hal_status = ADC_Disable(hadc);
```


# ASM with `-02` optimization
Optimized this does not work.

```
MODIFY_REG(hadc->Instance->CR, ADC_CR_CALINDEX, 0x9UL << ADC_CR_CALINDEX_Pos);
8009ec0: 6823 ldr r3, [r4, #0]
tmp_hal_status = ADC_Disable(hadc);
8009ec2: 4620 mov r0, r4
MODIFY_REG(hadc->Instance->CR, ADC_CR_CALINDEX, 0x9UL << ADC_CR_CALINDEX_Pos);
8009ec4: 689a ldr r2, [r3, #8]
8009ec6: f022 6270 bic.w r2, r2, #251658240 ; 0xf000000
8009eca: f042 6210 orr.w r2, r2, #150994944 ; 0x9000000
8009ece: 609a str r2, [r3, #8]
MODIFY_REG(hadc->Instance->CALFACT2, 0x00FF0000UL, 0x00020000UL);
8009ed0: f8d3 20c8 ldr.w r2, [r3, #200] ; 0xc8
8009ed4: f422 027f bic.w r2, r2, #16711680 ; 0xff0000
8009ed8: f442 3200 orr.w r2, r2, #131072 ; 0x20000
8009edc: f8c3 20c8 str.w r2, [r3, #200] ; 0xc8
SET_BIT(hadc->Instance->CALFACT, ADC_CALFACT_LATCH_COEF);
8009ee0: f8d3 20c4 ldr.w r2, [r3, #196] ; 0xc4
8009ee4: f042 7280 orr.w r2, r2, #16777216 ; 0x1000000
8009ee8: f8c3 20c4 str.w r2, [r3, #196] ; 0xc4
tmp_hal_status = ADC_Disable(hadc);

```