cancel
Showing results for 
Search instead for 
Did you mean: 

Using DMA with UART on STM32H753ZI and getting HAL_DMA_ERROR_TE (Transmission Error)

KEria.1
Associate III

Hello,

I am trying to set the UART5 TX with the DMA. I am using Cube, and in the GUI I selected UART5 to asynchronous, and added DMA for UART5_TX. Then, in the generated code, I added this part as I didn't see initialization for the DMA (inside the MX_DMA_Init()):

  /* Peripheral DMA init*/
  hdma_uart5_tx.Instance = DMA1_Stream0;
  //hdma_uart5_tx.Init.Channel = DMA_CHANNEL_4;
  hdma_uart5_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_uart5_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_uart5_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_uart5_tx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_uart5_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_uart5_tx.Init.Mode = DMA_NORMAL;
  hdma_uart5_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
  hdma_uart5_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_Init(&hdma_uart5_tx);
 
    __HAL_LINKDMA(&huart5,hdmatx,hdma_uart5_tx);

The Main function, I didn't do much except I added this code in the while(1):

while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
	  if (HAL_UART_Transmit_DMA(&huart5,au8ch, 1) == HAL_OK)
	  {
		  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET);
	  }
	  else
	  {
		  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
	  }
	  HAL_Delay(1000);
  }
  /* USER CODE END 3 */

Which is a code to transmit the first byte of an array. I connected the Nucleo-H753ZI board pins to a terminal software, and I didn't get anything. (Note that I was able to get something without using the DMA). The LED turned ON, which means the function is returning HAL_OK, but still nothing on the screen.

I tried to debug the code, I put a breakpoint in the function "void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)" and it stops there, which means it got the interrupt to send something, but then it goes into this autogenerated code:

if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U)  /* DMA1 or DMA2 instance */
  {
    /* Transfer Error Interrupt management ***************************************/
    if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
    {
      if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U)
      {
        /* Disable the transfer error interrupt */
        ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  &= ~(DMA_IT_TE);
 
        /* Clear the transfer error flag */
        regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
 
        /* Update error code */
        hdma->ErrorCode |= HAL_DMA_ERROR_TE;
      }
    }
...
...
...
/* manage error case */
    if(hdma->ErrorCode != HAL_DMA_ERROR_NONE)
    {
      if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U)
      {
        hdma->State = HAL_DMA_STATE_ABORT;
 
        /* Disable the stream */
        __HAL_DMA_DISABLE(hdma);
 
        do
        {
          if (++count > timeout)
          {
            break;
          }
        }
        while((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U);
 
        /* Process Unlocked */
        __HAL_UNLOCK(hdma);
 
        if((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
        {
          /* Change the DMA state to error if DMA disable fails */
          hdma->State = HAL_DMA_STATE_ERROR;
        }
        else
        {
          /* Change the DMA state to Ready if DMA disable success */
          hdma->State = HAL_DMA_STATE_READY;
        }
      }
 
      if(hdma->XferErrorCallback != NULL)
      {
        /* Transfer error callback */
        hdma->XferErrorCallback(hdma);
      }
    }
  }

Any idea what I may be missing?

12 REPLIES 12

Does that answer your question?

/* Specify the memory areas */
MEMORY
{
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 2048K
  RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
  RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH = 512K
  RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
  RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
}

KEria.1
Associate III

New update, so the previous memory map I did in the RAM.ld, I did the same in flash.ld file, and it started to transmit data now.

However, for some reason it is not transmitting what I am sending, and it is continuously transmitting. (not stopping after the 4 bytes I am sending)

KEria.1
Associate III

@Community member​  and @TDK​ Thank you both for your help.

I figured it out. I had to build void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) function in which I put the values I need to send, also in the Cube GUI, I had to make it Normal not circular in order to send the data only once.

It is working to send one array now. Thanks!

Karim