cancel
Showing results for 
Search instead for 
Did you mean: 

ADC in dual interleaved mode with normal DMA buffer.

Satty
Associate II

Hello, i am using STM32F746ZG to sample and process large amounts of ADC data. To increase it's speed dual interleaved mode is used. And because of low processing speed, the main idea is sample many samples of single channel (~50K) and process them.

First time, I call ADC, all works as expected and i get interrupt when buffer becomes filled.

  HAL_ADC_Start(&hadc2);
  HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)AData, sizeof(AData) / sizeof(uint32_t));

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    HAL_ADC_Stop(&hadc1);
    HAL_ADC_Stop(&hadc2);
/* send signal that data is ready */
}

But when it is called next time, no interrupt is generated. I can see that ADC is enabled and running, but DMA doesn't transfer any data (DMA NDTR doesn't decrement over time). So after some search i found this in reference manual for MCU:

Bit 13 DDS: DMA disable selection (for multi-ADC mode) This bit is set and cleared by software. 0: No new DMA request is issued after the last transfer (as configured in the DMA controller). DMA bits are not cleared by hardware, however they must have been cleared and set to the wanted mode by software before new DMA requests can be generated.

But reset of only this register did nothing. At the end only this way worked for me:

          ADC->CCR &= ~(ADC_CCR_MULTI);
 
          ADC->CCR &= ~(ADC_CCR_DMA);
          ADC->CCR |= ADC_DMAACCESSMODE_2;
 
          ADC->CCR |= ADC_DUALMODE_INTERL;
 
          HAL_ADC_Start(&hadc2);
          HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)AData, sizeof(AData) / sizeof(uint32_t));

I am trying to understand what this lines do, because they don't change anything, because the same configuration was written to CCR in MX_ADC1_Init function. Is this the only way to make this setup work?

Thank you and sorry for my poor language skills.

Here is my configuration, ADC1:

0693W000001tAJbQAM.png0693W000001tAJRQA2.png

ADC2:

0693W000001tAJgQAM.png

1 ACCEPTED SOLUTION

Accepted Solutions
Satty
Associate II

Ok, I think, i found needed information. According to RM0385, when using multi-mode ADC with DMA (not circle buffer -> you need to trigger ADC by software):

If the conversion sequence is interrupted (for instance when DMA end of transfer occurs), the multi-ADC sequencer must be reset by configuring it in independent mode first (bits DUAL[4:0] = 00000) before reprogramming the interleaved mode.

At the same time, according to the same RM:

Bit 13 DDS: DMA disable selection (for multi-ADC mode) This bit is set and cleared by software. 0: No new DMA request is issued after the last transfer (as configured in the DMA controller). DMA bits are not cleared by hardware, however they must have been cleared and set to the wanted mode by software before new DMA requests can be generated.

So, if you need to restart DMA after end of transfer, you need next code before restart (checked only HAL, it has no checks for this situation):

          ADC->CCR &= ~(ADC_CCR_MULTI);
          ADC->CCR |= ADC_DUALMODE_INTERL;
          ADC->CCR &= ~(ADC_CCR_DMA);
          ADC->CCR |= ADC_DMAACCESSMODE_2;

View solution in original post

1 REPLY 1
Satty
Associate II

Ok, I think, i found needed information. According to RM0385, when using multi-mode ADC with DMA (not circle buffer -> you need to trigger ADC by software):

If the conversion sequence is interrupted (for instance when DMA end of transfer occurs), the multi-ADC sequencer must be reset by configuring it in independent mode first (bits DUAL[4:0] = 00000) before reprogramming the interleaved mode.

At the same time, according to the same RM:

Bit 13 DDS: DMA disable selection (for multi-ADC mode) This bit is set and cleared by software. 0: No new DMA request is issued after the last transfer (as configured in the DMA controller). DMA bits are not cleared by hardware, however they must have been cleared and set to the wanted mode by software before new DMA requests can be generated.

So, if you need to restart DMA after end of transfer, you need next code before restart (checked only HAL, it has no checks for this situation):

          ADC->CCR &= ~(ADC_CCR_MULTI);
          ADC->CCR |= ADC_DUALMODE_INTERL;
          ADC->CCR &= ~(ADC_CCR_DMA);
          ADC->CCR |= ADC_DMAACCESSMODE_2;