cancel
Showing results for 
Search instead for 
Did you mean: 

UART Wakeup Callback called twice when receive uart message longer than 1 char

YohannDrc
Associate III

Hi,

I am currently trying to receive uart message when the MCU is in stop mode on a Nucleo-L073Rz board.

To do this I first wake up the mcu on uart start bit, and when the mcu receive the uart idle event.

I can then treat the received message in the main loop before entering again the main loop.

It works great when the received message is only one char long.
However if the received message is longer, the HAL_UARTEx_WakeupCallback is called a second time after all treatment has already be done.
Which is a problem, because it wake up the MCU whereas It doesn't trigger HAL_UARTEx_RxEventCallback in order to stop the mcu again.

I am quite new in embedded software so maybe I have to make some routine or clear flag, but I have no idea.

How does I assure the HAL_UARTEx_WakeupCallback not to be called twice ?

 

#define RX_BUFFER_SIZE 20 uint8_t charBuffer = 0; uint8_t rxBuffer[RX_BUFFER_SIZE] = {0}; volatile uint8_t uartMessageCompleted = 0; uint8_t enableStopMode = 0; void enterStopMode() { HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, RESET); // Green pin // Suspend Tick increment to prevent wakeup by Systick interrupt. // Otherwise the Systick interrupt will wake up the device within 1ms (HAL time base) HAL_SuspendTick(); // Enter Stop Mode HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); } void leaveStopMode() { // Set system clock back to ... oscillator because when exiting Stop mode by using an interrupt or a wake up event, // ... oscillator is selected as system clock SystemClock_Config (); //Resume Tick interrupt if disabled prior to Stop mode entry HAL_ResumeTick(); } void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart) { HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, SET); // Green pin HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_10); // Yellow pin leaveStopMode(); enableStopMode = 0; // To prevent the mcu to enter stop mode HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_10); // Yellow pin } void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, SET); // Green pin HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_12); // Blue pin if(huart->Instance == USART2) { uartMessageCompleted = 1; // Indicate uart message can be treated enableStopMode = 1; // Accept the mcu to enter stop mode HAL_UARTEx_ReceiveToIdle_IT(&huart2, rxBuffer, RX_BUFFER_SIZE); } HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_12); // Blue pin } void commandTreatment() { //printf((char*)rxBuffer); if (!strcmp((char*)rxBuffer, "help")) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9); // Pink pin HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9); // Pink pin } else { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9); // Pink pin HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9); // Pink pin HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9); // Pink pin HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9); // Pink pin } } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 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_USART2_UART_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ printf("SandboxStopMode\n\r"); HAL_UARTEx_ReceiveToIdle_IT(&huart2, rxBuffer, RX_BUFFER_SIZE); // set the wake-up event: specify wake-up on start-bit detection UART_WakeUpTypeDef wakeUpSelection; wakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT; if (HAL_UARTEx_StopModeWakeUpSourceConfig(&huart2, wakeUpSelection)!= HAL_OK) { Error_Handler(); } // Enable the UART2 Wake UP from stop mode Interrupt __HAL_UART_ENABLE_IT(&huart2, UART_IT_WUF); // enable MCU wake-up by UART2 HAL_UARTEx_EnableStopMode(&huart2); printf("Enter Stop mode in 3 seconds\n\r"); HAL_Delay(3000); enableStopMode = 1; while (1) { if (uartMessageCompleted == 1) { // Reset indication uartMessageCompleted = 0; // Treat userCommand commandTreatment(); } if (enableStopMode == 1) { enterStopMode(); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
View more

 


In order to follow when and how many times I entered callback function, I activate pin accordingly.
See capture bellow:

Yellow: HAL_UARTEx_WakeupCallback

Blue: HAL_UARTEx_RxEventCallback
Pink: Command treatment

Green: Run Mode

1 ACCEPTED SOLUTION

Accepted Solutions

Hi TDK,

Thank you for your answer.

As I use a 20 chars long buffer, I don't think I can get overflow in data reception buffer.
And all characters are well received as I can print them in HAL_UARTEx_RxEventCallback or commandTreatment function

As you advise, I check the uart flags:

When receiving 1 char:
6291648 -> 11000000000000011000000 

or
6295744 -> 11000000001000011000000 -> USART_ISR_EOBF

When receiving 2 char:
7344320 -> 11100000001000011000000 -> USART_ISR_WUF

If I clear USART_ISR_WUF flag before entering stop mode, There is no more second wakeup and all works well.
Maybe the USART_ISR_WUF is put on when the second char is received and I am maybe still in the HAL_UARTEx_WakeupCallback function ?

View solution in original post

2 REPLIES 2
TDK
Super User

Perhaps you aren't reading the incoming data fast enough and the second character causes an overflow condition. 10ms to handle a single character is a long time. Can you check the UART flags for this?

If you feel a post has answered your question, please click "Accept as Solution".

Hi TDK,

Thank you for your answer.

As I use a 20 chars long buffer, I don't think I can get overflow in data reception buffer.
And all characters are well received as I can print them in HAL_UARTEx_RxEventCallback or commandTreatment function

As you advise, I check the uart flags:

When receiving 1 char:
6291648 -> 11000000000000011000000 

or
6295744 -> 11000000001000011000000 -> USART_ISR_EOBF

When receiving 2 char:
7344320 -> 11100000001000011000000 -> USART_ISR_WUF

If I clear USART_ISR_WUF flag before entering stop mode, There is no more second wakeup and all works well.
Maybe the USART_ISR_WUF is put on when the second char is received and I am maybe still in the HAL_UARTEx_WakeupCallback function ?