I am having an issue with USART behaviour and am wondering if any of you can help! I am using an STM32F303 with three of its USARTs in use, of which USART1 is configured as an asynchronous RS485 port with its DE line controlled automatically. The TX, RX and DE pins from the microcontroller are connected to a TI SN65HVD1792 RS485 transceiver, which presents four lines (TX+, TX-, RX+, RX-) to the user for communication.
I am using interrupt-driven USART communication, which in most cases works absolutely fine. However, I am having an issue with handling the error condition in which the RS485 link is configured as two-wire (TX+/RX+ and TX-/RX- connected together, to form a +ve/-ve pair of wires used for both transmission and reception) and more than one device on the bus tries to transmit at the same time. When this happens, the STM32 stops responding to all serial communications until the power is cycled.
Looking a little bit closer at what is going on, I see that USART1_IRQHandler in stm32f3xx_it.c is being called repeatedly - over and over until I power-cycle the board. This calls HAL_UART_IRQHandler(&huart1) in stm32f3xx_hal_uart.c, the function of which is to check which interrupt has occurred (parity error, frame error, noise error, overrun, wakeup from stop, rx register not empty, tx ready, tx complete), deal with it appropriately, and then clear the interrupt state. However, none of these specific interrupts are recognised as having triggered - execution just passes by all the "if" statements, the function exits, and then runs again - endlessly.
I can't find any way of recognising that this has occurred, as it doesn't throw up any of the recognised error conditions. I'm aware that RS485 bus clash is something that should be avoided by good system design, but we can't rule out the possibility that it will happen when the system is in a customer installation - and it needs to be able to recognise the error, ignore the "clashed" message and continue - needing to power cycle it is unacceptable.
Does anyone have any ideas as to how to recognise this condition / stop the system from entering an interrupt loop?
Thanks in advance
The interrupt routine is as follows (HAL file version 1.2.0, date 13 Nov 15)
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
/* UART parity error interrupt occurred -------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_PE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE) != RESET))
{
__HAL_UART_CLEAR_IT(huart, UART_CLEAR_PEF);
huart->ErrorCode |= HAL_UART_ERROR_PE;
/* Set the UART state ready to be able to start again the process */
huart->State = HAL_UART_STATE_READY;
}
/* UART frame error interrupt occurred --------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_FE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
{
__HAL_UART_CLEAR_IT(huart, UART_CLEAR_FEF);
huart->ErrorCode |= HAL_UART_ERROR_FE;
/* Set the UART state ready to be able to start again the process */
huart->State = HAL_UART_STATE_READY;
}
/* UART noise error interrupt occurred --------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_NE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
{
__HAL_UART_CLEAR_IT(huart, UART_CLEAR_NEF);
huart->ErrorCode |= HAL_UART_ERROR_NE;
/* Set the UART state ready to be able to start again the process */
huart->State = HAL_UART_STATE_READY;
}
/* UART Over-Run interrupt occurred -----------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_ORE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
{
__HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF);
huart->ErrorCode |= HAL_UART_ERROR_ORE;
/* Set the UART state ready to be able to start again the process */
huart->State = HAL_UART_STATE_READY;
}
/* Call UART Error Call back function if need be --------------------------*/
if(huart->ErrorCode != HAL_UART_ERROR_NONE)
{
HAL_UART_ErrorCallback(huart);
}
/* UART wakeup from Stop mode interrupt occurred -------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_WUF) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_WUF) != RESET))
{
__HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF);
/* Set the UART state ready to be able to start again the process */
huart->State = HAL_UART_STATE_READY;
HAL_UARTEx_WakeupCallback(huart);
}
/* UART in mode Receiver ---------------------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) != RESET))
{
UART_Receive_IT(huart);
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
}
/* UART in mode Transmitter ------------------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_TXE) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE) != RESET))
{
UART_Transmit_IT(huart);
}
/* UART in mode Transmitter (transmission end) -----------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_TC) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC) != RESET))
{
UART_EndTransmit_IT(huart);
}
}
stm32f3xx_it.c
which call toHAL_UART_IRQHandler(UART_HandleTypeDef *huart)
. – imbearr