cancel
Showing results for 
Search instead for 
Did you mean: 

How to wake up STM32L4 from STOP1 when receiving on USART

Tombedded
Associate II

I have read AN4991 and the example code but in my case nothing works. I'm using DMA transfer with the UART. Can that be the reason? Is it not possible to wake up from STOP1 when using DMA to receive bytes from USART? Or how can it be done?

I use CubeMX to initialize peripherals but my "going to sleep" code is esentially like this:

__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
HAL_SuspendTick();
while(__HAL_UART_GET_FLAG(&huart1, USART_ISR_BUSY) == SET);
while(__HAL_UART_GET_FLAG(&huart1, USART_ISR_REACK) == RESET);
UART_WakeUpTypeDef WakeUpSelection;    
WakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;
HAL_UARTEx_StopModeWakeUpSourceConfig(&huart1, WakeUpSelection);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);
HAL_UARTEx_EnableStopMode(&huart1);
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
 
// After USART RX start bit we should wake up from stop and continue here - but it never happens
 
HAL_UARTEx_DisableStopMode(&huart1);
__HAL_UART_DISABLE_IT(&huart1, UART_IT_WUF);
HAL_ResumeTick();

Then I tried another approach. Configuring the UART RX pin as EXTI. Then I would lose the first byte but the transmitter could send a dummy byte to wake the receiver. This approach did not wake the system up either. Code as below:

while(__HAL_UART_GET_FLAG(&huart1, USART_ISR_BUSY) == SET);
while(__HAL_UART_GET_FLAG(&huart1, USART_ISR_REACK) == RESET);
 
// Configure UART RX pin as GPIO input that triggers interrupt on falling edge
GPIO_InitTypeDef GPIO_InitStruct = {
       .Pin = RX_Pin, // GPIO pin 10
       .Mode = GPIO_MODE_IT_FALLING, // Interrupt on falling edge
       .Pull = GPIO_NOPULL,
       .Speed = GPIO_SPEED_FREQ_VERY_HIGH
};
 
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
HAL_SuspendTick();
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI); 
 
// After interrupt we should wake up from stop and continue here - does not happen
 
HAL_ResumeTick();
HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);
GPIO_InitTypeDef GPIO_InitStruct = {
       .Pin = RX_Pin,
       .Mode = GPIO_MODE_AF_PP,
       .Pull = GPIO_NOPULL,
       .Speed = GPIO_SPEED_FREQ_VERY_HIGH,       
       .Alternate = GPIO_AF7_USART1
};
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  // restore USART RX on this pin

For this I made EXTI handlers:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {}
 
void EXTI15_10_IRQHandler(void) {}

I'll be grateful for any help I can get with this. Thanks!

9 REPLIES 9
Sarra.S
ST Employee

Hello @Tombedded​ and welcome to the Community 😊,

Can that be the reason?

>> Yes it can be!

In fact, as it is mentioned in the AN4635 in section 4.3, in most of the cases the DMA cannot be used in combination with the Stop mode, hence all DMA channels have to be disabled before entering the Stop Low-power mode.

and also in section 4.4.2 : The downside is that in DMA mode the LPUART cannot take advantage of wakeup from Stop mode.

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.

Thanks Sarra, good to know. I'm using the USART but I guess the same limitation applies there. To bad DMA is not mentioned in AN4991.

Then I need to find the answer to my alternate implemention - why there is no EXTI interrupt if I configure the UART RX pin as EXTI. Maybe UART must be disabled before the pin can work as EXTI?

I now tried call HAL_UART_DeInit() before configuring USART RX pin as EXTI but that did not help. Still no interrupt on falling edge of the pin. Tried the same with a non-USART pin and there I got an interrupt successfully. So is it not possible to reconfigure an USART pin to GPIO/EXTI pin after once configured as USART pin?

Hello again @Tombedded​ 

After some research, I now have a logical reason : In fact, in Stop mode, DMA is clocked-off, therefore it will not operate. Only STM32U5 using LPBAM supports DMA transfers in stop mode.

Regarding your 2nd question :

In order to configure a pin as an external interrupt (EXTI), the UART module associated with that pin must be disabled. This is because the EXTI interrupt is only triggered when the pin is configured in its GPIO mode. When the UART module is enabled, it will take control of the pin and configure it to its UART mode, thus disabling the EXTI interrupt. Therefore, the UART module must be disabled first.

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.

No, it's possible to re-configure a USART pin to EXTI/GPIO after once configured as USART pin! To do so :

  1. As u already said; reset the USART's hardware with HAL_UART_DeInit() 
  2. when configuring the pin as EXTI, the correct GPIO port and pin that needs to be configured needs to be specified. Additionally, the EXTI line needs to be enabled
  3. the NVIC needs to be configured correctly for the interrupt to be correctly handled

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.

I did try adding the HAL_UART_DeInit() to my code example above (another approach version). It still did not work.

I now changed UART RX to use interrupts instead of DMA For some reason removing DMA broke debugging - the MCU hangs after a while. If I stop debugging and power-cycle the MCU it runs. I'm using IAR and J-Link.

Anyways, UART RX works well using the interrupt mode but still sending something to UART does not wake up the MCU from STOP1. Code is essentially the same as my first code snippet above, but for UART RX I use now:

HAL_UART_Receive_IT(&huart1, rx_buffer, rx_buffer_size);

Guenael Cadier
ST Employee

Hello @Tombedded​ 

In case it could help, there are some code examples provided in STM32CubeL4 Firmware package that could be of interest. For instance, you could have a look at following example in Projects/NUCLEO-L476RG/Examples/UART/UART_WakeUpFromStop directory of the STM32CubeL4 FW package.

You could also find it here on Github.

Regards

Piranha
Chief II