cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G070 HAL_UART_ErrorCallback

DPrie.1
Associate II

Dear all,

I have 2 MODBUS 485 ports, one in UART1, the another in UART3, both in DMA mode.

Testing frame collisions with Docklight I see the function HAL_UART_ErrorCallback called with an Error code of 1 (Parity error), 8(Overrin error) or 11 (Parity+Noise+Overrun error).

In case of UART1, after a restart it recover himself and continue communicating without any problem.

However, when UART3 crashes (same type of messages, same frame collisions) after the same code, the UART doesn't recover, and I have to reset the microcontroller.

I saw in the datasheet the next table; (page 27 of https://www.st.com/resource/en/datasheet/stm32g070cb.pdf)

 0693W000008wdEzQAI.pngThere are some differences between UARTs, maybe I have to add more code for reset the UART3.

I'm using this code on the callback:

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
	if (huart == &huart1){
		__HAL_UART_CLEAR_PEFLAG(&huart1);
		HAL_UART_DMAStop(&huart1);
		HAL_UART_MspDeInit(&huart1);
		HAL_UART_MspInit(&huart1);
		if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)mb_buf_in1, mb_buf_in1_size) != HAL_OK){
			Error_Handler();
		}
		LED2_timeout=50;
 
		// FRAMING, overrun or HIGH noise ERROR
		// Restart USART and continue communicating
	}
	if (huart == &huart3){
		Errcallback_timeout=1;
 
		if (READ_BIT(huart3.Instance->ISR, UART_FLAG_ORE | UART_FLAG_FE | UART_FLAG_NE | UART_FLAG_RXNE)) {
		   //Flush errors
		   UART_flush();
		// Raise Error Handler
		//	_Error_Handler(__FILE__, __LINE__);
		}
 
		HAL_UART_MspDeInit(&huart3);
		/*
		__HAL_UART_CLEAR_PEFLAG(&huart3);
				__HAL_UART_CLEAR_OREFLAG(&huart3);
				__HAL_UART_CLEAR_FEFLAG(&huart3);
				__HAL_UART_CLEAR_NEFLAG(&huart3);
				__HAL_UART_CLEAR_IDLEFLAG(&huart3);
				__HAL_UART_CLEAR_TXFECF(&huart3);
		HAL_UART_DMAStop(&huart3);
		HAL_UART_DeInit(&huart3);
*/
//		__HAL_UART_CLEAR_PEFLAG(&huart3);
//		__HAL_UART_CLEAR_OREFLAG(&huart3);
//		__HAL_UART_CLEAR_FEFLAG(&huart3);
//		__HAL_UART_CLEAR_NEFLAG(&huart3);
//		__HAL_UART_CLEAR_IDLEFLAG(&huart3);
//		__HAL_UART_CLEAR_TXFECF(&huart3);
	/*
		__HAL_UART_SEND_REQ(&huart3, UART_RXDATA_FLUSH_REQUEST);
		__HAL_UART_CLEAR_IT(&huart3, UART_CLEAR_OREF);*/
		//HAL_UART_DeInit(&huart3);
 
//		if (HAL_RS485Ex_Init(&huart3, UART_DE_POLARITY_HIGH, 0, 0) != HAL_OK)
//		  {
//		    Error_Handler();
//		  }
		//HAL_UART_Init(&huart3);
 
 
		HAL_UART_MspInit(&huart3);
 
		if (HAL_UART_Receive_DMA(&huart3, (uint8_t *)mb_buf_in2, mb_buf_in2_size) != HAL_OK){
			Error_Handler();
		}
		LED1_timeout=50;
 
		// FRAMING, overrun or HIGH noise ERROR
		// Restart USART and continue communicating
	}
}

And the part of UART_flush:

void UART_flush(void) {
  // Flush UART RX buffer if RXNE is set
  if READ_BIT(huart3.Instance->ISR, UART_FLAG_RXNE) {
    SET_BIT(huart3.Instance->RQR, UART_RXDATA_FLUSH_REQUEST);
  }
 
  // Not available on F030xx devices!
  // SET_BIT(huart1.Instance->RQR, UART_TXDATA_FLUSH_REQUEST);
 
  // Clear All Errors (if needed)
  if (READ_BIT(huart3.Instance->ISR, UART_FLAG_ORE | UART_FLAG_FE | UART_FLAG_NE)) {
 
	__HAL_UART_CLEAR_PEFLAG(&huart3);
	__HAL_UART_CLEAR_OREFLAG(&huart3);
	__HAL_UART_CLEAR_FEFLAG(&huart3);
	__HAL_UART_CLEAR_NEFLAG(&huart3);
	__HAL_UART_CLEAR_IDLEFLAG(&huart3);
	__HAL_UART_CLEAR_TXFECF(&huart3);
 
  }
}

I tried several options, and clear some flags, but I didn't succeed.

Thank you in advance,

Best regards,

Daniel Prieto Castillo

HW&SW engineer

1 REPLY 1
Piranha
Chief II

HAL drivers are not interrupt/thread safe and overall broken and bloated. Just an example:

https://community.st.com/s/question/0D50X0000C5Tns8SQC/bug-stm32-hal-driver-lock-mechanism-is-not-interrupt-safe

Drop that junk and implement something sane:

https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx