[SOLVED]DUE ADC PDC and ring buffer: [EDIT ]buffer[0] do not write

[EDIT] Go to post#2 to see what the problem now...

Hi.

I'm making a library to use DUE analog sequencer and ADC interrupt for precise sampling.

It use a ring buffer of 256 sample * number of channel active sequencer channels on a 2 dimension array.

value[256][numChannels]

Main 256 buffer are control with counter; countOutterFront and countOutterRear;

front increment after each ENDRX interrupt and data transfer to buffer.

on void loop, I read the data using for each conversion array with value[countOutterRear], that return the array of conversion.
If Rear==front, while loop exit and try the next loop if there's is new data (Rear!=front).

I had a print statement to monitor, set enough fast, rear and front, rear, after catching up after boot, follow front.

Now the strange behavior, it take a whole iteration of 256 sample before see a change in the printed data.

Timing, ADC and interrupt seem to work properly...

here the git repo for all the code:

the the main function I think are involve...

void ADC_Sampler::bufferConfig() {
 ADC->ADC_IER =  ADC_IDR_ENDRX;   // interrupt enable register, enables only ENDRX
 // following are the DMA controller registers for this peripheral
 // "receive buffer address" 
 ADC->ADC_RPR = (uint32_t)bufferArray->value[bufferArray->countOutterFront];   // DMA receive pointer register  points to beginning of global_ADCount
 // "receive count" 
 ADC->ADC_RCR = numChannels;  //  receive counter set
 // "next-buffer address"
 ADC->ADC_RNPR = (uint32_t)bufferArray->value[bufferArray->countOutterFront]; // next receive pointer register DMA global_ADCounts_Arrayfer  points to second set of data 
 // and "next count"
 ADC->ADC_RNCR = numChannels;   //  and next counter is set
 // "transmit control register"
 ADC->ADC_PTCR = ADC_PTCR_RXTEN;  // transfer control register for the DMA is set to enable receiver channel requests
 
}




uint16_t* ADC_Sampler::data() {
 uint16_t* arr = bufferArray->data();
 return arr;
}

bool ADC_Sampler::available() {
 if (bufferArray->countOutterRear != bufferArray->countOutterFront) return true;
 return false;
}

void ADC_Sampler::ADC_Handler() {     // for the ATOD: re-initialize DMA pointers and count 
 
 //   read the interrupt status register 
 if (ADC->ADC_ISR & ADC_ISR_ENDRX){ /// check the bit "endrx"  in the status register /// ADC_IDR_ENDRX correction
 /// set up the "next pointer register" 
 ADC->ADC_RNPR =(uint32_t)bufferArray->value[bufferArray->countOutterFront];  // "receive next pointer" register set to global_ADCounts_Array 
 // set up the "next count"
 ADC->ADC_RNCR = numChannels;  // "receive next" counter
 bufferArray->countOutterFront++;
 }
}



#ifdef __cplusplus
extern "C"
{
#endif

void ADC_Handler (void)
{
 ADC_Sampler::ADC_Handler();
}

#ifdef __cplusplus
}
#endif



///ADCuffer
AdcBuffer::AdcBuffer(uint8_t innerSize) : countInnerFront(0), countInnerRear(0), countOutterFront(0), countOutterRear(0) {
 value = new uint16_t*[BUFFER_SIZE];
 for ( int i = 0; i < BUFFER_SIZE; i++) {
 value[i] = new uint16_t[innerSize] {0};
 }
}

uint16_t* AdcBuffer::data() volatile {
 uint16_t *arr = value[countOutterRear];
 countOutterRear++;
 return arr;
} 


bool AdcBuffer::available() {
if (countOutterRear != countOutterFront) return true;
 return false;
}



//main sketch


void loop() {
  
  String output;
  if(ADC_Sampler::available()) Serial.println("A7,A6,A5,A4,A3,A2,A0,A1,A9,A10,A11");
  while ( ADC_Sampler::available() ) {
    uint16_t* x = ADC_Sampler::data();
    for (int i = 0; i < ADC_sequencer_size; i++) {
      output += String(x[i]);
      output += ",";
    }
    
    output += " rear  ";
    output += String(ADC_Sampler::bufferArray->countOutterRear);
    output += "  front ";
    uint8_t fr = ADC_Sampler::bufferArray->countOutterFront;
    output += String(fr); 
    Serial.println(output);   
    output = String();//RESET
  }
  delay(1);
}

Regards.

Nitrof

Almost found answer.

2 thing:

1: the ADC->ADC_RNPR is the next pointer, so have to add +1 in bufferConfig and handler:

ADC->ADC_RNPR =(uint32_t)bufferArray->value[bufferArray->countOutterFront +1];  // "receive next pointer" register set to global_ADCounts_Array

2:still the current was not yet set event if front point to it, so get data add -1:

uint16_t* AdcBuffer::data() volatile {
 uint16_t *arr = value[countOutterRear-1];
 countOutterRear++;
 return arr;
}

Still one thing that do not work, even more strange: all the reading a at the right place and reactive, except for [2][] into the buffer that always say 0!

2121,2126,2096,2134,4095,4095,2137,2119,4095,3694,3568, rear  254  front 254
A7,A6,A5,A4,A3,A2,A0,A1,A9,A10,A11
2121,2125,2097,2133,4095,4095,2143,2120,4095,3695,3569, rear  255  front 255
A7,A6,A5,A4,A3,A2,A0,A1,A9,A10,A11
2120,2126,2097,2133,4095,4095,2136,2118,4095,3695,3569, rear  0  front 0
A7,A6,A5,A4,A3,A2,A0,A1,A9,A10,A11
447,49200,4018,62507,28881,71,3072,63552,9653,5195,6946, rear  1  front 1
A7,A6,A5,A4,A3,A2,A0,A1,A9,A10,A11
0,0,0,0,0,0,0,0,0,0,0, rear  2  front 2
A7,A6,A5,A4,A3,A2,A0,A1,A9,A10,A11
2121,2126,2098,2133,4095,4095,2134,2120,4095,3696,3570, rear  3  front 3
A7,A6,A5,A4,A3,A2,A0,A1,A9,A10,A11
2118,2126,2097,2134,4095,4095,2137,2119,4095,3695,3569, rear  4  front 4

that, I'm really confuse ! :o

Will update the git if anyone way to test it...

[UPDATE] one fill, I printed all the uffer array, it is the first buffer valu[0][] that stay 0... no more answer yet...

[UPDATE2] I test also the handler to see if *value[0] is pass to the handler on ADC->ADC_RNPR, and it is. I don't understand why it do not write on it...

Ok seem to got it...

I set in ADC setup pointer to current -1 et next 0. It now write on buffer[0]. If I can understand fo the first past, I do not on the subsequent one... If Someone can explain...

Anyway, final result:

void ADC_Sampler::bufferConfig() {
//...
 // "receive buffer address" 
	ADC->ADC_RPR = (uint32_t)bufferArray->value[bufferArray->countOutterFront-1];   // DMA receive pointer register  points to beginning of global_ADCount
	// "receive count" 
//...
	// "next-buffer address"
	ADC->ADC_RNPR = (uint32_t)bufferArray->value[bufferArray->countOutterFront]; // next receive pointer register DMA global_ADCounts_Arrayfer  points to second set of data 
	// and "next count"
//...
}

Regards.

Nitrof