cancel
Showing results for 
Search instead for 
Did you mean: 

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

rapoorv
Associate III

@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.

 

 

6 REPLIES 6
ABN
Associate III

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
ST Employee

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 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

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();
}



rapoorv
Associate III

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

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

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

rapoorv
Associate III

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.?