2015-10-02 05:39 AM
Using HAL, I have configured DMA1_CH2 and USART3_TX such that once in a while, a block of bytes will be copied from memory to peripheral, in NORMAL, i.e. non-circular mode.
Now, my handler, HAL_USART_TxCpltCallback, never gets called - but the one for the half complete does get called. In file stm32L4xx_hal_usart.c, function USART_DMATransmitCplt, the HAL_USART_TxCpltCallback is called. BUT: only when the DMA is in circular mode. Is this a bug, or does this somehow make sense and I have misunderstood how to use this feature? This HAL-internal handler does get called, so my configuration basically works I guess. For my USART Transmission in normal mode, I don't care for the half-completed callback, I only need to know when it's done. How is it supposed to be done? Thanks in advance2015-10-02 08:44 AM
Hi kledtke.steve.002,
When using DMA for UART transmission in normal mode, the UART Transmit Complete Interrupt is enabled with the call of UART_DMATransmitCplt.If you check the UART_IRQHandler, at the end of transmission, UART_EndTransmit_IT is called. At this level, UART state is set to ready and HAL_UART_TxCpltCallback is used.So in your code, pay attention to enable UART IRQ Handler in your it.c file.-Mayla-To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2015-10-05 06:45 AM
Hello,
the handler for the DMA channel is active in ..._it.c file, calling: HAL_DMA_IRQHandler( husart3.hdmatx ); In the USART_DMATransmitCplt function, the user-implemented handler is only called in the block titled ''circular mode''. See below. In USART_EndTransmit_IT, the user-provided handler, HAL_USART_TxCpltCallback,is indeed called. But according to the comments in the source file, that HAL_USART_IRQHandler, where USART_EndTransmit_IT is called,is only for the interrupt-based non-blocking mode, as when HAL_USART_Transmit_IT iscalled - not for DMA mode, i.e. when HAL_USART_Transmit_DMA is called. So I still don't understand how this is supposed to work. Have I overlooked something? Thanks,/*
(#) Non-Blocking mode API's with Interrupt are :
(++) HAL_USART_Transmit_IT()in simplex mode
(++) HAL_USART_Receive_IT() in full duplex receive only
(++) HAL_USART_TransmitReceive_IT()in full duplex mode
(++) HAL_USART_IRQHandler()
(#) No-Blocking mode API's with DMA are :
(++) HAL_USART_Transmit_DMA()in simplex mode
(++) HAL_USART_Receive_DMA() in full duplex receive only
(++) HAL_USART_TransmitReceive_DMA() in full duplex mode
(++) HAL_USART_DMAPause()
(++) HAL_USART_DMAResume()
(++) HAL_USART_DMAStop()
*/
static
void
USART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef* husart = ( USART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
/* DMA Normal mode */
if
( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
{
husart->TxXferCount = 0;
if
(husart->State == HAL_USART_STATE_BUSY_TX)
{
/* Disable the DMA transfer for transmit request by resetting the DMAT bit
in the USART CR3 register */
husart->Instance->CR3 &= ~(USART_CR3_DMAT);
/* Enable the USART Transmit Complete Interrupt */
__HAL_USART_ENABLE_IT(husart, USART_IT_TC);
// TEST: has this been forgotten, is this a bug?
//HAL_USART_TxCpltCallback(husart);
}
}
/* DMA Circular mode */
else
{
if
(husart->State == HAL_USART_STATE_BUSY_TX)
{
HAL_USART_TxCpltCallback(husart);
}
}
}
Hikledtke.steve.002,
When using DMA for UART transmission in normal mode, the UART Transmit Complete Interrupt is enabled with the call ofUART_DMATransmitCplt. If you check the UART_IRQHandler, at the end of transmission,UART_EndTransmit_IT is called. At this level, UART state is set to ready andHAL_UART_TxCpltCallback is used. So in your code, pay attention to enable UART IRQ Handler in your it.c file. -Mayla-2015-10-08 04:26 AM
Hikledtke.steve.002,
In the file stm32l4xx_it.c, you have to add:void
USARTx_IRQHandler( void ) { HAL_UART_IRQHandler(&UartHandle); } The explanation: when using DMA, you will have ''UART_DMATransmitCplt'' called. If you are in DMA Normal mode, the UART Transmit Complete Interrupt will be enabled:static
void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) { UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; /* DMA Normal mode */ if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) { huart->TxXferCount = 0; /* Disable the DMA transfer for transmit request by resetting the DMAT bit in the UART CR3 register */ huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAT); /* Enable the UART Transmit Complete Interrupt */ __HAL_UART_ENABLE_IT(huart, UART_IT_TC); } /* DMA Circular mode */ else { HAL_UART_TxCpltCallback(huart); } } This interrupt has to be managed with the UART IRQ handler. That is why I suggested to add it. -Mayla-To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.