cancel
Showing results for 
Search instead for 
Did you mean: 

Bug in ADC initialisation code (CubeIDE / FW_L1)

JU
Associate III

I found this issue whilst troubleshooting a couple of other issues - device target is STM32L152REx using low-level (LL) libraries.

CubeIDE Version: 1.9.0

CubeMX Version: 6.5.0-RC4

STM32Cube_FW_L1_V1.10.3

If I use lots of ADC channels (22 in my case) the generated code is wrong and the ADC does not function correctly;

CubeMX generates:

ADC_REG_InitStruct.SequencerLength = 22;

Which does not work (22 needs to be shifted left to the correct location in the register), it should generate:

ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_22RANKS;

Which I had to create my own defines for:

#define LL_ADC_REG_SEQ_SCAN_ENABLE_17RANKS (ADC_SQR1_L_4)
#define LL_ADC_REG_SEQ_SCAN_ENABLE_18RANKS  (ADC_SQR1_L_4 |                                ADC_SQR1_L_0)
#define LL_ADC_REG_SEQ_SCAN_ENABLE_19RANKS  ( ADC_SQR1_L_4 |                ADC_SQR1_L_1               )
#define LL_ADC_REG_SEQ_SCAN_ENABLE_20RANKS  ( ADC_SQR1_L_4 |                ADC_SQR1_L_1 | ADC_SQR1_L_0)
#define LL_ADC_REG_SEQ_SCAN_ENABLE_21RANKS  ( ADC_SQR1_L_4 | ADC_SQR1_L_2                              )
#define LL_ADC_REG_SEQ_SCAN_ENABLE_22RANKS  ( ADC_SQR1_L_4 | ADC_SQR1_L_2                | ADC_SQR1_L_0)
#define LL_ADC_REG_SEQ_SCAN_ENABLE_23RANKS  ( ADC_SQR1_L_4 | ADC_SQR1_L_2 | ADC_SQR1_L_1               )
#define LL_ADC_REG_SEQ_SCAN_ENABLE_24RANKS  ( ADC_SQR1_L_4 | ADC_SQR1_L_2 | ADC_SQR1_L_1 | ADC_SQR1_L_0)

I hope this is useful to someone.

5 REPLIES 5
Imen.D
ST Employee

Hello @JU​ 

You are right! I confirm this issue.

I added STM32CubeMX topic to this post and shared it with @Sara BEN HADJ YAHYA​ (from STM32CubeMX team) to review this request and take the necessary action.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

Hi @JU​ 

 After deep check: I found that LL driver is not correct:

the define of sequence length LL_ADC_REG_SEQ_SCAN_ENABLE_xxRANKS in stm32l1xx_ll_adc.h file should be up to 27 or 28.

Note: each channel rank setting is correct with [LL_ADC_REG_RANK_1; LL_ADC_REG_RANK_28]

I escalated this issue internally for fix in the coming releases of STM32CubeL1 (in LL driver) and CubeMX.

- Internal ticket number 126534 -

PS: This is an internal tracking number and is not accessible or usable by customers)

Thank you for having reported the point.

When your question is answered, please close this topic by choosing Select as Best.

This will help other users find this answer more quickly.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
JU
Associate III

I don't kniw if it's related but I also get weird ADC readings using the standard LL libraries / headers:

gVDDA = __LL_ADC_CALC_VREFANALOG_VOLTAGE(aADCxConvertedData[21], LL_ADC_RESOLUTION_12B);
 
gVrefInt = __LL_ADC_CALC_DATA_TO_VOLTAGE(gVDDA, aADCxConvertedData[21], LL_ADC_RESOLUTION_12B);

ADC[21] value is 378 which feels low, but somehow calculates out to gVDDA = 13198mV

Yet somehow the 2nd calculation gives a sensible result for VRefInt = 1218mV

The same happens for other ADC readings, for a 3000mV input (VDD = 3.3v) the ADC reading is ~950 where I would expect it to be closer to ~2950

My ADC initialisation code (all generated by CubeMX / CubeIDE) is:

ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV2;
	LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
	ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
	ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
	ADC_InitStruct.LowPowerMode = LL_ADC_LP_AUTOWAIT_NONE|LL_ADC_LP_AUTOPOWEROFF_NONE;
	ADC_InitStruct.SequencersScanMode = LL_ADC_SEQ_SCAN_ENABLE;
	LL_ADC_Init(ADC1, &ADC_InitStruct);
	ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
	ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_22RANKS; 
	ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
	ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
	ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
	LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
	LL_ADC_REG_SetFlagEndOfConversion(ADC1, LL_ADC_REG_FLAG_EOC_SEQUENCE_CONV);
	LL_ADC_SetChannelsBank(ADC1, LL_ADC_CHANNELS_BANK_A);

I'm still investigating this as all the ADC readings are lower than expected but using __LL_ADC_CALC_DATA_TO_VOLTAGE(gVDDA, aADCxConvertedData, LL_ADC_RESOLUTION_12B); ends up giving the correct result in millivolts somehow :\

EDIT: It appears LL_ADC_REG_Init tries to insert SequencerLength into ADCx_CR1 :|

JU
Associate III

To expand on the above edit;

stm32l1xx_ll_adc.c / stm32l1xx_ll_adc.h initialisation code appears to have further errors;

LL_ADC_REG_Init attempts to insert SequencerLength into the wrong register:

if(ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
    {
      MODIFY_REG(ADCx->CR1,
                   ADC_CR1_DISCEN
                 | ADC_CR1_DISCNUM
                ,
                   ADC_REG_InitStruct->SequencerLength
                 | ADC_REG_InitStruct->SequencerDiscont
                );
    }
    else
    {
      MODIFY_REG(ADCx->CR1,
                   ADC_CR1_DISCEN
                 | ADC_CR1_DISCNUM
                ,
                   ADC_REG_InitStruct->SequencerLength
                 | LL_ADC_REG_SEQ_DISCONT_DISABLE
                );
    }

SequencerLength should not be anywhere in ADC_CR1, I would guess it was meant to be Discontinuous Mode Channel Count (DISCNUM).

JU
Associate III

@Imen DAHMEN​ did you see this extra issue with the ADC initialisation?