cancel
Showing results for 
Search instead for 
Did you mean: 

USART Tx DMA on STM32H5

iguffick2
Associate III

I'm using an STM32H563 and the STM32CubMX for initialisation. I'm trying to use the USART in DMA mode and having trouble with the Tx DMA.

I use:

HAL_UARTEx_ReceiveToIdle_DMA(&huart10, (uint8_t *) uart10RxDMABuffer, UART10_RX_BUFFER_SIZE);

for the receive and get characters into my buffer and an interrupt after IDLE. In the interrupt I start a timer (for a delay). I get the timer interrupt then attempt:

HAL_UART_Transmit_DMA(&huart10, (uint8_t*)uart10TxDMABuffer, uart10TxSize);

This completes with a HAL_OK. But I don't get any characters from the UART and I don't get a transfer complete interrupt.

The DMA of the H5 (M33) is completely different to previous series. Are there any other steps I need to take that are particular to the H5 DMA controller?

Edit:

I've also noticed that if I comment the HAL_UART_Transmit_DMA I can receive multiple strings from the UART Rx and each time get an interrupt on the IDLE. Once I've attempted to call the transmit DMA the receive side stops working.

 

9 REPLIES 9
Foued_KH
ST Employee

Hello @iguffick2 , 

Could you please share your .ioc file and the code ?
I couldn't reproduce the issue ;

Foued_KH_0-1696601021503.png

 



Foued

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.

TDK
Guru

Does a blocking HAL_UART_Transmit call work?

You could look at the state of the DMA for error flags after the TC interrupt fails to happen.

If you feel a post has answered your question, please click "Accept as Solution".
iguffick2
Associate III

Thank you for your suggestions. I made a separate project with just the UART initialisation and test code. Thinking this would be cleaner and more concise to upload as an non-working example.

It works fine. In that I can receive, then send using polled or DMA, and I'm still able to receive again.

It must be something else in my bigger project that is interfering. I'll start adding blocks back in until it fails again.

 

iguffick2
Associate III

I've found the problem. In my cut down test I happened to use a 4 byte size on the call to HAL_UART_Transmit_DMA and I'm using 8 bit with parity, which requires a 16 bit buffer.

The call to HAL_UART_Transmit_DMA requires the size parameter in bytes, even thought the buffer is in words. Calling with an odd number stops the UART working.

The function in stm32H5xx_hal_uart.c does have a check for 9 bit and doubles the size value, but it only works for 9 bit and no parity, it should also be applicable for 8 bit with parity.

if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
nbByte = Size * 2U;
}

Similarly the HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) gives the size in bytes, not in words.

This is different to the way these functions work for instance on the H7 series.

IMHO this is a bug in the implementation of the HAL. Surely the whole idea of the HAL is that these functions remain the same across different silicon?

TDK
Guru

> The call to HAL_UART_Transmit_DMA requires the size parameter in bytes, even thought the buffer is in words.

Haven't used the U5, but on the F4, F7, H7 the parity bit is definitely not part of the buffer. Would be surprised if it's different on the U5. The comments in the code suggest it works the same there (arguments are words, not bytes).

If you feel a post has answered your question, please click "Accept as Solution".
iguffick2
Associate III

> Haven't used the U5, but on the F4, F7, H7 the parity bit is definitely not part of the buffer

I've now done this on the H5 and H7.

Both require a 16 bit buffer for the TX and Rx.  e.g. uint16_t TxBuffer[256]

To send 5 serial characters:

On the H7 I'd use HAL_UART_Transmit_DMA(&huart10, (uint8_t*)TxBuffer, 5);

On the H5 I have to use HAL_UART_Transmit_DMA(&huart10, (uint8_t*)TxBuffer, (5*2));

 

And you thought that the HAL code is written by people, who understand and care about what they are doing? What a naive idea... ;)

Previously there was a tag "bug-report" and at least the senior users could modify the tags of the topic and mark topics like this one with that tag. As you can see, that way we could create a list of bug reports for ST. The list is too long and shameful, therefore, when moving the forum, they "solved" the problem by removing any bug reporting option. So now topics like this one can be better ignored and managers can report to the bosses that the problems are solved: "See, no bug reports anymore!"

Edited by moderation to adhere to community guidelines.

Foued_KH
ST Employee

Hello @iguffick2 , 

For 8bit + parity configuration, for example Rx mode, the parity bit is received by the peripheral but is not part of the data retrieved by the HAL by reading the RDR register. The peripheral uses it to indicate the parity error or not.
So, as far as the data is concerned, only 8 bits are available. We need to use u16 for user buffers, only in 9B/No parity config.

Foued

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.

CDavi.3
Associate II

specifically regarding UART, DMA and H5 series, please check the following ERRATA:

https://www.st.com/resource/en/errata_sheet/es0621-stm32h523xx-and-stm32h533xx-device-errata-stmicroelectronics.pdf

Basicalliy: "USART does not generate DMA requests after setting/clearing DMAT bit"

A possible workaround is to don't clear this DMAT bit.

So look for any of: ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);

This is done, among other, in: static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)

 

So my guess is: if you are using UART+DMA and interrupts, I am quite sure that tha function "UART_DMATransmitCplt" is called and the DMA tx won't work anymore for the next transmission.

Maybe you have a chance if you are not using interrupt, but I am not sure.