Hi trampas,
The easiest way to get this working, is to set-up the event channels for asynchronous operation and the interrupt inputs to work on level rather than edge detection. This allows the input signals to pass through the event channels to the TCC2 counter unhindered and for the timer to clock off the event edges instead.
Setting up the event channels for asynchronous operation also means that you don't have clock them with a generic clock.
Here's an example that sets up TCC2 to count input events on D12, with D10 determining timer count direction. The TCC2 counter value is output to the console:
// Setup TCC2 to count input events on D12, with D10 determining timer count direction
void setup()
{
SerialUSB.begin(115200); // Send data back on the Zero's native port
while(!SerialUSB); // Wait for the SerialUSB port to be ready
PM->APBCMASK.reg |= PM_APBCMASK_EVSYS; // Switch on the event system peripheral
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable the generic clock...
GCLK_CLKCTRL_GEN_GCLK0 | // ....on GCLK0
GCLK_CLKCTRL_ID_TCC2_TC3; // Feed the GCLK0 to TCC2 and TC3
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Enable the port multiplexer on digital pin D10 count and D12 input
PORT->Group[g_APinDescription[10].ulPort].PINCFG[g_APinDescription[10].ulPin].reg |= PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
PORT->Group[g_APinDescription[12].ulPort].PINCFG[g_APinDescription[12].ulPin].reg |= PORT_PINCFG_PULLEN | PORT_PINCFG_PMUXEN;
// Set-up the pin as an EIC (interrupt) peripheral on D10 and D12
PORT->Group[g_APinDescription[12].ulPort].PMUX[g_APinDescription[12].ulPin >> 1].reg = PORT_PMUX_PMUXO_A | PORT_PMUX_PMUXE_A ;
//attachInterrupt(10, NULL, HIGH); // Attach interrupts to digital pin 10 (external interrupt 2)
EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO2; // Enable event output on external interrupt 2
EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE2_HIGH; // Set event on detecting a HIGH level
//attachInterrupt(12, NULL, HIGH); // Attach interrupts to digital pin 12 (external interrupt 3)
EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO3; // Enable event output on external interrupt 3
EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE3_HIGH; // Set event on detecting a HIGH level
EIC->CTRL.reg |= EIC_CTRL_ENABLE; // Enable EIC peripheral
while (EIC->STATUS.bit.SYNCBUSY); // Wait for synchronization
EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) | // Attach the event user (receiver) to channel 0 (n + 1)
EVSYS_USER_USER(EVSYS_ID_USER_TCC2_EV_0); // Set the event user (receiver) as timer TCC2, event 0
EVSYS->USER.reg = EVSYS_USER_CHANNEL(2) | // Attach the event user (receiver) to channel 1 (n + 1)
EVSYS_USER_USER(EVSYS_ID_USER_TCC2_EV_1); // Set the event user (receiver) as timer TCC2, event 1
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_3) | // Set event generator (sender) as external interrupt 3
EVSYS_CHANNEL_CHANNEL(0); // Attach the generator (sender) to channel 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_2) | // Set event generator (sender) as external interrupt 2
EVSYS_CHANNEL_CHANNEL(1); // Attach the generator (sender) to channel 1
TCC2->EVCTRL.reg |= TCC_EVCTRL_TCEI1 | // Enable the TCC event 1 input
TCC_EVCTRL_TCEI0 | // Enable the TCC event 0 input
//TCC_EVCTRL_TCINV1 | // Invert the event 1 input
//TCC_EVCTRL_TCINV0 | // Invert the event 0 input
TCC_EVCTRL_EVACT1_DIR | // Set event 1 to change the counter direction
TCC_EVCTRL_EVACT0_COUNTEV; // Set event 0 to count the incoming events
TCC2->WAVE.reg = TCC_WAVE_WAVEGEN_NFRQ; // Set the TCC2 timer counter to normal frequency mode
while (TCC2->SYNCBUSY.bit.WAVE); // Wait for synchronization
TCC2->CTRLA.bit.ENABLE = 1; // Enable TCC2
while (TCC2->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void loop()
{
TCC2->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC; // Trigger a read synchronization on the COUNT register
while (TCC2->SYNCBUSY.bit.CTRLB); // Wait for the CTRLB register write synchronization
while (TCC2->SYNCBUSY.bit.COUNT); // Wait for the COUNT register read sychronization
SerialUSB.println(TCC2->COUNT.reg); // Output the TCC2 COUNT register
}