cancel
Showing results for 
Search instead for 
Did you mean: 

low power MCU in stopmode start using considerable amount of current after few minutes

sde c.1
Senior II

Hi,

We have a STM32L031F6 which is used as an RTC. A weird phenomenon is occurring: when the controller goes to sleep, it only uses 2µA, but after 2 minutes and 40 seconds, it starts consuming 50 to 100µA, depending on the hardware board used. There is no external trigger at that moment, so we expect the controller to stay in sleep mode until the next external trigger. However, this consumption is also not enough for the run state of the controller, which consumes +500µA in run mode.

As a test, I set up an EXTI input to output mode and toggled the pin when the chip is out of sleep mode. When the power consumption is 2µA, this output is not active. When the consumption is 50-100µA, the output is not active. When the consumption is +500µA, the output toggles as expected.

What can cause this behavior? Could there be a problem with the chip itself? We only use the ADC, RTC, I2C, and TIM2 modules.

2024_06_26_08_36_28_NIC_main_board_rev01.PrjPcb_Altium_Designer_23.11.1_Viewer.png

 

 

 

void ExitStopMode(){
		SystemClock_Config();
		HAL_ResumeTick();
}

void ExitStopModeWithExtPower(){
		__HAL_ADC_ENABLE(&hadc);
		MX_I2C1_Init(); // use this rude method because __HAL_I2C_ENABLE(&hi2c1) does not have the desired effect
		tmr_ms_Start(&BatteryCheckTmr,3000);   // first battery check , 3s after power up, then every hour
}

void EnterStopMode(){
	// Goto STOP mode
	allEventsStopped(); // do not enter STOP before all event timers are elapsed

	//check power state again , if already ON exit the function
	if(PowerApplied()) return;

	__HAL_ADC_DISABLE(&hadc);
	if (hi2c1.Instance != NULL) { HAL_I2C_DeInit(&hi2c1); } // use this rude method because __HAL_I2C_DISABLE(&hi2c1) does not have the desired effect

	HAL_SuspendTick();
	HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);
}


// will be triggered on positive and negative edges of the tampering pins
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){

	ExitStopMode(); // needed the support HAL timers

}
bool PowerApplied(){
	return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
}
int main(void)
{
  /* USER CODE BEGIN 1 */
  bool bSystemPoweredUp=1;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_ADC_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
  IntrusionInputs_Init();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  while (1)
  {
	  if(PowerApplied()){
		  if(!bSystemPoweredUp){
			  ExitStopModeWithExtPower();  // the trigger was power-up event,  spin up the I2C and ADC
			  bSystemPoweredUp = 1;
		  }
		  AliveTasks();
	  }
	  else{
		  bSystemPoweredUp = 0;
		  EnterStopMode(); // TODO extrea check !
	  }

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
sde c.1
Senior II

It appears that the issue was related to the code in the HAL libraries. To resolve it, I made the following changes:

Instead of:

__HAL_ADC_ENABLE(&hadc);

I now use:

LL_ADC_EnableInternalRegulator(ADC1);
LL_ADC_Enable(ADC1);

And instead of:

__HAL_ADC_DISABLE(&hadc);

I now use:

LL_ADC_Disable(ADC1);
LL_ADC_DisableInternalRegulator(ADC1);

 With these changes, the rest current remains stable at 2 µA.

View solution in original post

9 REPLIES 9
Danish1
Lead II

That could be due to one (or more) of the GPIO pins floating to an intermediate voltage (somewhere between Vdd and Vss).

If these pins are set as digital inputs the input circuitry looks like a CMOS inverter, where you have an NMOS transistor with its source connected to Vss and a PMOS transistor with its source connected to Vdd; the gates both going to the input pin and the drains connected together.

If the input pin is at Vss, the NMOS transistor is off (and the PMOS is on).

If the input pin is at Vdd, the PMOS transistor is off (and the NMOS is on).

If the input pin is at a voltage between Vss and Vdd, both transistors are partly on, and "class A" current flows between Vdd and Vss - increased supply current.

There are various fixes.

If you want the pin to remain as a digital input, pull it high or low with a resistor (either externally or turn on a built-in pull-up or pull-down).

Or you could program the pin to be digital output. Or set it "analog" which disables the digital input.

as you can see in the schematic, the inputs need to be used as intrusion event, and are pulled up with a 1M5 resistor.

Danish1
Lead II

PB1? (I can't see if that's wired to BOOT0)

SWDIO? SWCLK? (I know these often have pulls)

Boot0 -> 10k to GND
PB1 is configured as output low.

SWDIO and SWCLK just go to the debug connector and do not have Pull Up or Down configuration in ioc

 

sde c.1
Senior II

It appears that the issue was related to the code in the HAL libraries. To resolve it, I made the following changes:

Instead of:

__HAL_ADC_ENABLE(&hadc);

I now use:

LL_ADC_EnableInternalRegulator(ADC1);
LL_ADC_Enable(ADC1);

And instead of:

__HAL_ADC_DISABLE(&hadc);

I now use:

LL_ADC_Disable(ADC1);
LL_ADC_DisableInternalRegulator(ADC1);

 With these changes, the rest current remains stable at 2 µA.

@sde c.1 , very interesting. But can you explain *why* this fixes the issue? what's the difference between the HAL and LL calls? It would be instructive to hear. Plus, this may potentially be something ST could fix in the HAL code, in order to prevent others from experiencing such strange and distressing behavior.

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

Unfortunately, I don't have the time to thoroughly investigate the HAL code.

In other developments, I noted that HAL functions are not always working 100% reliably, so we tried the lower layer functions instead.

Nonetheless, HAL remains a huge speed booster in our development process

Unfortunately, I don't have the time to thoroughly investigate the HAL code.

 

Shame. You told us the symptoms and now the solution, but we still don't why this happened.

Still, no one is paying you to debug ST's HAL so that's understandable.

 

I do notice that, by convention,  a dunder prefix (double underscore) indicates an internal HAL function,

__HAL_ADC_ENABLE

and not a user-facing API. You can use them of course, but you have to be more conscientious than doing do than you would be with normal HAL functions.

 

looking at `HAL_ADC_*` completions in CubeIDE, it looks like there are dedicated public function related to what you're trying to do:

  • HAL_ADCEx_RegularStop (which calls a function named  ADC_Disable)
  • HAL_ADCEx_EnterADCDeepPowerDownMode
  • HAL_ADCEx_DisableVoltageRegulator

and maybe others.

 

is it possible you used the wrong HAL incantation for the task?

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

nicely noticed !
I will take a look and reply later .