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 */
}

 


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
Guru

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 ?