Skip to main content
Explorer II
July 11, 2024
Question

STM32L0xx UART can't wakeup MCU after RX line was in low level during stop mode

  • July 11, 2024
  • 1 reply
  • 1649 views

Hi,

I am using a custom board integrating a STM32L071kzt6 MCU and have an issue to wakeup the MCU with uart start bit detection if the MCU uart rx line was no more pullup by the device with which the MCU communicates (A FT230XS USB to RX bridge).

It is the case when the USB which powered the FT230XS chip is disconnected.
When the USB is then reconnected, the FT230XS chip re pull-up the MCU uart rx line as expected, but communication is no more possible.
If the UART RX pin is internally pulled up, the problem disappear as the RX line does't get low when USB is disconnected, but I don't know if it is a relevant solution

In fact the MCU wakeup with UART start bit detection when USB is disconnected the first time, then a frame error appears, and then the MCU re-enter stop mode.
But it is not possible to wakeup again the MCU with UART start bit detection.
(It is still possible with other way as EXTI, or I2C on match address detection for exemple)
There is no problem if the MCU is in RUN mode, so it is really a problem with how I handle STOP mode

Here are the main code :

 

 

/* USER CODE BEGIN WHILE */

 printf("Enter main SandboxMockupStopMode\n\r");

 // LED (Green for mockup V1, RED for mockup V2
 HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);

 // ##### UART #####

 HAL_UARTEx_ReceiveToIdle_IT(_huartUsb, rxBuffer, RX_BUFFER_SIZE);

 // Enable the UART peripheral to wakeup the MCU
 configureUartStopMode();

 printf("Enter Stop mode in 1 second\n\r");
 HAL_Delay(1000);

 enableStopMode = 1;

 while (1)
 {
 if (uartMessageCompleted == 1)
 {
 // Reset indication
 uartMessageCompleted = 0;

 printf("UART buffer : ");
 printf((char*)rxBuffer);
 printf("\r\n");

 printf("uartWakeupCount : %lu\r\n", uartWakeupCount);
 printf("uartRxEventCount : %lu\r\n", uartRxEventCount);
 printf("uartErrorCount : %lu\r\n", uartErrorCount);
 printf("uartErrorCode : %lu\r\n", uartErrorCode);
 printf("uartAbortCount : %lu\r\n", uartAbortCount);
 printf("uartAbortTransmitCallbackCount : %lu\r\n", uartAbortTransmitCallbackCount);
 printf("uartAbortReceiveCount : %lu\r\n", uartAbortReceiveCount);
 printf("statusAbortReceive : %d\r\n", statusAbortReceive);
 printf("statusActivateReceive : %d\r\n", statusActivateReceive);
 }

 if (enableStopMode == 1 && usbUartReceiving == 0 && uartMessageCompleted == 0)
 {
 enterStopMode();

 leaveStopMode();
 }

 /* USER CODE END WHILE */
void configureUartStopMode()
{
 // Set the wake-up event: specify wake-up on start-bit detection
 UART_WakeUpTypeDef wakeUpSelection;
 wakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;
 HAL_UARTEx_StopModeWakeUpSourceConfig(_huartUsb, wakeUpSelection);

 // Enable the UART2 Wake UP from stop mode Interrupt
 __HAL_UART_ENABLE_IT(_huartUsb, UART_IT_WUF);

 // Enable MCU wake-up by UART2
 HAL_UARTEx_EnableStopMode(_huartUsb);
}

void enterStopMode()
{
 HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); // LED (Green for mockup V1, RED for mockup V2)
 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); // For debug only

 /* Clear Wakeup interrupt flag if needed */
 if (__HAL_UART_GET_FLAG(_huartUsb, USART_ISR_WUF) != RESET)
 {
 __HAL_UART_CLEAR_FLAG(_huartUsb, USART_ISR_WUF);
 }

 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

 // 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()
{
 HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); // LED (Green for mockup V1, RED for mockup V2)
 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); // For debug only

 // 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();
}

 

 

And here how callbacks are handled:

 

 

void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
{
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // For debug only

 uartWakeupCount++;

 usbUartReceiving = 1; // To prevent the mcu to enter stop mode

 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // For debug only
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // For debug only

 uartRxEventCount++;

 if(huart->Instance == _instanceUsartUsb)
 {
 //printf((char*)rxBuffer);

 uartMessageCompleted = 1; // Indicate uart message can be treated
 usbUartReceiving = 0; // Accept the mcu to enter stop mode

 HAL_UARTEx_ReceiveToIdle_IT(_huartUsb, rxBuffer, RX_BUFFER_SIZE);
 }

 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // For debug only
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); // For debug only

 uartErrorCount++;

 uartErrorCode = huart->ErrorCode;

 // Noise error
 if (uartErrorCode & HAL_UART_ERROR_NE)
 {
 // Clear noise error flag
 __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_NE);
 }

 // Parity error
 if (uartErrorCode & HAL_UART_ERROR_PE)
 {
 // Clear frame error flag
 __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_PE);
 }

 // Frame error
 if (uartErrorCode & HAL_UART_ERROR_FE)
 {
 // Clear frame error flag
 __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_FE);
 }

 // Overrun error
 if (uartErrorCode & HAL_UART_ERROR_ORE)
 {
 // Clear overrun flag
 __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE);
 __HAL_UART_FLUSH_DRREGISTER(huart); //flush data
 }

 usbUartReceiving = 0; // Accept the mcu to enter stop mode

 // Restart Uart RX
 statusAbortReceive = HAL_UART_AbortReceive_IT(_huartUsb);
 statusActivateReceive = HAL_UARTEx_ReceiveToIdle_IT(_huartUsb, rxBuffer, RX_BUFFER_SIZE);

 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); // For debug only
}

void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)
{
 uartAbortCount++;
}

void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)
{
 uartAbortTransmitCallbackCount++;
}

void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
{
 uartAbortReceiveCount++;
}

 

 

 

And below captures show when callback functions are called and MCU UART RX and TX line state:

Disconnect and reconnect USB.png

 

 

 

Disconnect USB.png

 

 

 

    This topic has been closed for replies.

    1 reply

    Graduate II
    July 11, 2024

    I'm not 100% sure, but I think I remember something about that in the Errata docs on that device. Have a look there.

    Kind regards
    Pedro

    YohannDrcAuthor
    Explorer II
    July 11, 2024

    Hi Pedro,

    Thanks for the advice, I will look at it and return to you when done.

    Kind regards,
    Yohann

    YohannDrcAuthor
    Explorer II
    July 12, 2024

    I read the STM32L07xxx/L08xxx device errata documentation.
    There was indeed issues with wakeup from stop mode with UART on MCU revision A and B.
    However the issue disappeared on current revision (1, P, Q, Z) of the MCU. The MCU I used is rev Z, so there is normally no problem with that.