2024-02-13 12:48 AM
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
Solved! Go to Solution.
2024-02-13 10:05 AM
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 ?
2024-02-13 05:57 AM
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?
2024-02-13 10:05 AM
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 ?