AnsweredAssumed Answered

STM32F407 ADC-DMA weird behaviour

Question asked by li.gavin on Oct 24, 2014
Latest reply on Oct 24, 2014 by li.gavin
I am using T2 to trigger ADC1,ADC2 and ADC3, all the ADCs are working in indepent mode. each ADC EOC will trigger a DMA2 in a dedicate channel.
T2->ADC1->DMA2_Stream0.Channel_0
T2->ADC2->DMA2_Stream2.Channel_1
T2->ADC3->DMA2_Stream1.Channel_2
when I am doing single step and go into every single function calls, the code runs as expected. all interrupt can be generated correctly. LEDs blink correctly.
when I run in full speed mode or single step over function calls, the code seems frozen, LEDs never blink. But when I set a break point in ISRs, it will stop at the break point and everything seems normal.

I don't understand what wrong, please help me and pointing me to a direction.
Thanks.

/* Local Includes */
#include "adc.h"
#include "stm32f4xx_syscfg.h"
#include "stdio.h"
#include "string.h"
/* Local Type Definitions */
/* Local Globals */
/* Local Functions */
static void NVIC_DMA2_init(void);
static void TIM2_init(void);
static void ADC_Common_init(void);
static void ADC_init(const ADCDev *dev);
static void DMA2_init(uint32_t* buf, uint32_t buf_size);
  
static volatile int adc1_rdy = 0;
static volatile int adc2_rdy = 0;
static volatile int adc3_rdy = 0;
  
static void NVIC_DMA2_init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
    NVIC_Init(&NVIC_InitStructure);
}
void DMA2_Stream0_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0))
    {
        DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0);
        adc1_rdy |= ADC_DMA_HT_RDY;
    }
    if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
    {
        DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
        adc1_rdy |= ADC_DMA_TC_RDY;
    }
}
void DMA2_Stream1_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF0))
    {
        DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF0);
        adc2_rdy |= ADC_DMA_HT_RDY;
    }
  
    if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF0))
    {
        DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF0);
        adc2_rdy |= ADC_DMA_TC_RDY;
    }
}
void DMA2_Stream2_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA2_Stream2, DMA_IT_HTIF0))
    {
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_HTIF0);
        adc3_rdy |= ADC_DMA_HT_RDY;
    }
  
    if(DMA_GetITStatus(DMA2_Stream2, DMA_IT_TCIF0))
    {
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF0);
        adc3_rdy |= ADC_DMA_TC_RDY;
    }
}
static void TIM2_init(void)
{
    TIM_Cmd(TIM2, DISABLE);
    TIM_UpdateRequestConfig(TIM2, TIM_UpdateSource_Regular);
    /* TIM2 TRGO selection */
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T2_TRGO
  
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    /* Time base configuration */
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Period = (uint32_t)(42000000) *1 - 1;  // very long for test
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
}
  
static void ADC_Common_init(void)
{
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);
}
static void ADC_init(const ADCDev *dev)
{
    ADC_InitTypeDef ADC_InitStruct;
    ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStruct.ADC_ScanConvMode = ENABLE;
    ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; // Scan on Demand (Trigger)
    ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
    ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStruct.ADC_NbrOfConversion = dev->chn_nr;
  
    ADC_Init(dev->adc, &ADC_InitStruct);
  
    for (int i=0;i<sizeof(dev->chn_nr);i++)
        ADC_RegularChannelConfig(dev->adc, dev->chn[i], i+1, ADC_SampleTime_56Cycles);
      
    ADC_EOCOnEachRegularChannelCmd(dev->adc, ENABLE);
  
    ADC_DMARequestAfterLastTransferCmd(dev->adc, ENABLE);
    ADC_DMACmd(dev->adc, ENABLE);
}
  
static void DMA2_init(uint32_t* buf, uint32_t buf_size)
{
    NVIC_DMA2_init();
  
    DMA_InitTypeDef  DMA_InitStructure;
    DMA_DeInit(DMA2_Stream0);
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
      
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buf;
    DMA_InitStructure.DMA_BufferSize = 4;
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);
    DMA_ITConfig(DMA2_Stream0, DMA_IT_HT | DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA2_Stream0, ENABLE); //Enable the DMA2 - Stream0 - Channel0
  
    DMA_InitStructure.DMA_Channel = DMA_Channel_1;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC2->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr += DMA_InitStructure.DMA_BufferSize * 2;
    DMA_InitStructure.DMA_BufferSize = 4;
    DMA_Init(DMA2_Stream2, &DMA_InitStructure);
    DMA_ITConfig(DMA2_Stream2, DMA_IT_HT | DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA2_Stream2, ENABLE); //Enable the DMA2 - Stream2 - Channel1
  
    DMA_InitStructure.DMA_Channel = DMA_Channel_2;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC3->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr += DMA_InitStructure.DMA_BufferSize * 2;
    DMA_InitStructure.DMA_BufferSize = 4;
    DMA_Init(DMA2_Stream1, &DMA_InitStructure);
    DMA_ITConfig(DMA2_Stream1, DMA_IT_HT | DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA2_Stream1, ENABLE); //Enable the DMA2 - Stream1 - Channel2
}
/* Exposed API */
void adc_init(const ADCDev *dev1, const ADCDev *dev2, const ADCDev *dev3, uint32_t* buf, uint32_t buf_size)
{
    DMA2_init(buf, buf_size);
    ADC_Common_init();
    ADC_init(dev1);
    ADC_init(dev2);
    ADC_init(dev3);
    TIM2_init();
}
void adc_start(void)
{
    TIM_Cmd(TIM2, ENABLE);
    ADC_Cmd(ADC1, ENABLE);
    ADC_Cmd(ADC2, ENABLE);
    ADC_Cmd(ADC3, ENABLE);
}
void adc_stop(void)
{
    TIM_Cmd(TIM2, DISABLE);
}
int adc1_get_status(void)
{
    int tmp = adc1_rdy;
    adc1_rdy = 0;
    return tmp;
}
int adc2_get_status(void)
{
    int tmp = adc2_rdy;
    adc2_rdy = 0;
    return tmp;
}
int adc3_get_status(void)
{
    int tmp = adc3_rdy;
    adc3_rdy = 0;
    return tmp;
}
  
static const ADCDev adc1 = {ADC1, 4, { 1,  2,  3,  4,}};
static const ADCDev adc2 = {ADC2, 4, {10, 11, 12, 13,}};
static const ADCDev adc3 = {ADC3, 4, { 4,  5,  6,  7,}};
  
volatile uint16_t adc_buf[ADCBUFSIZE];
  
int main(void)
{
    int led1_onoff, led2_onoff, led3_onoff;
    /* Local Globals */
  
    platform_init();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    memset((uint32_t*)adc_buf, 0, ADCBUFSIZE);
    led1_onoff = led2_onoff = led3_onoff = 0;
    adc_init(&adc1, &adc2, &adc3, (uint32_t*)adc_buf, ADCBUFSIZE);
    adc_start();
    while(TRUE)
    {
        if (adc1_get_status() & ADC_DMA_TC_RDY) {
            gpio_write_pin(GPIOPortID_G, GPIOPinID_6, led1_onoff); //LED1
            led1_onoff = !led1_onoff;
        }
        if (adc2_get_status() & ADC_DMA_TC_RDY) {
            gpio_write_pin(GPIOPortID_G, GPIOPinID_8, led2_onoff); //LED1
            led2_onoff = !led2_onoff;
        }
        if (adc3_get_status() & ADC_DMA_TC_RDY) {
            gpio_write_pin(GPIOPortID_I, GPIOPinID_9, led3_onoff); //LED1
            led3_onoff = !led3_onoff;
        }
    }
}
#ifndef __ADC_H__
#define __ADC_H__
  
/* Includes */
#include "config.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_dma.h"
  
#define TOTAL_CHN  8
#define TOTAL_ADC  3
#define ADCBUFSIZE (TOTAL_CHN*TOTAL_ADC)
typedef struct {
    ADC_TypeDef * adc;
    int chn_nr; //total channels
    uint8 chn[TOTAL_CHN];
} ADCDev;
  
/* Function Prototypes */
void adc_init(const ADCDev *dev1, const ADCDev *dev2, const ADCDev *dev3, uint32_t* buf, uint32_t buf_size);
void adc_start(void);
void adc_stop(void);
  
#define ADC_DMA_HT_RDY    1
#define ADC_DMA_TC_RDY    2
 int adc_get_status(void);
 int adc1_get_status(void);
 int adc2_get_status(void);
 int adc3_get_status(void);
  
#endif //__ADC_H__

Outcomes