Skip to main content
laojian
Associate II
February 25, 2021
Question

How does HAL_UART_Transmit_IT() triggered Interrupt handler HAL_UART_IRQHandler() for data sending?

  • February 25, 2021
  • 4 replies
  • 2089 views

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

{

 /* Check that a Tx process is not already ongoing */

 if (huart->gState == HAL_UART_STATE_READY)

 {

  if ((pData == NULL) || (Size == 0U))

  {

   return HAL_ERROR;

  }

  /* Process Locked */

  __HAL_LOCK(huart);

  huart->pTxBuffPtr = pData;

  huart->TxXferSize = Size;

  huart->TxXferCount = Size;

  huart->ErrorCode = HAL_UART_ERROR_NONE;

  huart->gState = HAL_UART_STATE_BUSY_TX;

  /* Process Unlocked */

  __HAL_UNLOCK(huart);

  /* Enable the UART Transmit data register empty Interrupt */

  __HAL_UART_ENABLE_IT(huart, UART_IT_TXE);

  return HAL_OK;

 }

 else

 {

  return HAL_BUSY;

 }

}

The code initializes UART_HandleTypeDef *huart at abstract layer, and enables TXEIE. But in order to start a real transmission, you need to write to DR to start an immediate TX if none is in progress, then get a TXE to trigger the ISR to send. How does this trigger happen?

This topic has been closed for replies.

4 replies

KnarfB
Super User
February 25, 2021

When the TX interrupt flag is enabled, the interrupt will be triggered as soon as the condition is met.

The interrupt handler calls HAL_UART_IRQHandler which calls UART_TxISR_8BIT /16BIT which does the work (writing to TDR),

hth

KnarfB

laojian
laojianAuthor
Associate II
February 27, 2021

Hi KnarfB,

Thanks for your reply. Actually, the core reason is that the initial value of SR is 0xc0, which means the initial value of TXE is 1. So when  __HAL_UART_ENABLE_IT(huart, UART_IT_TXE) is executed, it will automatically trigger the ISR (both TXE and TXEIE is 1), and in ISR, the data will be copied to DR, and this copy will trigger TX immediately.

You need to have TXE == 1 to trigger the ISR, and only in ISR that TX can be started, but you need the TX to be started to get TXE to 1, it is a dead loop. The solution is initialize TXE to 1. It solves all.

Regards,

Jian

Piranha
Principal III
February 27, 2021

> in order to start a real transmission, you need to write to DR to start an immediate TX if none is in progress, then get a TXE

Not exactly. The important concept to understand is that the TXE interrupt happens whenever the transmit register is empty. It doesn't require a data transmission before to get TXE interrupt. Therefore transmission with interrupts just have to enable TXEIE and the actual transmission (even the first byte) can happen in interrupt.

laojian
laojianAuthor
Associate II
February 28, 2021

Hi Piranha,

Yes, you are right, a finished transmission is not necessary to have TXE to be 1, and I think that is also why TXE is initializd to be 1.

Regards,