cancel
Showing results for 
Search instead for 
Did you mean: 

UART DMA TX complete callback issue

RN
Senior

Hello,

In the uart driver code of STM32 CUBE layer i found this,

static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)

{

 UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;

 /* DMA Normal mode*/

 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)

 {

  huart->TxXferCount = 0U;

  /* Disable the DMA transfer for transmit request by setting the DMAT bit

    in the UART CR3 register */

  CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);

  /* Enable the UART Transmit Complete Interrupt */

  SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);

 }

 /* DMA Circular mode */

 else

 {

  HAL_UART_TxCpltCallback(huart);

 }

}

if DMA Is in normal mode , HAL_UART_TxCpltCallback() is not called ,

then , how to get UART DMA tx complete callabck in normal mode ??

also who makes huart->gState = HAL_UART_STATE_READY; ?

Please help

5 REPLIES 5

Can't help you, bumping you off my feed

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
RN
Senior

Hi Clive,

Sorry, whats wrong ?

dcomer
Associate II

Hi RN, I don't have a complete answer, but if you refer to the document UM1725, "Description of STM32F4HAL and LL drivers", section 20, "HAL DMA Generic Driver", subsection 20.2 has the following:

"At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can add his own function by customization of function pointer XferCpltCallback and XferErrorCallback (i.e a member of DMA handle structure)."

Furthermore, in section 2.12.3.2 Interrupt mode, there is an example of how to use. That said, I don't have it quite working but expect to in the next day. Let me know if this is what you are looking for and, if so, I will post a response on how I get it working. If you beat me to, please reply with your solution.

Dave

HYu.5
Associate II

Just encountered the same problem here.

Seems like it forget to reset it. I can only send it once and then always get serial port busy. I'm thinking about write own interrupt service.

Do you find the solution?

Note, that in the non-circular leg of UART_DMATransmitCplt() the USART Tx interrupt is enabled by SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);

So the idea here is, that this is a "go to complete end" transfer thus the transfer is deemed finished not when DMA moves the last byte to USART->DR, but later, when the last byte actually leaves the USART, ie. when USART->SR. TC is set. In other words, the HAL_UART_TxCpltCallback() is here called from USART_EndTransmit_IT() which you are supposed to have hooked on the USART interrupt servicing routine (and have that ISR enabled somewhere in the startup code of course).

I don't Cube/HAL.

JW