Using DMA with UART on STM32H753ZI and getting HAL_DMA_ERROR_TE (Transmission Error)
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?
