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?

- 1,071
- 1
- 12
- 23
3 Answers
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.

- 21
- 2
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" ...

- 359
- 5
- 13
-
I allmost forgot - here you can find a ADC DMA Double Buffer example for the STM32F103: http://www.bepat.de/2020/11/27/stm32f103c8-adc-dual-regular-simultaneous-mode/ - you can ignore the "Dual Regular simultaneous" featrue, the principle of how to handle the data buffer stays the same ... – Chris_B Jan 31 '21 at 06:05
-
1Thanks 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. – GAMELASTER Jan 31 '21 at 10:14
-
Hi @GAMELASTER I am trying to do the same thing, any update on this? – a_bet Jul 26 '22 at 18:36
-
Hi @a_bet , I'm sorry but I don't remember exactly, but I think I wasn't able to solve it :( – GAMELASTER Jul 28 '22 at 11:50
-
@GAMELASTER no problem, will reply here if I manage to do it – a_bet Jul 31 '22 at 13:21
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)
.

- 5,753
- 72
- 57
- 129

- 1