2025-02-19 12:55 PM
I'm using a STM32L051C8T6 in a custom board. The software function is to enter stop mode to reduce the current consumption and only wake the MCU up with GPIO EXTI, RTC wakeup timer and UART wake up.
The device is entering the low power mode and exiting successfully, but I'm facing issues with my UART after waking up. My UART is configured to use DMA on Rx and Tx, but now I'm only using the DMA on Tx, for testing purpose.
My problem is that after waking up via UART, I want to keep the microcontroller awaken attending to configuration commands, until receive a configuration ending command. However, the MCU wakes with the USART config command, but it's unable to trigger the UART RxEventCallback via DMA.
I think, maybe the MCU just need an specific configuration after waking up to make the UART Rx callback via DMA work well.
See the code below:
Part 1 of the code:
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_DMA_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
MX_ADC_Init();
MX_TIM2_Init();
MX_RTC_Init();
/* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, at_serial.rx_buffer, sizeof(at_serial.rx_buffer));
wakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;
HAL_UARTEx_StopModeWakeUpSourceConfig(&huart1, wakeUpSelection);
HAL_UARTEx_EnableStopMode(&huart1);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);
HAL_DBGMCU_EnableDBGStopMode();
HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
ATSerial_Init(&at_serial,&huart1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_BUSY)) {}
HAL_SuspendTick();
HAL_PWR_EnableSleepOnExit();
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Part 2 of the code:
void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart1)
{
HAL_ResumeTick();
SystemClock_Config();
__enable_irq();
__HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, at_serial.rx_buffer, sizeof(at_serial.rx_buffer));
if(strncmp((char *)at_serial.rx_buffer, WAKE_UP_STR, strlen(WAKE_UP_STR))==0){
HAL_UART_Transmit(&huart1, (uint8_t *)CFG_MODE_STR, strlen(CFG_MODE_STR), 1000);
while(1);
HAL_UART_Transmit(&huart1, (uint8_t *)EXIT_CFG_MODE_STR, strlen(EXIT_CFG_MODE_STR), 1000);
}
HAL_UARTEx_StopModeWakeUpSourceConfig(&huart1, wakeUpSelection);
HAL_UARTEx_EnableStopMode(&huart1);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);
memset(at_serial.rx_buffer, 0, sizeof(at_serial.rx_buffer));
}
}
At line 14 of part 2 of the code "the while(1)" will be used to check if a exit command has been sent. For now, I didn't change this yet, because I want to discover why the it doesn't trigger any interruption.
Part 3 of the code:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
SystemClock_Config();
HAL_ResumeTick();
if(huart == &huart1){
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
ATSerial_Process_CMD(&at_serial);
}else{
if(huart == &huart2){
uart_rx_complete = 1;
__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, sim.rx_buffer, Y7080_RX_BUFFER_SIZE);
}
}
}
The Rx pin is configured with internal pull-up to avoid floating pin waking up the MCU every time. And also the UART is clocked by the HSI(16MHz).
2025-02-19 12:22 PM
I'm using a STM32L051C8T6 in a custom board. The software function is to enter stop mode to reduce the current consumption and only wake the MCU up with GPIO EXTI, RTC wakeup timer and UART wake up.
The device is entering the low power mode and exiting successfully, but I'm facing issues with my UART after waking up. My UART is configured to use DMA on Rx and Tx, but now I'm only using the DMA on Tx, for testing purpose.
My problem is that after waking up via UART, I want to keep the microcontroller awaken attending to configuration commands, until receive a configuration ending command. However, the MCU wakes with the USART config command, but it's unable to send any answer/information via UART. I checked the registers and the UART sending functions status. The code flow indicates that everything worked fine, but the device that is configuring the MCU on the other side, can't receive any confirmation if the command was executed sucessfully or not.
I think, maybe the MCU just need an specific configuration after waking up to keep UART working well.
See the code below:
Part 1 of the code:
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_DMA_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
MX_ADC_Init();
MX_TIM2_Init();
MX_RTC_Init();
/* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, at_serial.rx_buffer, sizeof(at_serial.rx_buffer));
wakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;
HAL_UARTEx_StopModeWakeUpSourceConfig(&huart1, wakeUpSelection);
HAL_UARTEx_EnableStopMode(&huart1);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);
HAL_DBGMCU_EnableDBGStopMode();
HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
ATSerial_Init(&at_serial,&huart1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_BUSY)) {}
HAL_SuspendTick();
HAL_PWR_EnableSleepOnExit();
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Part 2 of the code:
void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart1)
{
HAL_ResumeTick();
SystemClock_Config();
__enable_irq();
__HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, at_serial.rx_buffer, sizeof(at_serial.rx_buffer));
if(strncmp((char *)at_serial.rx_buffer, WAKE_UP_STR, strlen(WAKE_UP_STR))==0){
HAL_UART_Transmit(&huart1, (uint8_t *)CFG_MODE_STR, strlen(CFG_MODE_STR), 1000);
while(1);
HAL_UART_Transmit(&huart1, (uint8_t *)EXIT_CFG_MODE_STR, strlen(EXIT_CFG_MODE_STR), 1000);
}
HAL_UARTEx_StopModeWakeUpSourceConfig(&huart1, wakeUpSelection);
HAL_UARTEx_EnableStopMode(&huart1);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);
memset(at_serial.rx_buffer, 0, sizeof(at_serial.rx_buffer));
}
}
At line 14 of part 2 of the code "the while(1)" will be used to check if a exit command has been sent. For now, I didn't change this yet, because I want to discover why the HAL_UART Transmit is executing till the end, but the configuration terminal that sends the commands doesn't receive any confirmation.
The Rx pin is configured with internal pull-up to avoid floating pin waking up the MCU every time.
2025-02-20 02:27 AM
Hi @Andryck_Sant
Some comments about your implementation :
- Please note that HAL_UARTEx_ReceiveToIdle_DMA() API is not a blocking service, i.e. that your code execution will exit this before the reception if completed or even started. the function programs the reception and enables it, but reception management, and completion will be handled thorugh DMA and UART interrupts.
End of the reception (either on reception of expected nb of bytes, or on IDE event occurrence) will be notified though the HAL_UARTEx_RxEventCallback callback, you have to implement on your side.
- So, by calling (line14)
if(strncmp((char *)at_serial.rx_buffer, WAKE_UP_STR, strlen(WAKE_UP_STR))==0)
just after HAL_UARTEx_ReceiveToIdle_DMA(), content of at_serial.rx_buffer might not be the one you expect.
- last remark concerns the content of your HAL_UARTEx_WakeupCallback() callback. Remember this callback is executed in an interrupt context. So would be continue code execution after wakeup in your main while(1) loop.
Hope this helps.
regards