Electrical – Checking interrupt flags for UART data receiving and transmitting on STM32

cinterruptsstm32uart

I'm trying to develop a UART receiver/transmitter for an academic project. For now i developed the UART continuous data receiving part and it works quite well. Here is the code:
Interrupt file:

extern volatile char RxData[10][8];
extern volatile uint8_t RxComplete;
extern volatile uint8_t RxCompleteOneRow;

extern volatile uint8_t ColumnRxBuffer;
extern volatile uint8_t RowRxBuffer;
void USART2_IRQHandler(void)
{
    //HAL_UART_IRQHandler(&huart2);

        if(RowRxBuffer < 9)
        {
            if(ColumnRxBuffer < 7)
            {
                RxData[RowRxBuffer][ColumnRxBuffer] = (uint8_t)(huart2.Instance->DR & (uint8_t)0xff);
                ColumnRxBuffer++;
            }
            else
            {
                RxData[RowRxBuffer][ColumnRxBuffer] = (uint8_t)(huart2.Instance->DR & (uint8_t)0xff);
                ColumnRxBuffer = 0;
                if(RowRxBuffer == 0)
                {
                    RxCompleteOneRow = 1;
                }
                RxComplete = 1;
                __HAL_UART_FLUSH_DRREGISTER(&huart2);
                RowRxBuffer++;
            }
        }
        else
        {
            if(ColumnRxBuffer < 7)
            {
                RxData[RowRxBuffer][ColumnRxBuffer] = (uint8_t)(huart2.Instance->DR & (uint8_t)0xff);
                ColumnRxBuffer++;
            }
            else
            {
                RxData[RowRxBuffer][ColumnRxBuffer] = (uint8_t)(huart2.Instance->DR & (uint8_t)0xff);
                ColumnRxBuffer = 0;
                RxComplete = 1;
                __HAL_UART_FLUSH_DRREGISTER(&huart2);
                RowRxBuffer = 0;
            //  tick = 0;

            }
        }

    return;
}

UART Config:

static void MX_USART2_UART_Init(void)
{

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 9600;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }

  __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);

}

The device needs to send some data over UART in non blocking mode, so i tryed to modify the code, using some if statement to check if the interrupt is generated from the incoming data or the completed transmission.

To do so i used if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE)) and if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_TC)) in the interrupt handler and adding __HAL_UART_ENABLE_IT(&huart2, UART_IT_TC); in the config function.
Doing these modification the micro doesn't even start: it goes in an unknown state and remain stuck to it. Debugging the code step-by-step i noticed that the micro goes to this unknown state when it tries to turn on a LED, which is the first thing that does this code. If necessary i could upload the entire code.

What am i doing wrong?

For sake of readability, here it is the modified code that i mentioned before https://pastebin.com/qhS2JjLm

Best Answer

If you have nothing (more) to send, then you need to disable your UART_IT_TC interrupt. This interrupt flag is set whenever the UART Transmit buffer is empty, so since you don't even load anything into the Transmit buffer this flag will always be set, resulting in the micro continuously jumping to your interrupt handler and never executing any other code.

Do not __HAL_UART_ENABLE_IT(&huart2, UART_IT_TC); until you are ready to send data and __HAL_UART_DISABLE_IT(&huart2, UART_IT_TC); in your interrupt when you have finished sending.

You could also simplify your receive code a little by moving the line RxData[RowRxBuffer][ColumnRxBuffer] = (uint8_t)(huart2.Instance->DR & (uint8_t)0xff); which is duplicated 4 times for each of the conditions so that it's executed immediately after if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE)) before any of the if/else conditions.