STM34L4 freeze during UART with Interrupt Idle line
Hi,
We are building an IoT device, using STM32L476RET6 as main core. It communicates with an LPWAN modem with AT-commands via UART. We have redirected UART2 into external pins for "serial output" into Nucleo RX pins.
During testing, we noticed initially that some devices where seemingly "stuck" in some state - no printing in Nucleo RX, not responding to external interrupts - while communicating with LPWAN modem ( it stayed in idle ON state).
No hard fault or similar (we have put checks inside repsective callbacks). IWDG can reset the device, but it is a "last resort" method.
After putting device in debug mode, catching the situation and pausing the code, it stopped here :
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->ISR);
uint32_t cr1its = READ_REG(huart->Instance->CR1); <<<-------Looking at USART1 ISR register, we found ORE error flag.
Resuming the code in debug mode makes the MCU continue, but in run mode the MCU is frozen , which is strange.
For UART TX, we are using basic transmit command such as :
uint8_t res = HAL_UART_Transmit(&MODEM_UART, (uint8_t*) command_to_send, strlen(command_to_send), 1000);For UART RX, we are using Idle Iine interrupt for receiving in combination with ring buffer (using lwrb library) :
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart == &huart1) {
// write rx result into ring buffer
lwrb_write(&rb, isr_buffer, Size);
data_ready_flag = true;
// Enable UART RX Interrupt with Idle-line detection
int retries = 10;
do {
if (HAL_UARTEx_ReceiveToIdle_IT(&huart1, isr_buffer, sizeof(isr_buffer)) == HAL_OK) {
break;
}
retries--;
} while (retries > 0);
}
}
Our function for AT commands communication looks like this :
static int send_rcv_at_command(const char *command_to_send, const char *exp_res, int timeout) {
uint32_t tick = HAL_GetTick();
bool command_expected_to_be_sent = true;
char buffer_final[1024] = {0};
int total_num_of_bytes = 0;
printf("Send command %s\r\n", command_to_send);
// Enable UART RX Interrupt with Idle-line detection, if not already enabled
if (((huart1.Instance->CR1 & USART_CR1_IDLEIE_Msk) >> USART_CR1_IDLEIE_Pos) == 0) {
int retries = 10; // retry if function fail
do {
if (HAL_UARTEx_ReceiveToIdle_IT(&huart1, isr_buffer, sizeof(isr_buffer)) == HAL_OK) {
break;
}
retries--;
} while (retries > 0);
if (retries == 0) {
return -1;
}
}
while (return_code > 0 && ((HAL_GetTick() - tick) < timeout)) {
if (command_expected_to_be_sent == true) {
if ((command_to_send != NULL) && (strlen(command_to_send) > 0)) {
//send command
uint8_t res = HAL_UART_Transmit(&MODEM_UART, (uint8_t*) command_to_send, strlen(command_to_send), 1000);
if (res == HAL_OK) { // Tx successfull
command_expected_to_be_sent = false;
} else { //Tx fail, try again
continue;
}
}
}
if (data_ready_flag) { // data available at UART1
data_ready_flag = false;
// Receive characters from ring buffer
int numOfBytes = lwrb_read(&.rb, &buffer_final[total_num_of_bytes], sizeof(buffer_final) - total_num_of_bytes);
total_num_of_bytes = total_num_of_bytes + numOfBytes;
}
// ...
// further parsing...
// ...
}
HAL_UART_Abort_IT(&huart1);
lwrb_reset(&rb);
return 0;
}
Screenshot from callstack of debug mode:
1) If it is a UART error, why does the MCU freezes and not just fail to receive and continue ?
2) How can MCU recover from a fail at UART communication ?
