2017-04-10 03:51 AM
Hi everyone,
I've been struggling with a problem a few years ago.
I want to send data to my computer via uart and to free the mcu, I need it to be done with dma.
The problem was, the first transmission worked fine but I couldn't send a second transmission.
When running my nucleo (f411re) under gdb, I could see that the second transmit never started because huart->gState remain set to HAL_UART_STATE_BUSY_TX.
I modify the stm32f4xx_hal_uart.c source code for the stm32cubeMX HAL library and it worked well.
Today, I start a new project and I realize that 2 years later this bug is still there with the latest HAL library !!!
Here is my modified uart source code. The changes are around line 2000
Could someone from ST confirm that it is indeed an error in the library or I'm misusing the dma somehow...
Solved! Go to Solution.
2017-04-10 11:03 AM
Hello,
You should
enable HAL_UART_IRQHandler() inside 'stm32f4xx_it.c',
this will ensure the USART communication by checking the flag, as the set of the ready flag is managed inside HAL_UART_IRQHandler() by the UART_EndTransmit_IT().
I suggest you refer to ready-use UART example using DMA in STM32CubeF4:
For more clarification, you can refer to the 'Continuous communication using DMA' paragraph in the reference manual RM0090 and
follow the UM1725 in the section 'UART Firmware driver API description'.
Hope this helps you.
Imen
2017-04-10 05:35 AM
I checked through your zip file.
what is the bug ?
this is my Uart DMA code.
void IO::CheckTxDMABufferProgress(void) {
if (DMABufHasData) {
char uartState = HAL_UART_GetState(&huart1);
if ((uartState == HAL_UART_STATE_READY) || (uartState == HAL_UART_STATE_BUSY_RX)) {
DMABufHasData = false;// sending now
if (HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Usart1TxDMABuffer + U1TxBufferPtrOUT, U1TxBufferPtrIN - U1TxBufferPtrOUT) == HAL_OK) {
HAL_UART_Transmit_DMA_Status = UartDMAsuccess; //flag only not needed
U1TxBufferPtrOUT = U1TxBufferPtrIN; //now our buffer is empty, but still transmitting, DO NOT DISTURB whist transmittingempty
}else {
Error_Handler();/* Transfer error in transmission process */
HAL_UART_Transmit_DMA_Status = UartDMAfailed; //flag only not needed
}
}
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-04-10 07:50 AM
Hi Nick, thanks for taking the time
At around line 2000, I added a line to change the huart.gState flag from HAL_UART_STATE_BUSY_TX to HAL_UART_STATE_READY in the UART_DMATransmitCplt() callback function.
When, in your example, you call :
if (HAL_UART_Transmit_DMA(&huart1, [...] ) == HAL_OK) { ... }
The HAL_UART_Transmit_DMA function (at line 895 in the file I uploaded) sets 'huart->gState' to HAL_UART_STATE_BUSY_TX which is fine but when the transfer is completed, it should be set back to HAL_UART_STATE_READY. The HAL library does not reset the flag when dma transmission is completed and a second transmission cannot be started because the peripheral is still considered busy...
2017-04-10 11:03 AM
Hello,
You should
enable HAL_UART_IRQHandler() inside 'stm32f4xx_it.c',
this will ensure the USART communication by checking the flag, as the set of the ready flag is managed inside HAL_UART_IRQHandler() by the UART_EndTransmit_IT().
I suggest you refer to ready-use UART example using DMA in STM32CubeF4:
For more clarification, you can refer to the 'Continuous communication using DMA' paragraph in the reference manual RM0090 and
follow the UM1725 in the section 'UART Firmware driver API description'.
Hope this helps you.
Imen
2017-04-11 10:13 AM
Ha HA, Thanks Imen !
It is just a serious case of plain stupid me
I did as you said : '
refer to ready-use UART example
' (a bit annoyed to be honest, because my code came from there, but still... maybe I missed something...)It turns out that I declared a function in stm32f4xx_it.h named : USARTx_DMA_TX_IRQHandler() ... but It come with the
♯ define
USARTx_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler (in main.h in the example)
So of course the HAL_UART_IRQHandler() function was never called ...........
So, my bad everyone, and Imen I owe you one !