STMicroelectronics / STM32CubeF4

STM32Cube MCU Full Package for the STM32F4 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
Other
827 stars 409 forks source link

UART Transmit DMA. no UART_IRQ_Handler call after transmit complete (it works in debug mode) #104

Closed thegabriele97 closed 2 years ago

thegabriele97 commented 2 years ago

Hi! So I'm trying to send some data using DMA via UART (so using UART_Transmit_DMA() function). Looking at the source code it setups a callback for the dma transfer complete and calls HAL_DMA_Start_IT(). When the transfer finishes, DMA_IRQ_Handler is called and calling HAL_DMA_IRQHandler() it calls the callback that enables the TransferComplete interrupt.

This action should launch the UART_IRQ_Handler() but this doesn't happen! Even if the NVIC is set up properly.

The only way I found to launch is to call __HAL_UART_ENABLE_IT(&huart, UART_IT_TC) before UART_Transmit_DMA(). But this is not enough, the only way to make it works is to place a breakpoint at __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC) (inside stm32f4xx_hal_uart.c) in this way the interrupt routines (DMA & UART_IRQ_Handler) are executed first then __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC)is executed at the end.

Is this normal or I am doing something wrong?

EDIT: Ok I discovered another think, I better understood the problem now. Starting from the fact that __HAL_UART_ENABLE_IT(&huart, UART_IT_TC) is useless in my case ( I don't need to enable the ITC bit in the register), there is always the same problem.

The DMA callback enables the ITC but meanwhile the TC status flag has been cleared so no interrupt fires. If I put a breakpoint before clearing the TC status flag, the ITC is set by the callback and the interrupt fires successfully!

What is the meaning of clearing this flag inside UART_Transmit_DMA()?

/* 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); //<<<!!!--- why this?

/* Process Unlocked */
__HAL_UNLOCK(huart);
KORKAD commented 2 years ago

Hello @thegabriele97, The purpose for clearing TC flag is just to ensure that no data in USART DR register before starting a new transfert.

The new transfert will be start just when enabling the DMA transmit request by setting the DMAT bit in the UART CR3 register.

So, if you put breakpoint before enabling the DMA transmit request you shall expect no data transmitted. Please check that the DMAT bit in the UART CR3 is in stat 0 before calling the HAL_UART_Transmit_DMA().

Maybe you have a previous UART transmit DMA transfer that is not yet finished...

With Regrds KORKAD

ASELSTM commented 2 years ago

Hi @thegabriele97,

Please allow me to close this thread as there is no activity since a couple of months. You can reopen it at any time if you have more details so that we can help you.

With regards,