AnsweredAssumed Answered

STM32: ADC with DMA

Question asked by tauch.tim.002 on Jul 6, 2015
Latest reply on Jul 6, 2015 by tauch.tim.002
Hi everyone,

I'm trying to get a timer triggered (TIM2_UPDATE) AD-conversion of 8 regular channels working. The System is running with 168 MHz. AD-conversion is done in scan mode with a frequency of 2 kHz. For data handling a circular-mode DMA is used.

After starting Timer 2 the CPU is running into MemManage Error Interrupt. Thats why I think the problem lies in the DMA configuration. Can everyone help?
I have to use the HAL library with the following code:

#define NUMCHANNELS     8
ADC_HandleTypeDef       ADC_Handle;
ADC_ChannelConfTypeDef  ADC_ChannelConf[NUM_CHANNELS];
DMA_HandleTypeDef       DMA_Handle;
TIM_MasterConfigTypeDef sMasterConfig;
uint16_t                DmaBuffer[NUM_CHANNELS];

__DMA2_CLK_ENABLE();
 
DMA_Handle.Instance                 = DMA2_Stream0;
HAL_DMA_DeInit( &DMA_Handle );
 
DMA_Handle.Init.Channel             = DMA_CHANNEL_0;
DMA_Handle.Init.Direction           = DMA_PERIPH_TO_MEMORY;
DMA_Handle.Init.PeriphInc           = DMA_PINC_DISABLE;
DMA_Handle.Init.MemInc              = DMA_MINC_ENABLE;
DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DMA_Handle.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
DMA_Handle.Init.Mode                = DMA_CIRCULAR;
DMA_Handle.Init.Priority            = DMA2_PRIO_ADC12;
DMA_Handle.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
DMA_Handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
DMA_Handle.Init.MemBurst            = DMA_MBURST_SINGLE;
DMA_Handle.Init.PeriphBurst         = DMA_PBURST_SINGLE;
DMA_Handle.XferCpltCallback         = TransferError;
DMA_Handle.XferErrorCallback        = TransferError;
DMA_Handle.XferHalfCpltCallback     = TransferError;
DMA_Handle.XferM1CpltCallback       = TransferError;
HAL_DMA_Init( &DMA_Handle );
 
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 11, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
 
// Enable TIM2 clock
__TIM2_CLK_ENABLE();
 
// TIM2 configuration
// TIM2CLK = 2*PCLK1 = 84 MHz, Prescaler = 84, TIM2 counter clock = 1 MHz
TimHandle.Instance = TIM2;
TimHandle.Init.Prescaler = (PM_Rcc_t::PCLK1 * 2 / 100000) - 1;
TimHandle.Init.Period = 10000;
TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
if(HAL_TIM_Base_Init( &TimHandle ) != HAL_OK)
  TRACE(1, (TRACE_ERR, "Timer 2 Init failed"));
 
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if(HAL_TIMEx_MasterConfigSynchronization(&TimHandle, &sMasterConfig) != HAL_OK)
  TRACE(1, (TRACE_ERR, "Timer 2 Init failed"));
 
// Enable ADC clock
__ADC1_CLK_ENABLE();
 
// ADC configuration
// AHB2CLK = 84 MHz, PRESCALER = 4, ADCCLK = 21 MHz
// 12 bit conversion needs 12 cycles + 3
// ADC is triggered externally by TIM2 UPDATE
ADC_Handle.Instance                    = ADC1;
ADC_Handle.Init.ClockPrescaler         = ADC_CLOCKPRESCALER_PCLK_DIV4;
ADC_Handle.Init.Resolution             = ADC_RESOLUTION12b;
ADC_Handle.Init.ScanConvMode           = ENABLE;
ADC_Handle.Init.ContinuousConvMode     = DISABLE;
ADC_Handle.Init.DiscontinuousConvMode  = DISABLE;
ADC_Handle.Init.ExternalTrigConvEdge   = ADC_EXTERNALTRIGCONVEDGE_RISING;
ADC_Handle.Init.ExternalTrigConv       = ADC_EXTERNALTRIGCONV_T2_TRGO;
ADC_Handle.Init.DataAlign              = ADC_DATAALIGN_RIGHT;
ADC_Handle.Init.NbrOfConversion        = NUM_CHANNELS;
ADC_Handle.Init.NbrOfDiscConversion    = 0;
ADC_Handle.Init.EOCSelection           = EOC_SINGLE_CONV; // EOC_SEQ_CONV;
ADC_Handle.Init.DMAContinuousRequests  = ENABLE;
 
if(HAL_ADC_Init( &ADC_Handle ) != HAL_OK)
  TRACE(1, (TRACE_ERR, "ADC Init failed"));
__HAL_LINKDMA(&ADC_Handle, DMA_Handle, DMA_Handle);
 
ADC_ChannelConf[LOAD_12].Channel             = ADC_CHANNEL_0;
ADC_ChannelConf[LOAD_12].Rank                = 1;
ADC_ChannelConf[LOAD_12].SamplingTime        = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_12].Offset              = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_12]);
 
ADC_ChannelConf[LOAD_3].Channel              = ADC_CHANNEL_2;
ADC_ChannelConf[LOAD_3].Rank                 = 2;
ADC_ChannelConf[LOAD_3].SamplingTime         = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_3].Offset               = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_3]);
 
ADC_ChannelConf[LOAD_4].Channel              = ADC_CHANNEL_3;
ADC_ChannelConf[LOAD_4].Rank                 = 3;
ADC_ChannelConf[LOAD_4].SamplingTime         = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_4].Offset               = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_4]);
 
ADC_ChannelConf[LOAD_5].Channel              = ADC_CHANNEL_8;
ADC_ChannelConf[LOAD_5].Rank                 = 4;
ADC_ChannelConf[LOAD_5].SamplingTime         = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_5].Offset               = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_5]);
 
ADC_ChannelConf[LOAD_6].Channel              = ADC_CHANNEL_9;
ADC_ChannelConf[LOAD_6].Rank                 = 5;
ADC_ChannelConf[LOAD_6].SamplingTime         = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_6].Offset               = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_6]);
 
ADC_ChannelConf[GRID_VOLTAGE].Channel        = ADC_CHANNEL_10;
ADC_ChannelConf[GRID_VOLTAGE].Rank           = 6;
ADC_ChannelConf[GRID_VOLTAGE].SamplingTime   = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[GRID_VOLTAGE].Offset         = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[GRID_VOLTAGE]);
 
ADC_ChannelConf[TEMP_HEATSINK].Channel       = ADC_CHANNEL_11;
ADC_ChannelConf[TEMP_HEATSINK].Rank          = 7;
ADC_ChannelConf[TEMP_HEATSINK].SamplingTime  = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[TEMP_HEATSINK].Offset        = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[TEMP_HEATSINK]);
 
ADC_ChannelConf[VCC12V_A].Channel            = ADC_CHANNEL_12;
ADC_ChannelConf[VCC12V_A].Rank               = 8;
ADC_ChannelConf[VCC12V_A].SamplingTime       = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[VCC12V_A].Offset             = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[VCC12V_A]);
 
if(HAL_ADC_Start_DMA( &ADC_Handle, (uint32_t*)DmaBuffer, NUM_CHANNELS) != HAL_OK)
  TRACE(1, (TRACE_ERR, "ADC Init failed"));
 
/* Diable the Half transfer complete interrupt */
__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_HT);
 
/* Diable the transfer Error interrupt */
//__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_TE);
 
/* Diable the FIFO Error interrupt */
//__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_FE);
 
/* Diable the direct mode Error interrupt */
//__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_DME);
 
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_OVR);
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_EOC);
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_AWD);
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_JEOC);
 
if(HAL_TIM_Base_Start(&TimHandle)  != HAL_OK)
  TRACE(1, (TRACE_ERR, "Timer 2 Init failed"));

Outcomes