AnsweredAssumed Answered

STM32F4 ADC DMA Transfer Error

Question asked by ott.simon on Feb 6, 2016
Latest reply on Jul 1, 2016 by Clive One
I am using STM32F407VGT-6 chips.

I use the DMA2 Stream0 with the ADC1 to read analog values. On two of my Boards, the code is working fine and I am not having any problems. On a third Board I programmed today, the DMA does not work (The Transfer Error Interrupt Flag TEIF is set).

I then placed the function in which I do my "ADC_Setup()" (Look at the code below) at another place in the code on a working Board and it also stopped working. So depending on which functions I call before and after the ADC_Setup() the DMA works fine or does not, although I do not change anything in the ADC_Setup() at all.

I tried clearing the DMA EN bit before doing the DMA configuration and clearing the flags before starting the DMA.
This did not change anything. It seems that the only thing that influences if the DMA is running or not, is where I place the ADC_Setup() function in the code. And unfortunately on one Board I do not find a place where it works at all.

Can someone help me understand this problem?

void ADC_Setup(void)
{
  ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_initStruct;
 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    RCC_AHB1PeriphClockCmd((RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
            RCC_AHB1Periph_GPIOC), ENABLE);
 
  // DMA2 Stream0 channel0 configuration
  DMA_Cmd(DMA2_Stream0, DISABLE);
  while (DMA2_Stream0->CR & DMA_SxCR_EN);
 
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;                                    //DMA channel 0..7
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;                   //ADC1 Address
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADC_Buffer;                     //uint16_t ADC_Buffer
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                           // Data from Peripheral to memory
  DMA_InitStructure.DMA_BufferSize = NBR_OF_CHANNELS;                               //Number of Data
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                  //increment peripheral pointer
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                           //increment address pointer
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;       //size of data .. 16bit
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;               //size of data
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                   //start from beginning when end is reached
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;                               //high - only adc exists
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                            //FIFO or direct
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;                 //FIFO specific
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                       //specifies the amount of data to be transferred in a single non interruptable transaction
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;               //specifies the amount of data to be transferred in a single non interruptable transaction
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
 
  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
 
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
  NVIC_Init(&NVIC_InitStructure);
 
  DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2);
  DMA_Cmd(DMA2_Stream0, ENABLE);
 
 
  // Configure ADC1 Pins
  GPIO_initStruct.GPIO_Mode = GPIO_Mode_AN;
  GPIO_initStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_initStruct.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_Init(GPIOA, &GPIO_initStruct);
 
  GPIO_initStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
  GPIO_Init(GPIOC, &GPIO_initStruct);
 
  // ADC1 Init
  ADC_DeInit();
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;                          //single, dual, triple
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div6;                       //max 14MHz aus APB2? (Diller)
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;           //
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;     //Delay between to ADC-cycles
  ADC_CommonInit(&ADC_CommonInitStructure);
 
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;                                      //Enable: Multiplexing
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                                //Start next Conv. immediately
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;       //this case: Software trigger
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = NBR_OF_CHANNELS;                      //number of channels in regular group
  ADC_Init(ADC1, &ADC_InitStructure);
 
  // ADC1 regular channel config
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 5, ADC_SampleTime_480Cycles);
 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 6, ADC_SampleTime_480Cycles);
 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 7, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 8, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 9, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 10, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 11, ADC_SampleTime_480Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 12, ADC_SampleTime_480Cycles);
 
 // Enable DMA request after last transfer (Single-ADC mode)
  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
 
  // Enable ADC1 DMA
  ADC_DMACmd(ADC1, ENABLE);
 
  // Enable ADC1
  ADC_Cmd(ADC1, ENABLE);
 
  ADC_SoftwareStartConv(ADC1);
}

Outcomes