STM32L476 in STOP2 mode

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderators: RoccoMarco, barthess

Stephane
Posts: 12
Joined: Tue Aug 26, 2014 3:41 pm
Has thanked: 2 times
Been thanked: 2 times

STM32L476 in STOP2 mode

Postby Stephane » Mon Mar 30, 2020 1:25 pm

Hello,

I have troubles trying to use the STOP2 sleep mode on a STM32L476.

Its on a custom board: i enter manually in sleep mode. (now with a command under the shell)
And the wakeup will come from 3 different sources: external button, LPUART activity, or timeout on internal timer. (RTC is on LSE)
The consumption i obtain is 70uA when sleeping: not perfect, but it is not the problem.
The problem is that this value is obtained only for the FIRST sleep cycle.
All the next sleep cycles are at min 200uA.
And during wake, everything seems fine.

And i tried a LOT of things without result.
I think its a problem of register reconfiguration.
For that, i tried to backup all PWR_CRx, RCC_CRx, and RCC_Ax registers, then restoring them after wakeup, without success.
Thinking its perhaps an OS related problem, I tried also to stop Chibios before sleepping, also without success.

Its why i put here the code of my sleep function.
This code is called from main() because i read somewhere there is better to go in sleep mode from main(). (if we have many threads)

Its under Chibios 19.1.

Code: Select all

/** ****************************************************************************
 * \fn     void sleep_for_x_sec(uint16_t nb_sec)
 * \brief  Put the STM32 in the Stop2 mode
 *         Must be called only from main()  To be tested (seen some comments on forums)
 * \param[in]  (u16) nb_of sec to wait in sleep mode: 1-65535
 * \return     (u8)  wake source:  WAKE_SOURCE_TIMER, WAKE_SOURCE_EXTERNAL, WAKE_SOURCE_LPUART
*/
uint8_t sleep_for_x_sec(uint16_t nb_sec)
{
  static RTCWakeup wakeupspec;
  static uint8_t wakeup_source;

  GL_Sleep_Requested = 0;                               // Reset Flag Sleep_Requested

                                                        // Config CB for ext button
  GL_Flag_External_WakeUp = 0;                          // Reset flag that will be set by the CB
  palEnableLineEvent(LINE_WakeUp, PAL_EVENT_MODE_FALLING_EDGE);     // Falling edge creates event
  palSetLineCallback(LINE_WakeUp, cb_external_input_wake_up, NULL); // Active callback

                                                        // Config LPUART for wakeup
  LPUART1->CR1 &= ~USART_CR1_UE;                        // Disable LPUART to allow modif
  LPUART1->CR1 |= USART_CR1_UESM;                       // LPUART able to wakeup from Stop
  LPUART1->CR3 |= USART_CR3_WUS_1;                      // Wakeup on Start bit detected
  LPUART1->CR3 |= USART_CR3_WUFIE;                      // Wakeup from Stop IRQ enabled
  LPUART1->CR3 |= (0x1U << 23);                         // LPUART clk enabled during STOP (UCESM)
  LPUART1->ICR = USART_ICR_WUCF;                        // Clear WUF flag
  LPUART1->CR1 |= USART_CR1_UE;                         // Enable LPUART after modif

                                                        // Config RTC for wakeup after delay
  wakeupspec.wutr = ( (uint32_t)4 ) << 16;              // bits 16-18 = WUCKSel : Select 1 Hz clk
  wakeupspec.wutr |= nb_sec - 1;                        // bits 0-15  = WUT : Period = x+1 sec
  rtcSTM32SetPeriodicWakeup(&RTCD1, &wakeupspec);       // Set RTC wake-up config

  ports_set_lowpower();                                 // Set ports for low power

//  DBGMCU->CR = DBGMCU_CR_DBG_STOP;                      // Allow debug in Stop mode: +130uA !!!

//  chSysLock();                                // Wakeup in strange mode: 200uA, freezed

  chSysDisable();                               // No effect
  SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;   // No effect        // Disable TickInt Request
  chSysEnable();                                // No effect

  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;                    // Low power mode in deep sleep
  PWR->CR1 |= PWR_CR1_LPMS_STOP2;                       // Deep sleep mode in Stop2

// -----------------------------------------------------
                                                        // 
  __WFI();                                              // Sleep now !!!
                                                        //
// -----------------------------------------------------

  LPUART1->CR1 &= ~USART_CR1_UESM;                      // LPUART not able to wakeup from Stop

  if (GL_Flag_External_WakeUp)                          // Search for the wake-up sources
  {
    wakeup_source = WAKE_SOURCE_EXTERNAL;               // External signal indicated by callback
  }
  else if ( !(LPUART1->ISR & USART_ISR_IDLE) )
  {
    wakeup_source = WAKE_SOURCE_LPUART;                 // LPUART
  }
  else                                                  // Else
  {
    wakeup_source = WAKE_SOURCE_TIMER;                  // Its the internal timer
  }

  SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;                   // Clear deep sleep mask

  PWR->SCR |= PWR_SCR_CSBF;                             // Clear standby flag

  LPUART1->ICR |= USART_ICR_PECF;                       // Clear Parity error

//  chSysUnlock();
//  chSysDisable();                             // No effect

  ports_set_normal();                                   // Restore ports states

  stm32_clock_init();                                   // Re-init RCC and power, Important

  __enable_irq();                               // No effect

  SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;    // No effect          // Enable TickInt Request

  return wakeup_source;
}


The callback for the external button is this simple:

Code: Select all

void cb_external_input_wake_up(void *arg)
{
  (void)arg;
  GL_Flag_External_WakeUp = 1;                                  // Set Flag for Wake_Up signal
}


I can post also a relatively small program to show everything. (around 300 lines without ports init/deinit)
But it is designe for my board.

If someone has some ideas, i'm happy to receive it.

Stephane

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32L476 in STOP2 mode

Postby Giovanni » Mon Mar 30, 2020 9:47 pm

Hi,

Never tried that, you should make sure to stop all interrupt sources before entering sleep mode, including the OS time (SysTick or TIMx depending on the mode).

Also, are the oscillator states the same? what do you do about GPIO before going to sleep?

Giovanni

Stephane
Posts: 12
Joined: Tue Aug 26, 2014 3:41 pm
Has thanked: 2 times
Been thanked: 2 times

Re: STM32L476 in STOP2 mode

Postby Stephane » Tue Mar 31, 2020 1:33 pm

Hi,

Thank for the ideas, it makes me double check again a lot of thing and i found the problem:
After the wake-up, i reconfigured manually all GPIOs, and the problem is that i put:

Code: Select all

  palSetLineMode(LINE_SWDIO, PAL_MODE_ALTERNATE(0));
  palSetLineMode(LINE_SWCLK, PAL_MODE_ALTERNATE(0));
instead of

Code: Select all

  palSetLineMode(LINE_SWDIO, PAL_MODE_ALTERNATE(0) | PAL_STM32_PUPDR_PULLUP);
  palSetLineMode(LINE_SWCLK, PAL_MODE_ALTERNATE(0) | PAL_STM32_PUPDR_PULLDOWN);
And because of the missing pullup/pulldown on these lines, i had 130uA more consumption when sleeping, without anything connected on these lines ! (the STLINK was physically disconnected)

Is there a function that Chibios provides to configure the GPIOs as described in board.chcfg(board.h) ?
I seen __early_init() in board.c, but it is not accessible from main().
Otherwise, i will backup all GPIOs registers on local variables and then restore them after wakeup.

And to asnwer your questions (and help others):
-My code uses the standard tick mode
-Before the sleep, i now disable interrupts using __disable_irq(); but i had to enclose it as:

Code: Select all

  chSysDisable();
  __disable_irq();
  chSysEnable();
Otherwise, the source of the wakeup is not correct for the button (Callback)
-For the GPIO during sleep, except for the debug, external_button and LPUART, all the pins are as:

Code: Select all

palSetLineMode(LINE_SPI1_nCS1, PAL_MODE_INPUT_ANALOG);

This state is now enough for me to continue my project.
I will later slowly check for every GPIOs if there is a better combination of pullup/pulldown to lower more the consumption.

Thank for your help

Stephane

rew
Posts: 380
Joined: Sat Jul 19, 2014 12:59 pm
Has thanked: 2 times
Been thanked: 13 times

Re: STM32L476 in STOP2 mode

Postby rew » Wed Apr 01, 2020 12:58 pm

As an extra explanation:

A digital input has an N- and P-FET connected in the "inverter" configuration. Now the core runs at about 1.2V, so these mosfets are properly "ON" at a V_GS of 1.2V. So... when you don't have anything connected and the voltage on that pin happens to stumble to say 1.5V, both the N-FET and the P-FET will be ON and shorting the supply to the ground. These mosfets are tiny. So while you can buy mosfets that have an RDSON in the order of 1mOHm, these guys have an RDSON in the order of tens of kiloOhms. From your measurements: on the order of 50-60k for the sum of the P-FET and N-FET.

If you configure the pin as "analog" this input-circuit is disconnected and won't consume any piower. Similarly configuring a pullup or pulldown will make sure that one of the input mosfets is properly off so even if the other one would turn on (it will) no static current will flow.

I would've expected the RDSON of these input mosfets to be a bit lower. It is possible that they are and "noise" in the environment causes the pin to pass through the "interesting" region 100 or 120 times per second. So that... on average you hit about 130 uA....

geoffrey.brown
Posts: 87
Joined: Thu May 07, 2015 9:47 pm
Has thanked: 3 times
Been thanked: 15 times

Re: STM32L476 in STOP2 mode

Postby geoffrey.brown » Wed May 06, 2020 6:08 pm

Don't forget to turn off the debugger hardware:

DBGMCU->CR = 0;

This is a considerable current draw.

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32L476 in STOP2 mode

Postby Giovanni » Wed May 06, 2020 6:30 pm

geoffrey.brown wrote:Don't forget to turn off the debugger hardware:

DBGMCU->CR = 0;

This is a considerable current draw.


Does this also stop the DWT counter? this would disable the RTC unit in the RTOS so no polled delays and no time measurement services.

Giovanni

geoffrey.brown
Posts: 87
Joined: Thu May 07, 2015 9:47 pm
Has thanked: 3 times
Been thanked: 15 times

Re: STM32L476 in STOP2 mode

Postby geoffrey.brown » Wed May 06, 2020 7:36 pm

I don't know the answer. I do know that if the debug unit is on, then you can't reach the really low power states.
Geoffrey

iggarpe
Posts: 129
Joined: Sun Sep 30, 2012 8:32 pm

Re: STM32L476 in STOP2 mode

Postby iggarpe » Thu May 07, 2020 8:22 pm

Giovanni wrote:
geoffrey.brown wrote:Don't forget to turn off the debugger hardware:

DBGMCU->CR = 0;

This is a considerable current draw.


Does this also stop the DWT counter? this would disable the RTC unit in the RTOS so no polled delays and no time measurement services.

Giovanni


I do not think so. I have a design that clears DBGMCU->CR in order to achieve the expected standby power consumption and while it's not in standby all seems to work fine, although to be honest I did not test polled delays nor time measurement services specifically. OTH if the DWT counter is stopped *any* polled delay would loop forever. I guess I would have noticed.

iggarpe
Posts: 129
Joined: Sun Sep 30, 2012 8:32 pm

Re: STM32L476 in STOP2 mode

Postby iggarpe » Thu May 07, 2020 8:24 pm

geoffrey.brown wrote:Don't forget to turn off the debugger hardware:

DBGMCU->CR = 0;

This is a considerable current draw.


This drove me crazy for oh so many hours.

The most expensive lines of code I wrote in 2019:

DBGMCU->CR &= ~(DBGMCU_CR_DBG_SLEEP |
DBGMCU_CR_DBG_STOP |
DBGMCU_CR_DBG_STANDBY);

iggarpe
Posts: 129
Joined: Sun Sep 30, 2012 8:32 pm

Re: STM32L476 in STOP2 mode

Postby iggarpe » Thu May 07, 2020 8:28 pm

Besides the already mentioned DBGMCU->CR clear, two other things to check:

1- Disconnect any TTL serial adapters. They'll cause current consumption in the order of hundreds of uA.

2- Disconnect STLink or any other debugger interface. They also cause small current consumption that becomes very significant for the lowest power consumption modes like stop, standby and shutdown.


Return to “STM32 Support”

Who is online

Users browsing this forum: No registered users and 24 guests