cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Transmit_DMA does not check if DMA is actually ready?

Matthias1
Associate

Hi,

I am using STM32Cube_FW_F4_V1.24.2. I noticed that HAL_UART_Transmit_DMA internally only checks the UART state (line 17) but completely ignores the return value of HAL_DMA_Start_IT (line 48). So what will happen if HAL_DMA_Start_IT returns HAL_BUSY for instance? In this case HAL_UART_Transmit_DMA would return HAL_OK although the start of the DMA transfer actually failed? In this case the data would never be sent. Or is this scenario impossible (by design)?

/**
  * @brief  Sends an amount of data in DMA mode.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         the sent data is handled as a set of u16. In this case, Size must indicate the number
  *         of u16 provided through pData.
  * @param  huart  Pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  pData Pointer to data buffer (u8 or u16 data elements).
  * @param  Size  Amount of data elements (u8 or u16) to be sent
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t *tmp;
 
  /* 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;
 
    /* Set the UART DMA transfer complete callback */
    huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;
 
    /* Set the UART DMA Half transfer complete callback */
    huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;
 
    /* Set the DMA error callback */
    huart->hdmatx->XferErrorCallback = UART_DMAError;
 
    /* Set the DMA abort callback */
    huart->hdmatx->XferAbortCallback = NULL;
 
    /* Enable the UART transmit DMA stream */
    tmp = (uint32_t *)&pData;
    HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t *)tmp, (uint32_t)&huart->Instance->DR, Size);
 
    /* Clear the TC flag in the SR register by writing 0 to it */
    __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
 
    /* Process Unlocked */
    __HAL_UNLOCK(huart);
 
    /* Enable the DMA transfer for transmit request by setting the DMAT bit
       in the UART CR3 register */
    SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
 
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

Thanks in advance!

Kind regards,

Matthias

2 REPLIES 2

Please note that this is a primarily user-driven forum with casual ST presence. We haven't seen much feedback from the Cube/HAL developers here, either. And most users who provide answers here apparently don't use Cube/HAL.

So, if you have doubts about it, you may be better off not using Cube/HAL.

JW

Piranha
Chief II
  1. Of course the same is true also for USART driver. Actually UART driver should be eliminated as it's a subset of USART anyway.
  2. HAL's "busy" concept and many other things must also be eliminated or replaced.
  3. The same goes for HAL developer team and management...