Update ( I thought of sharing it with you as I go along):
There was some silly mistakes in the code above. Now I am getting something that make sense with the following code:
volatile uint32_t CaptureCountA, CaptureCountB;
volatile boolean CaptureFlag
const int max_i = 64;
int i, Buff1[max_i];
void setup() {
Serial.begin(115200); // initilize serial port to 250000 baud
PMC->PMC_PCER0 |= PMC_PCER0_PID28; // Timer Counter 0 channel 1 IS TC1
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKDIS ; // disable internal clocking while setup regs
TC0->TC_CHANNEL[1].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 // capture mode, MCK/2, clk on rising edge
| TC_CMR_ABETRG // TIOA is used as the external trigger
| TC_CMR_LDRA_RISING // load RA on rising edge of trigger input
| TC_CMR_LDRB_FALLING; // load RB on falling edge of trigger input
TC0->TC_CHANNEL[1].TC_IER |= TC_IER_LDRAS | TC_IER_LDRBS; // Trigger interruption on Load RA and load RB
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN ; // Reset TC counter and enable
//NVIC_DisableIRQ(TC1_IRQn);
//NVIC_ClearPendingIRQ(TC1_IRQn);
NVIC_SetPriority(TC1_IRQn, 0); // Give TC1 interrupt the highest urgency
NVIC_EnableIRQ(TC1_IRQn); // Enable TC1 interrupts
// print the startup header
Serial.println("Timer Capture");
i = 0;
}
void loop() {
if (i < max_i){
if (CaptureFlag) {
i+=1;
CaptureFlag = 0;
Buff1[i] = CaptureCountA;
}
}
else if(i==max_i){
i+=1;
Serial.println("The measurements are:");
for (int j = 0; j <= max_i; j++) {
printf("\r %d \n", Buff1[j]);
}
}
}
void TC1_Handler() {
uint32_t status = TC0->TC_CHANNEL[1].TC_SR; // Read & Save satus register -->Clear status register
if ((status & TC_SR_LOVRS) == TC_SR_LOVRS) abort();
if ((status & TC_SR_LDRAS) == TC_SR_LDRAS) { // If ISR is fired by LDRAS then ....
CaptureCountA = TC0->TC_CHANNEL[1].TC_RA; // get data from capture register A for TC0 channel 1
CaptureFlag = 1; // set flag indicating a new capture value is present
}
else if ((status & TC_SR_LDRBS) == TC_SR_LDRBS) { // If ISR is fired by LDRBS then ....
CaptureCountB = TC0->TC_CHANNEL[1].TC_RB; // get data from caputre register B for TC0 channel 1
}
}
The above works up to 200KHz square wave. At 300KHz, I get twice the correct number most of the time, so it is missing one period.
Comments/Questions:
-
why the code is missing periods? My guess is that the interrupts are eating time. I imagine that this is linked to the point made by ard_newbie in reply 1 of:
Bad digital IO speed? - Arduino Due - Arduino Forum
-
Another thing I do not understand is that, if I comment the:
else if ((status & TC_SR_LDRBS) == TC_SR_LDRBS) {
CaptureCountB = TC0->TC_CHANNEL[1].TC_RB;
}
then the code stops. I tried to comment, in addition, | TC_CMR_LDRB_FALLING;
the same, the code stops.
Is there a way so the code only go to interrupts on the rising edge? It will halve the number of interrupts, and it will also imply less logic on the code...
Another option, again suggested by ard_newbie on the reply 1 of:
https://forum.arduino.cc/index.php?topic=602555.0
is to forget about the interrupts and do code blocking. However, mot sure how to do this in this context, not even sure if it is possible: the Atmel documentation call it "programmable event"... not sure how to interpret it in this context...
In any case, I still need to digest all the information provided by ard_newbie in his post and links... I really find my limited knowledge of C (I am a Fortran90 lover) as a barrier as sometimes it is just the code itself which confuse me...
In any case, work in progress...