Arduino ZERO timer interrupts

Hi,

I don't know if this is what you need, but here is an example sketch that shows how the clock frequency for the timers can be set for an M0 Pro. (Note only TC3 and TC5 are available because TC4 is used internally for the micros() routine in the M0 Pro - I am not sure about the Zero). If you want to set the top-count and generate interrupts when this is reached you might be better of with using the TCC. This is because they are designed to be used in this mode for PWM control and H-bridge motor drivers.

For my part, I have been trying to read the TCC counter values for use as a 24-bit live-time clock. This will reduce latency due to interrupt servicing compared to 16 bit timer counters. Sadly, despite a months of evenings testing things and reading the manual, I did not manage to get this to work. It seems it only works using the event system.

I wish you success!

Harry J. Whitlow

/////////////////////////////////////////////////////////////////////////
//
//
//   Real time clock on TC3
//
//
//
/////////////////////////////////////////////////////////////////////////

volatile uint32_t realTcount = 0x0 ;   // Counter for superticks (overflow interrupts)


void setup() {
Serial.begin(9600);
setTC3clock();
}


/*
This is test code that counts to 10 s then resets and waits 3s to test 
reset, start and stop functions on TC3. 
*/
void loop() {
  
  delay(250);
  
    Serial.print(realTime(), 7);
    Serial.println();
    double val = realTime();
   
    if( int(val) >= 10)
    {
  resetStartTC3();  // reset so never gets above 10 s
      stopTC3();
    delay(3000); //wait 3 sec
    startTC3();
    }
    
}





void TC3_Handler()  // Interrupt on overflow
{
  TcCount16* TC = (TcCount16*) TC3; // get timer struct
    realTcount++;                    // Increment the supertick register
    TC->INTFLAG.bit.OVF = 1;    // writing a one clears the ovf flag
//  }
}

/*
Get the real time in seconds.
*/
double realTime() 
{   
double  realTime =  (realTcount * 1.2288E-2) + (REG_TC3_COUNT16_COUNT * 1.875E-7) ;;
return realTime;
}


/*
  Setup the Generic clock register
*/


void setTC3clock()
{
  GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 ));
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization
  TcCount16* TC = (TcCount16*) TC3; // get timer struct
  TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;   // Disable TC
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16;  // Set Timer counter Mode to 16 bits
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_NFRQ; // Set TC as normal Normal Frq
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV8;   // Set perscaler
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  // Interrupts
  TC->INTENSET.reg = 0;              // disable all interrupts
  TC->INTENSET.bit.OVF = 1;          // enable overfollow interrup
  // Enable InterruptVector
  NVIC_EnableIRQ(TC3_IRQn);
  // Enable TC
  TC->CTRLA.reg |= TC_CTRLA_ENABLE;
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
}



void resetStartTC3()
{
   TcCount16* TC = (TcCount16*) TC3; // get timer struct
   realTcount = 0x00;                // Zero superclicks
    TC->CTRLBSET.reg |= TC_CTRLBCLR_CMD_RETRIGGER;   // restart
}

void stopTC3()
{
  TcCount16* TC = (TcCount16*) TC3; // get timer struct
    TC->CTRLBSET.reg |= TC_CTRLBSET_CMD_STOP;   // Stop counter
}


void startTC3()
{
  TcCount16* TC = (TcCount16*) TC3; // get timer struct
    TC->CTRLBSET.reg |= TC_CTRLBSET_CMD_RETRIGGER;   //  Start
}