2021-03-11 03:44 AM
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)
There 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
2021-03-14 07:34 AM
HAL drivers are not interrupt/thread safe and overall broken and bloated. Just an example:
Drop that junk and implement something sane: