cancel
Showing results for 
Search instead for 
Did you mean: 

Wake stm32l151 up from stop mode by way of USART

David Rodenas
Associate II
Posted on May 31, 2017 at 14:56

Hello everyone, 

I have looked up this issue but I am afraid I have been unable to find a solution. 

I am trying to wake a stm32l151CCT6 MCU up from stop mode by way of USART1 interrupt. I have the RXNE interrupt enabled (I am posting some of my code below) but I seem to never get an interrupt after entering stop mode. Separately, both the usart and enter to/wakeup from stop mode work. Is there something I am missing? If useful, I am using the stm32l1xx standard peripheral library 

Any help is much appreciated. 

My code below:

/* Enter stop mode */

void lpm_enter(void)

{

   /* Turn off LSE and HSE clocks */

   cpu_deinit();

   /* Disable the Power Voltage Detector */

   PWR_PVDCmd(DISABLE);

   /* Clear Wakeup flag */

   PWR->CR |= PWR_CR_CWUF;

   /* Set MCU in ULP (Ultra Low Power) */

   PWR_UltraLowPowerCmd(ENABLE);

   /* Enable the fast wake up from Ultra low power mode */

   PWR_FastWakeUpCmd(ENABLE);

   /* Enter STOP mode with regulator in low power mode */

   PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);

}

/* Exit stop mode */

void lpm_exit(void)

{

extern void SetSysClock( void );

   

/* Disable interrupts */

   dint(); 

   /* Reconfigure the system clocks */

   SetSysClock();

   /* RTC is used as system clock; Re-initialise */

   mcu_rtc_init();   

   /* Disable ULP (Ultra Low Power) */

   PWR_UltraLowPowerCmd(DISABLE); // add up to 3ms wakeup time

   /* Enable the Power Voltage Detector */

   PWR_PVDCmd(ENABLE);

   /* Set internal voltage regulator */

   PWR_VoltageScalingConfig( PWR_VoltageScaling_Range1 );

   

/* Enable interrupts */

   eint();

}

/* USART1 configuration */

void

usart_init(void)

{

   NVIC_InitTypeDef NVIC_InitStructure;

   GPIO_InitTypeDef GPIO_InitStructure;

   USART_InitTypeDef USART_InitStructure;

   

   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);

   /* GPIO pin configuration */

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;

   GPIO_Init(GPIOB, &GPIO_InitStructure);

   

   /* Alternate function conf */

   GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);

   GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

   

   /* USART conf */

   USART_InitStructure.USART_BaudRate = 115200;

   USART_InitStructure.USART_WordLength = USART_WordLength_8b;

   USART_InitStructure.USART_StopBits = USART_StopBits_1;

   USART_InitStructure.USART_Parity = USART_Parity_No;

   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

   USART_Init(

USART

1

, &USART_InitStructure);

   /* Enable RXNE interrupt */

   USART_ITConfig(

USART

1

, USART_IT_RXNE, ENABLE);

   /* Enable USART1 global interrupt */

   NVIC_EnableIRQ(USART1_IRQn);

   

   USART_Cmd(

USART

1

, ENABLE);

}

/* USARTx IRQHAndler */

void USART1_IRQHandler(void)

{

   if(USART_GetITStatus(

USART

1

, USART_IT_RXNE) != RESET)

   {

      unsigned char x;

      /* Exit stop mode */

      lpm_exit();

     

      USART_ClearITPendingBit(

USART

1

, USART_IT_RXNE);

      x = USART_ReceiveData(

USART

1

);

      /* Loop until the end of reception */

      while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET);

      /* Handle input */

      if(usart_input_handler != NULL) usart_input_handler(x);

   }

}

Many thanks again

#stm32l151 #wakeup #usart #stop-mode #stm32l15x
1 ACCEPTED SOLUTION

Accepted Solutions
Danish1
Lead II
Posted on May 31, 2017 at 22:51

The USART needs its clock running in order to allow it to receive characters. Unless I'm mistaken (I don't use the 'L151) STOP mode stops the LSE and HSE clocks (I suspect HS is divided down to generate the baud clock in the UART).

So you won't be able to receive anything - or trigger the processor to wake up by the USART - while in STOP mode.

You might be able to wake up from SLEEP mode by way of the USART but I don't know if power-consumption with a slow MSI oscillator will be too high for your application.

One thing I have done was (when sleeping waiting for something to come in through the USART) to program the microcontroller to wake up on an EXTI edge on the same pin as USART RX. There are complications here: The first few bits might be lost while the oscillator gets going but I could afford to lose the first character or two, and could force the USART back in sync by negating RTS until I was ready.

Hope this helps,

Danish

View solution in original post

3 REPLIES 3
Danish1
Lead II
Posted on May 31, 2017 at 22:51

The USART needs its clock running in order to allow it to receive characters. Unless I'm mistaken (I don't use the 'L151) STOP mode stops the LSE and HSE clocks (I suspect HS is divided down to generate the baud clock in the UART).

So you won't be able to receive anything - or trigger the processor to wake up by the USART - while in STOP mode.

You might be able to wake up from SLEEP mode by way of the USART but I don't know if power-consumption with a slow MSI oscillator will be too high for your application.

One thing I have done was (when sleeping waiting for something to come in through the USART) to program the microcontroller to wake up on an EXTI edge on the same pin as USART RX. There are complications here: The first few bits might be lost while the oscillator gets going but I could afford to lose the first character or two, and could force the USART back in sync by negating RTS until I was ready.

Hope this helps,

Danish

Max
ST Employee
Posted on June 01, 2017 at 08:09

Danish is correct, the USART need a clock to operate while they are off in stop mode.

If you need USART function in low power mode, you should look at STM32L0 or STM32L4.

They embed a LPUART that can work in stop mode.

It still need a clock, so a clock need to stay on but it can work with a low speed clock.

David Rodenas
Associate II
Posted on June 01, 2017 at 09:19

Thanks Danish and Mark. Really helpful. I will try Danish's workaround, as I can live with it. But yeah, I will consider switching to a different micro in the near future.