2024-07-11 03:23 AM
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:
2024-07-11 03:46 AM
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
2024-07-11 04:45 AM
Hi Pedro,
Thanks for the advice, I will look at it and return to you when done.
Kind regards,
Yohann
2024-07-11 11:28 PM
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.
2024-07-12 01:09 AM
Only 2 things I can think of are:
1) The UART status is not being cleared correctly when an error (PE, FE...).
2) The UART does not start correctly with a break character...
Kind regards
Pedro
2024-07-15 11:28 PM
Thank you Pedro for your suggestions.
For now I will just pullup the MCU uart RX pin to avoid this behaviour.
I will later go deeper in your ideas.