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?

This discussion is locked. Please start a new topic to ask your question.
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

Announcement

We’re moving the ST Community to a new platform to give you a better and more reliable community experience.