After having a chat with the person I work with, it turned out that this solution is still too bothersome because the actual trigger of the interruption causes a burst, which because of interruptions leads to all other systems' watchdogs to die.
However I learnt enough to continue to search on my own.
I searched in the datasheet and found out that I can set the EVACT0 of TCC0 to increment the counter found in TCC->COUNT.reg on every event.
After setting things up, I still cannot find anything but the value 0 if I take the value of the counter. What am I missing?
Here is my code for the setup of the counter:
void setupGCLK() {
PM->APBCMASK.reg |= PM_APBCMASK_EVSYS; // Switch on the event system peripheral
GCLK->GENDIV.reg = GCLK_GENDIV_DIV(3) | // Divide the 48MHz system clock by 3 = 16MHz
GCLK_GENDIV_ID(4); // Set division on Generic Clock Generator (GCLK) 4
GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK 4
GCLK_GENCTRL_SRC_DFLL48M | // Set the clock source to 48MHz
GCLK_GENCTRL_ID(4); // Set clock source on GCLK 4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Route GCLK4 to TCC0 and TCC1
GCLK_CLKCTRL_GEN_GCLK4 |
GCLK_CLKCTRL_ID_TCC0_TCC1;
while (GCLK->STATUS.bit.SYNCBUSY);
}
void setupTCC0() {
// Enable the port multiplexer on digital pin D7
//PORT->Group[g_APinDescription[7].ulPort].PINCFG[g_APinDescription[7].ulPin].bit.PMUXEN = 1;
PORT->Group[PORTA].PINCFG[21].bit.PMUXEN = 1;
PORT->Group[PORTA].PINCFG[21].bit.PULLEN = 1;
PORT->Group[PORTA].PINCFG[21].bit.INEN = 1;
// Set-up the pin as an TCC0 PWM output on D7
//PORT->Group[g_APinDescription[7].ulPort].PMUX[g_APinDescription[7].ulPin >> 1].reg |= PORT_PMUX_PMUXO_F;
PORT->Group[PORTA].PMUX[21 >> 1].reg |= PORT_PMUX_PMUXO_A;
EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO5; // Enable event output on external interrupt 5
EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE5_HIGH; // Set event detecting a HIGH level
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT5; // Disable interrupts on external interrupt 5
EIC->CTRL.reg |= EIC_CTRL_ENABLE; // Enable EIC peripheral
while (EIC->STATUS.bit.SYNCBUSY); // Wait for synchronization
Serial.println("EIC Set up OK");
EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) | // Attach the event user (receiver) to channel 0 (n + 1)
EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_0); // Set the event user (receiver) as TCC0 Event 0
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT | // No event edge detection
EVSYS_CHANNEL_PATH_ASYNCHRONOUS | // Set event path as asynchronous
EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_5) | // Set event generator (sender) as external interrupt 5
EVSYS_CHANNEL_CHANNEL(0); // Attach the generator (sender) to channel 0
TCC0->EVCTRL.reg = TCC_EVCTRL_TCEI0 | // Enable the TCC event 0 input
//TC_EVCTRL_TCINV | // Invert the event input
TCC_EVCTRL_EVACT0_INC; // Set up the counting of Events
Serial.println("TCC0 EV Set up OK");
TCC0->CTRLA.reg = TCC_CTRLA_PRESCSYNC_PRESC | // Reload timer on the next prescaler clock
TCC_CTRLA_PRESCALER_DIV1 ; // Set prescaler to 1
Serial.println("TCC0 CTRLA Set up OK");
TCC0->CTRLA.bit.ENABLE = 1; // Enable TCC0
Serial.println("TCC0 CTRLA Enable OK");
while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
And the main arduino file goes like this:
int memo, memo2; // Variables for time counting in loop
void setup() {
SerialUSB.begin(115200); // Initialise the native serial port
while(!SerialUSB); // Wait for the console to open
setupGCLK();
SerialUSB.println("GCLK Set up OK");
setupTCC0();
}
void loop() {
// put your main code here, to run repeatedly:
memo=millis();
if (memo-memo2>1000){
memo2=memo;
SerialUSB.print("Counters: ");
SerialUSB.print(TCC0->COUNT.reg);
SerialUSB.print(" ");
SerialUSB.println(TCC0->CC[0].reg);
}
}
I tried the solution @MartinL gave in that old topic, but it does not work either: