STMicroelectronics / STM32CubeF4

STM32Cube MCU Full Package for the STM32F4 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
Other
869 stars 418 forks source link

No doublebuffered version of HAL_UART_Receive_DMA? #89

Closed santalint closed 2 years ago

santalint commented 3 years ago

For continuous reception of data on UART, it is desirable to use doublebuffering, but the HAL does not provide any such function.

Right now I have to modify the HAL to achieve this, but I believe there should be an official implementation of this.

bmcdonnell-fb commented 3 years ago

@santalint wouldn't you just alternate the destination parameter you give to it each time?

santalint commented 3 years ago

Originally, I did it the way you describe @bmcdonnell-fb but I found the DMA double buffer capability to be a better option, as it don't require extra code to do the switching.

bmcdonnell-fb commented 3 years ago

I think using that method shouldn't require any changes to the HAL, though, right?

santalint commented 3 years ago

No changes would be needed if there was a double buffer version of HAL_UART_Receive_DMA, or if that function handled that case, but I couldn't find any such, and ended up making changes on my own.

bmcdonnell-fb commented 3 years ago

What changes did you need to make, and why was it required? Changing the value of a parameter (pointer) that you pass to the function isn't a library change.

Obviously it's nicer when a library already supports the thing you want to do. But I don't understand what change you're suggesting needs to be made to the library itself in order to implement what you want.

(Mind you, I'm not an ST employee; just an interested developer.)

santalint commented 3 years ago

If you follow HAL_UART_Receive_DMA to UART_Start_Receive_DMA it only assigns a single buffer to put data in. It also only sets XferCpltCallback and XferHalfCpltCallback (aside from the error callback and abort callback), before calling HAL_DMA_Start_IT. For double buffered, you need to set two buffers, and also set XferM1CpltCallback and XferM1HalfCpltCallback, followed by a call to HAL_DMAEx_MultiBufferStart_IT instead of HAL_DMA_Start_IT. As there is no function (that sets the relevant extra parts) in the the UART part of the HAL, I had to write it myself.

My request is only to have the same functionality provided by default in the HAL.

bmcdonnell-fb commented 3 years ago

If I understand correctly, you still could use the existing HAL library without modification, but you'd have to kick off each "ping" and "pong" yourself (with e.g. HAL_UART_Receive_DMA()), instead of calling something that wraps HAL_DMAEx_MultiBufferStart_IT() once.

bmcdonnell-fb commented 3 years ago

It does seem like it would be cleaner and more consistent if they provided that function to wrap HAL_DMAEx_MultiBufferStart_IT(), though.

santalint commented 3 years ago

As I said, I did use that approach before changing to double buffered. One reason I prefer the double buffer approach is that reception can continue before the receive complete interrupt is serviced, as the DMA controller switches to the other buffer by itself.

bmcdonnell-fb commented 3 years ago

We seem to be using the term "double buffered" differently. IME, what I described is still "double buffering", albeit maybe with more processor intervention.

So to be more precise, if I understand correctly, HAL modification isn't required to perform double buffering on a UART per se. But HAL modification is required in order to do the double buffering using the existing HAL_DMAEx_MultiBuffer functions.

Have I got it now?

santalint commented 3 years ago

Yes, I meant the double buffer functionality as provided by the DMA controller. Sorry for the confusion.

KORKAD commented 2 years ago

Hello @santalint,

Thank you for this interresting raised request. But, I don't understand the real needs... From application point of view. What is the limitation, to dont use two consicutive DMA transfer? you can start a second transfert inside the XferCpltCallback(). Do you know, if a specific standard protocol exist that required such specific HAL UART service?

With Regards KORKAD

santalint commented 2 years ago

If I am supposed to start a new transfer during XferCpltCallback there will be an inherent delay between the interrupt and start of new transfer. This is of course affected by interrupt priorities and what other interrupts may occur at the same time. By utilizing the double buffer functionality provided by the DMA controller there won't be any such delay between transfer complete and transfer start.

ASELSTM commented 2 years ago

Hi,

Thank you for your contribution and for this insightful request. There is unfortunately no plan to support such feature for the moment.

However, the driver offers the reception to idle feature which can be useful for the purpose. You may refer to the UART_ReceptionToIdle_CircularDMA example delivered within the STM32CubeF4 firmware. The example allows to handle reception of Data from Hyperterminal using DMA and notify application of already received data while the reception is still ongoing.

Otherwise, you may also refer to the USART_Communication_Rx_IT_Continuous example provided within STM32CubeL4 firmware. A double buffer is available for received data, allowing continuous reception.

Hope this will help you. Please allow me to close the issue. Thank you for your comprehension.

With regards,

kjsdf7wr3 commented 2 years ago

@santalint I am using https://github.com/jrahlf/stm32_uart_dma_buffered. You can use it as is or as a starting point.