2024-06-26 8:56 AM
Hello,
I got a problem with HAL library 10.4 for STM32L152RE in UART DMA transmission, the data is transmited only one time using the function HAL_UART_Transmit_DMA(&huart3,t_Buffer ,11) using uart3, after that the UART3 structure keep the "flag" huart3.gState to HAL_UART_STATE_BUSY and all the other transmissions failed
it never come back to the HAL_UART_STATE_READY so it is impossible to make another transmission.
I solve the problem by changing this flag state back to "ready" when transmission is done using indirectly the (callback) transmission interrupt provided in DMA1_Channel2_IRQHandler but it is not really a solution !!
it should be OK once the data has been transmitted properly by HAL_UART_Transmit_DMA.
is it a bug in 10.4 HAL STM32L1 release ( maybe previous ones too ) or this behavior is normal and I need to use that "manual solution" ?
thanks
Thierry
2024-06-26 10:21 AM - edited 2024-06-26 10:39 AM
Look at HAL_DMA_IRQHandler, there is a section of code that handles an error interrupt raised by the DMA. Does a breakpoint there trigger? If the DMA is reporting a transmission error, you want to find out why that's happening, not why the error isn't being automatically cleared by the HAL.
2024-06-26 6:00 PM
I checked everything, including DMA and UART (should be USART because I use USART3 but it doesn't seems to be important, code has been generated by STM32CUBEMX !!!)
I make a mistake, it is HAL_UART_STATE_BUSY_TX not HAL_UART_STATE_BUSY the "flag" huart3.gState
there are no errors in DMA, or in UART HAL processes, there is just something wrong when transmit is complete with DMA in normal mode, it sets the UART IT complete but only the circular DMA seems to put the "flag" huart3.gState to HAL_UART_STATE_READY
I checked for USART HAL library 10.4 and 10.3, it is the same behavior !!!
So for now, I use indirectly the DMA1_Channel2_IRQHandler to reset the flag since the HAL_UART_TxCpltCallback seems to not working with normal DMA mode !!!
I don't know if it is the best solution, but at least it works (I don't know if properly !!)
Thierry
2024-06-27 1:31 AM - edited 2024-06-27 1:32 AM
I don't use Cube, but the general idea is, that after the DMA ended, the DMA IRQ Handler checks in DMA registers if the interrupt was Transfer Complete, and if so, UART_DMATransmitCplt() or equivalent is called (read: check the chain of events upon the DMA IRQ Handler/Transfer complete). That should set USARTx_CR1.TCIE bit, which when the stop bit of last byte is actually transmitted from USART, causes the USART IRQ Handler to be called, which has to call HAL_UART_IRQHandler() and that upon the USARTs_SR.TC flag calls UART_EndTransmit_IT(), which ultimately sets huart->gState = HAL_UART_STATE_READY; (read: check the chain of events upon the USART IRQ Handler/USARTx_SR.TC)).
In other words, once you use Cube/HAL, you have to play along all requirements Cube/HAL has on the user - and not all may be entirely documented. Clicking in Cube/MX should result in working solution, but not necessarily does if you don't follow the "just straighforward click from scratch" process, and/or modify any of the generated code.
Or, simply ditch Cube/HAL and just use that "manual solution".
JW
2025-06-23 10:19 AM
I see the same error, and am not using HAL nor CUBE to generate code (I hard-code in assembly). I have a very similar application - trying to send a 105 byte control string to UART4 at regular intervals using DMA TX. After some fiddling I got it to run, but it only ran once. very curious.
Digging around, I finally read the DMA1_LISR register after executing, and get 3 error flags set: TCIF, HTIF, FEIF. None of those make any sense according to the reference manual, and the string is transmitted faithfully. I was able to restore repeatable functionality by the following: enable the transmit, then wait for transmit complete (by timing or interrupt), then write 0x3D to DMA1_LIFCR to clear all fault bits (I'm using stream 0, adjust this for different streams).
I would be interested to find out what I am doing to generate these fault bits, but I can confirm that this behavior is in the hardware, not in the HAL or CUBE code.
(My setup is: mburst=pburst=0, trbuff=1, ct=0, dbm=0, pincos=0, pfctrl=0, minc=1, pinc=circ=0, mem to periph, bytes).
Jeff Casey
2025-06-23 1:59 PM
show your main.c and attach IOC file
2025-06-23 3:11 PM
As I said, I hard-code in assembly, there is no .c source. Below are three snippets of pseudo code from the hardware initialization section, and pre/post DMA-TX. I also use non-DMA comm over this UART for non-time critical parameter changes to the other boards on this serial link, so I have to turn on/off the DMA bursting. All three sections are nothing more than writing values to various hardware registers, so I'll just list those.
I should note that this is all on an STM32H725ZGT6. I am running SYSCLK at 400 MHz.
(initialization)
UART4_CR1, 0x2C <<<<<------- I generally run RX interrupts to an input buffer, but polled TX service
UART4_BRR, 167 <<<<<------- baud rate set to 600 kBaud
UART4_CR3, 1<<12 <<<<<------- I run with OVR disabled
UART4_CR1, 0x2D
DMA1_S0CR, 0x00120440 <<<<------- setup stream0, direct mode, bytes, mem to peripheral
DMA1_S0NDTR, 105 <<<<------- 105 byte count for burst
DMA1_S0PAR, UART4_TDR
DMA1_S0M0AR, spit <<<<<------- address of text literal to send to request data dumps
DMA1_S0FCR, 0
DMAMUX1_C0CR,0x40
(to start DMA TX burst)
UART4_CR1, 0x2C
UART4_CR3, 0x1080 <<<<-------- enables UART for DMA transmission
UART4_CR1, 0x2D
(after TX is complete)
DMA1_LIFCR,0x3D <<<<------ this is where we clear the error flags to enable repeat bursts
UART4_CR1,0x2C
UART4_CR3,1<<12 <<<<------ disables DMA transmission for normal I/O
UART4_CR1,0x2D
2025-06-23 3:14 PM
sorry, there should be one additional line at the end of the block to start the DMA burst:
DMA1_S0CR,0x00120441 <<<<<------ DMA stream EN bit turned on
2025-06-23 3:33 PM
@JCase.1 I didn't pay attention to the date. So I initially was responding to @Thierry.1