How to get interrupt by the end of DMA ADC?

was-ja

Well-known member
Hello,

I have small test that is based on adc_dma, where I am collecting data from 2 ADC simultaneously. I would like to call a call_back function after each successfull measuring of each my 16K samples. I tried to use

Code:
    attachInterruptVector(IRQ_ADC_ETC0, ic1);
    attachInterruptVector(IRQ_ADC_ETC1, ic2);
    NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
    NVIC_ENABLE_IRQ(IRQ_ADC_ETC1);
but it seems that I should do it other way. The complete source is below:

Code:
#pragma GCC push_options
#pragma GCC optimize ("Ofast")


#include <ADC.h>
#include <AnalogBufferDMA.cpp>


const int readPin_adc_0 = A16; // Fast:A0-11,16-17; No:A12-15; 
const int readPin_adc_1 = A17; // Slow:A0-9,12-17; No:10-11


ADC *adc = new ADC();

const uint32_t buffer_size = 16*1024;

#define MT DMAMEM
// #define MT

MT static volatile uint16_t __attribute__((aligned(32))) dma_adc_buff1[buffer_size];
MT static volatile uint16_t __attribute__((aligned(32))) dma_adc_buff2[buffer_size];
AnalogBufferDMA abdma1(dma_adc_buff1, buffer_size, dma_adc_buff2, buffer_size);

MT static volatile uint16_t __attribute__((aligned(32))) dma_adc2_buff1[buffer_size];
MT static volatile uint16_t __attribute__((aligned(32))) dma_adc2_buff2[buffer_size];
AnalogBufferDMA abdma2(dma_adc2_buff1, buffer_size, dma_adc2_buff2, buffer_size);

// const uint32_t initial_average_value = 2048;

unsigned int CurTime[2];
int LoopCount[2];


void ProcessAnalogData(AnalogBufferDMA *pabdma, int8_t adc_num);

int IC_Count[2]={0,0};

void ic1()
{ IC_Count[0]++; }


void ic2()
{ IC_Count[1]++; }


void setup()
{ //    while (!Serial && millis() < 5000) ;

    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(readPin_adc_0, INPUT);
    pinMode(readPin_adc_1, INPUT);

    Serial.begin(9600);
    Serial.println("Setup ADC_0");

    adc->adc0->setAveraging(0); // set number of averages
    adc->adc1->setAveraging(0); // set number of averages

#define ACS ADC_CONVERSION_SPEED::VERY_HIGH_SPEED
#define ASS ADC_SAMPLING_SPEED::VERY_HIGH_SPEED
#define ARE 12

    adc->adc0->setResolution(ARE);
    adc->adc1->setResolution(ARE);

    adc->adc0->setConversionSpeed(ACS);
    adc->adc0->setSamplingSpeed(ASS);
    adc->adc1->setConversionSpeed(ACS);
    adc->adc1->setSamplingSpeed(ASS);

    abdma1.init(adc, ADC_0);
    abdma2.init(adc, ADC_1);

    adc->adc1->startContinuous(readPin_adc_1);
    adc->adc0->startContinuous(readPin_adc_0);

    Serial.println("End Setup");
    CurTime[0]=CurTime[1]=ARM_DWT_CYCCNT;
    LoopCount[0]=LoopCount[1]=0;
    attachInterruptVector(IRQ_ADC_ETC0, ic1);
    attachInterruptVector(IRQ_ADC_ETC1, ic2);
    NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
    NVIC_ENABLE_IRQ(IRQ_ADC_ETC1);
}


void loop()
{ if (abdma1.interrupted()) ProcessAnalogData(&abdma1, 0);
  if (abdma2.interrupted()) ProcessAnalogData(&abdma2, 1);
}


void ProcessAnalogData(AnalogBufferDMA *pabdma, int8_t adc_num)
{ uint16_t min_val = 0xffff;
  uint16_t max_val = 0;

  volatile uint16_t *pbuffer = pabdma->bufferLastISRFilled();
  int Len = pabdma->bufferCountLastISRFilled();
  if ((uint32_t)pbuffer >= 0x20200000u)  arm_dcache_delete((void*)pbuffer, sizeof(dma_adc_buff1));

  if(((LoopCount[adc_num]++)&31)==0)
  { float sum = 0.0;
    float sum2 = 0.0;
    float InvLen = 1./(float)Len;

    for(int i=0; i<Len; i++)
    { uint16_t val = *pbuffer;
      if (val < min_val) min_val = *pbuffer;
      if (val > max_val) max_val = *pbuffer;
      sum += val;
    }
    sum*=InvLen;
    for(int i=0; i<Len; i++)
    { float val = ((float)(*pbuffer)) - sum;
      sum2 += val*val;
    }

    sum2*=InvLen;
    unsigned int ct=ARM_DWT_CYCCNT;
    unsigned int ct2=CurTime[adc_num]; CurTime[adc_num]=ct;
    unsigned int tpc=(((ct-ct2)>>19)+1)>>1;
    Serial.printf(" %d - %u(%u): Ticks/Conversion=%d, Len=%d, %u <= %u(%u) <= %u : %d %d\n", adc_num, pabdma->interruptCount(), pabdma->interruptDeltaTime(), tpc, Len,
      min_val, (unsigned int)(sum+0.5), (unsigned int)(sum2+0.5), max_val, IC_Count[0], IC_Count[1]);
  }
  pabdma->clearInterrupt();
}

#pragma GCC pop_options

Please, help me to modify this code such a way that instead to call to abdma1.interrupted() several times, my call back function ic1() is call backed.

Thank you!
 
Back
Top