Skip to main content
Associate II
January 3, 2025
Question

ADC sampling shows wrong values after wakeup from STOP2 mode (STM32WB55VGQ)

  • January 3, 2025
  • 4 replies
  • 1006 views

@ABN 
Hello All,

Steps happening in the code (FREERTOS based). 

1. Initialization ( 4 ADC channels, DMA, BLE)

2. Take 1 sample of each channel. Store in register.

3. GOTO STOP2 mode.

4. Wakeup at 10th second using LPTIM.

5. Reinint everything above menitoned.

6. Take ADC samples of the 4 channels.

The problem.

ADC samples taken after 1st init is correct. ADC samples taken hereafter on wakeup are incorrect.
This is being checked by debugging through STM programmer.

 

 

4 replies

ABN
Associate III
January 3, 2025

The code snippet is the Init of ADC

 

hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc1.Init.LowPowerAutoWait = DISABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.NbrOfConversion = 4;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.DMAContinuousRequests = DISABLE;
 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 hadc1.Init.OversamplingMode = ENABLE;
 hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
 hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
 hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
 hadc1.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_3;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_4;
 sConfig.Rank = ADC_REGULAR_RANK_2;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_VREFINT;
 sConfig.Rank = ADC_REGULAR_RANK_3;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_9;
 sConfig.Rank = ADC_REGULAR_RANK_4;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 

This snippet is application Init and refresh of ADC

status_code_t AdcInput_StPort_init(uint16_t *adcBuffer, uint16_t adcBufferLength)
{
 status_code_t status = STATUS_OK;
	/* ADC Calibration starts */
	HAL_StatusTypeDef ret;

	/* Stops the ADC */
	ret = HAL_ADC_Stop(myHalAdcPtr);
	if(ret != HAL_OK)
	{
		status = STATUS_ERR_PROTOCOL;
	}

	/* Start the Calibration */
	ret = HAL_ADCEx_Calibration_Start(myHalAdcPtr, ADC_SINGLE_ENDED);
	if(ret != HAL_OK)
	{
		status = STATUS_ERR_PROTOCOL;
	}

	/* ADC Calibration Done */
 if(HAL_OK != HAL_ADC_Start_DMA(myHalAdcPtr, (uint32_t *)adcBuffer, adcBufferLength))
 {
 	status = STATUS_ERR_PROTOCOL;
 }

 return status;
}

status_code_t AdcInput_StPort_refresh(AdcInputCallback_t cb)
{
 status_code_t status = STATUS_OK;
 myAdcInputCallback = cb;

	/* ADC Calibration Done */
 if(HAL_OK != HAL_ADC_Start(myHalAdcPtr))
 {
 	status = STATUS_ERR_PROTOCOL;
 }

 return status;
}




STTwo-32
Technical Moderator
January 3, 2025

Hello @rapoorv 

Could you please try to disable ADC and ADC regulator before entering STOP 2 mode then after the wake-up, reconfigure them and check the clock configuration after the wake-up. Also, After the Wake-up, you can disable and enable again the ADC, then perform an ADC calibration. Don't forget to leave some time before the conversation after the Wake-up.

Best Regards.

STTwo-32 

ABN
Associate III
January 3, 2025

Hi @STTwo-32 

In the PreSleepProcessing function the following code is executed

__weak void PreSleepProcessing(uint32_t ulExpectedIdleTime)
{
/* place for user code */
	HAL_SuspendTick();
	HAL_LPTIM_TimeOut_Start_IT(&hlptim1, 0xFFFF, ulExpectedIdleTime);
	LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48);
	LL_C2_EXTI_DisableIT_32_63(LL_EXTI_LINE_48);
	__HAL_RCC_I2C3_CLK_DISABLE();
	__HAL_RCC_I2C1_CLK_DISABLE();
	HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);
 /*De-initialize the DMA and ADC */
 HAL_ADC_DeInit(&hadc1);
 HAL_DMA_DeInit(&hdma_adc1);
}

 As per the 'HAL_ADC_DeInit' definition in 'stm32wbxx_hal_adc.c', ADC regulator is getting disabled

 /* Reset register CR */
 /* Bits ADC_CR_JADSTP, ADC_CR_ADSTP, ADC_CR_JADSTART, ADC_CR_ADSTART,
 ADC_CR_ADCAL, ADC_CR_ADDIS and ADC_CR_ADEN are in access mode "read-set":
 no direct reset applicable.
 Update CR register to reset value where doable by software */
 CLEAR_BIT(hadc->Instance->CR, ADC_CR_ADVREGEN | ADC_CR_ADCALDIF);
 SET_BIT(hadc->Instance->CR, ADC_CR_DEEPPWD);


After wakeup, the post sleep operations are as follows

__weak void PostSleepProcessing(uint32_t ulExpectedIdleTime)
{
/* place for user code */
 SystemClock_Config();
 PeriphCommonClock_Config();

 HAL_LPTIM_TimeOut_Stop_IT(&hlptim1);
 HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
 HAL_ResumeTick();

 __HAL_RCC_I2C3_CLK_ENABLE();
 __HAL_RCC_I2C1_CLK_ENABLE();

 MX_DMA_Init();
 MX_ADC1_Init();
}



rapoorvAuthor
Associate II
January 7, 2025

Hi @STTwo-32 
Can you suggest something after going through the problem point and the code ?

STTwo-32
Technical Moderator
January 7, 2025

Hello @rapoorv 

Could you try to test it first without BLE et activated in a baremetal code. If it works fine integrate RTOS and test it again. If this also go fine, try to test it all. If possible on a NUCLEO Board just to make sure we dont have any design issue.

Best Regards.

STTwo-32

rapoorvAuthor
Associate II
January 13, 2025

hello @STTwo-32 

We could not try the above thing suggested by you, but in the code mentioned by @ABN  there is a delay inserted. check below code.

__weak void PostSleepProcessing(uint32_t ulExpectedIdleTime)
{
/* place for user code */
 SystemClock_Config();
 PeriphCommonClock_Config();

 HAL_LPTIM_TimeOut_Stop_IT(&hlptim1);
 HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
 HAL_ResumeTick();

 __HAL_RCC_I2C3_CLK_ENABLE();
 __HAL_RCC_I2C1_CLK_ENABLE();

 MX_DMA_Init();
 MX_ADC1_Init();
HAL_Delay(35);
}

 Seems like the 35ms delay inserted after the ADC init. gives us the corrrect values of the ADC sampling.

We could not figure out why this delay is required. Anything below 35ms messes up the ADC conversions. 
Any idea what are the things in the initilization phase which can take this much of startup time.?