[Bug report] HAL_UART_TxCpltCallback() doesn't get called in DMA normal (instead of circular) mode
I believe I may have found a bug in the latest version (1.24.1) of the STM32F4 HAL library.
The HAL documentation states this about using UART in DMA mode:
DMA mode IO operation
- Send an amount of data in non blocking mode (DMA) using HAL_UART_Transmit_DMA()
- ...
- At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can add his own code by customization of function pointer HAL_UART_TxCpltCallback
However, here is the code called when a UART DMA Tx is completed:
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 = 0x00U;
/* 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
{
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Tx complete callback*/
huart->TxCpltCallback(huart);
#else
/*Call legacy weak Tx complete callback*/
HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}As can be seen, the callback is only called when DMA is in circular mode. This isn't mentioned in the documentation, and moreover, it makes no sense to me: if I fire a UART transfer in normal mode, this callback is exactly what I'd like to use to monitor when the transfer ends. I don't see why this callback should be restricted to circular mode.
Also, if you look at, say, the SPI code, it doesn't distinguish between DMA normal and circular mode; it calls the callback either way. The code for I2C is way more complex, but I also don't see it making a distinction between DMA normal and circular mode. So, at a minimum, the UART behavior is inconsistent.
I suggest the call to the callback be taken out of the else clause, so it gets called regardless of whether DMA is in normal or circular mode.
