Hi,
my best season greeting to all forum participants and PJRC Team!
Let me please, ask you regarding to the maximum possible ADC speed on Teensy 4.1 by using DMA and two channels.
To get it myself I slightly modified the example adc_dma from Teensydoino (1.56) and attachint it here:
where ACS - conversion speed, ASS - sampling speed and ARE - the resolution.
With this settings I found very impressive 3.4MS/s on the first channel and 2MS/s on the second running the test at 600MHz clock and surprisingly slowdown at overclocked 812MHz as: 2.3MHz and 1.3MHz
I have questions, please, help me to understand:
Thank you!
my best season greeting to all forum participants and PJRC Team!
Let me please, ask you regarding to the maximum possible ADC speed on Teensy 4.1 by using DMA and two channels.
To get it myself I slightly modified the example adc_dma from Teensydoino (1.56) and attachint it here:
Code:
#include <ADC.h>
#include <AnalogBufferDMA.cpp>
// ADACK_2_4, ADACK_4_0, ADACK_5_2 and ADACK_6_2, ACS ADC_CONVERSION_SPEED::VERY_HIGH_SPEED
#define ACS ADC_CONVERSION_SPEED::VERY_HIGH_SPEED
#define ASS ADC_SAMPLING_SPEED::HIGH_VERY_HIGH_SPEED
// resolution
#define ARE 8
const int readPin_adc_0 = 24;
const int readPin_adc_1 = 26;
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);
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
adc->adc0->setResolution(ARE);
adc->adc1->setResolution(ARE);
adc->adc0->setConversionSpeed(ACS);
adc->adc0->setSamplingSpeed(ASS);
adc->adc1->setConversionSpeed(ACS);
adc->adc0->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;
}
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\n", adc_num, pabdma->interruptCount(), pabdma->interruptDeltaTime(), tpc, Len,
min_val, (unsigned int)(sum+0.5), (unsigned int)(sum2+0.5), max_val);
}
pabdma->clearInterrupt();
}
where ACS - conversion speed, ASS - sampling speed and ARE - the resolution.
With this settings I found very impressive 3.4MS/s on the first channel and 2MS/s on the second running the test at 600MHz clock and surprisingly slowdown at overclocked 812MHz as: 2.3MHz and 1.3MHz
I have questions, please, help me to understand:
- why the first channel works faster that the second one, or I need to adjust something at the second channel to run it at the same speed as the first channel?
- I would like to work at slightly overclocked CPU (i.e. 812MHz) and it seems that all other my computational parts works ok on this speed (I have small radiator on CPU). Please, suggest how to force Teensy 4.1 to work at 812MHz at least with the same speed of ADC as on the 600MHz?
Thank you!