cancel
Showing results for 
Search instead for 
Did you mean: 

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

laojian
Associate II

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?

4 REPLIES 4
KnarfB
Principal III

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
Associate II

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
Chief II

> 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
Associate II

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,