cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U535: Delay needed after ADC1 initialization before starting with ADC_CR_ADSTART?

Uwe Bonnes
Chief

Hello,

here the exit of my (extended)initialization prodecure for ADC of STM32U535 running at 3.3v and 160 Mhz.  Before setting ADC_CR_ADSTART, without the small delay or with the delay in line 14  and the limit for i smaller "6" like here "5" in the code, ADC_CR_ADSTART stays high  and the programm keeps in the while (ADC1->CR & ADC_CR_ADSTART)  loop line16/17. __DMB() is not replacement for the delay.

Is the needed delay some artefact of my setup or some requirement that I do not find/oversee in RM0456?

    ADC1->CR  |= ADC_CR_ADCAL; /*8*/
    while (ADC1->CR & ADC_CR_ADCAL) {
	__NOP();
    }
    __DMB();
    ADC1->CR  &= ~ADC_CR_ADCALLIN;
    __DMB();
    const uint8_t channel = 19U;
    AdcSetRegularSequence(ADC1, 1U, &channel);
    ADC1->CR |= ADC_CR_ADEN;
    while (!(ADC1->ISR & ADC_ISR_ADRDY)) {
	__NOP();
    }
    for (volatile int i = 0; i < 5; i++) {}
    ADC1->CR |= ADC_CR_ADSTART;
    while (ADC1->CR & ADC_CR_ADSTART) {
	__NOP();
 

 

2 REPLIES 2
waclawek.jan
Super User

ADC is dual-clock (if not more), so perhaps you want to add also the clock setup to the minimal example exhibiting the failure.

ST might want to start to meticulously document the exact delays needed and their relationship to the clocks, instead of "oh just throw in a DMB here and there" (it would be even better would there be a foolproof method of setting up things based on readbacks, but I understand that hardware bugs creep in, the hardware complexity shot through the roof long ago, but ST should not resort to handwaving like the far-eastern competition routinely does). The duration of DMB may vary with exact source of execution and maybe other factors, too.

JW 

Uwe Bonnes
Chief

Here the ADC clock setting

    RCC->CCIPR3 |= RCC_CCIPR3_ADCDACSEL_0;
    RCC->AHB2ENR1 |= RCC_AHB2ENR1_ADC12EN;
    RCC->AHB2RSTR1 |= RCC_AHB2RSTR1_ADC12RST;
    RCC->AHB2RSTR1 = 0;
    /* Wake up */
    ADC1->CR &= ~ADC_CR_DEEPPWD;
    ADC1->ISR = ADC_ISR_LDORDY;
    ADC1->CR |= ADC_CR_ADVREGEN;
    while ((ADC1->ISR & ADC_ISR_LDORDY) == 0U)
	continue;
    /* Divide Sysclk by 4 for 40 MHz ADC clock*/
    ADC12_COMMON_NS->CCR &= ~ADC_CCR_PRESC_Msk;
    ADC12_COMMON_NS->CCR |= ADC_CCR_PRESC_1;
    AdcPowerOff(ADC1);