2

According to documentation, many of STM32's supports DMA in Double-Buffer (or also known as Multi-Buffer) mode. In HAL, there are two functions for this feature: HAL_DMAEx_MultiBufferStart and HAL_DMAEx_MultiBufferStart_IT in stm32xxxx_hal_adc_ex file. But in any SDK (H7, F7, F4 etc.), there are not single example of usage of those two functions. How to get this double-buffering DMA working together with ADC?

3 Answers 3

1

I`ve configure DMA in Double buffer mode for I2S interface. My sequence looks like this:

/*Starting with DMA in single buffer mode*/
HAL_I2S_Transmit_DMA(&hi2s3, Addr, Size);

/* Pause current DMA by disconnecting it from periphery (in my case - i2s interface) */
HAL_I2S_DMAPause(&hi2s3);

/* Mask all DMA interrupt, deal with internal state machine of dma handle */
HAL_DMA_Abort(hi2s3.hdmatx);

/* Set callback for XferCplt/XferHalfCplt interrupt for second buffer (I just set it to the same, that I`ve already have for first buffer) */
hi2s3.hdmatx->XferM1CpltCallback = hi2s3.hdmatx->XferCpltCallback;
hi2s3.hdmatx->XferM1HalfCpltCallback = hi2s3.hdmatx->XferHalfCpltCallback;

/*Configure DMA in Double Buffer mode*/
HAL_DMAEx_MultiBufferStart_IT(hi2s3.hdmatx,
                                  (uint32_t)Addr,
                                  (uint32_t)&hi2s3.Instance->DR,
                                  (uint32_t)(Addr + (Size >> 1)),
                                  Size >> 1);


/*Connect periphery to newly configured DMA in double buffer mode*/
HAL_I2S_DMAResume(&hi2s3);

Hope this will help.

Sign up to request clarification or add additional context in comments.

Comments

0

I never used the functions you mentioned for double buffer technique. I simply create a buffer, which has double the size of a "normal" buffer and use the DMA Callback functions HAL_ADC_ConvCpltCallback and HAL_ADC_ConvHalfCpltCallback for the decision which half of the buffer needs to be processed.

On an "HAL_ADC_ConvCpltCallback" Interrupt the upper half of the Double Buffer is processed while the ADC is writing its data in the lower half and vice versa ...

So: if I want e.g. to process my data in blocks of 100 samples, I create a buffer with 200 samples

uint32_t ADC_DMABuffer[ADC_DMABufferSize * 2];

and start the ADC with

HAL_ADC_Start_DMA(&hadc1, ADC_DMABuffer, ((uint32_t)(ADC_DMABufferSize * 2)));  // Double Buffer

For processing the data in the lower half the start pointer is

ADC_DMABuffer[0]

for the upper half the start pointer is

ADC_DMABuffer[ADC_DMABufferSize]

and the count of data, that need to be processed is of course "ADC_DMABufferSize" ...

5 Comments

I allmost forgot - here you can find a ADC DMA Double Buffer example for the STM32F103: bepat.de/2020/11/27/… - you can ignore the "Dual Regular simultaneous" featrue, the principle of how to handle the data buffer stays the same ...
Thanks for you message. Yes, this is one of the ways how to have double buffering, but there is one catch. The DMA's Multi-Buffer feature have one great feature, you can change the pointers of buffers on the fly HAL_DMAEx_ChangeMemory. That's the feature I need, and it's not possible to do it with your current solution.
Hi @GAMELASTER I am trying to do the same thing, any update on this?
Hi @a_bet , I'm sorry but I don't remember exactly, but I think I wasn't able to solve it :(
@GAMELASTER no problem, will reply here if I manage to do it
0

HAL_ADC_Start_DMA and HAL_DMAEx_MultiBufferStart_IT, these two functions have conflicts. If you insist on using HAL_DMAEx_MultiBufferStart_IT, you should modify it or do something outside as _hal_unlock(hdma).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.