Keeping the timer alive while in standby on the M0 Pro

Hi,

I'm hoping someone can point me in the right direction.

I'm trying to put an Arduino M0 Pro to sleep but keep either millis() or another timer running to in the background.

I've been through the datasheet and I can see that I need to keep the GCLK and the Timer running in standby.

Can someone please help me confirm if I'm setting this up correctly since I think my timer code might be freezing the micro:

#include "LowPower.h"

#define LED_PIN 13

#define CPU_HZ 48000000
#define TIMER_PRESCALER_DIV 1024

void startTimer(int frequencyHz);
void setTimerFrequency(int frequencyHz);
void TC3_Handler();

bool isLEDOn = false;
volatile long NewMillis = 0; 

const int pin = 0;
unsigned char count = 10;

void setup() {
  SerialUSB.begin(115200);
    // Wait for serial USB port to open
  while(!SerialUSB);
  SerialUSB.println("***** ATSAMD21 Standby Mode Example *****");
  
  // ***** IMPORTANT *****
  // Delay is required to allow the USB interface to be active during
  // sketch upload process
  SerialUSB.println("Entering standby mode in:");
  for (count; count > 0; count--)
  {
    SerialUSB.print(count); 
    SerialUSB.println(" s");
    delay(1000);
  }
  // *********************
    
  // External interrupt on pin (example: press of an active low button)
  // A pullup resistor is used to hold the signal high when no button press
  attachInterrupt(pin, blink, LOW);
  startTimer(1000);
}

void loop() {
  SerialUSB.println("Entering standby mode.");
  SerialUSB.println("Apply low signal to wake the processor.");
  SerialUSB.println("Zzzz...");
  // Detach USB interface
  USBDevice.detach();
  // Enter standby mode
  LowPower.standby();  
  // Attach USB interface
  USBDevice.attach();
  // Wait for serial USB port to open
  while(!SerialUSB);
  // Serial USB is blazing fast, you might miss the messages
  delay(1000);  
  SerialUSB.println("M:  " + String(millis()));
  SerialUSB.println("nM: " + String(NewMillis));
  SerialUSB.println("Awake!");
  SerialUSB.println("Send any character to enter standby mode again");
  // Wait for user response
  while(!SerialUSB.available()){

  }
  while(SerialUSB.available() > 0)
  {
    SerialUSB.read();
  }



  }

  
void blink(void)
{
       digitalWrite(LED_PIN,HIGH);
       delay(100);
       digitalWrite(LED_PIN,LOW);
}

void setTimerFrequency(int frequencyHz) {
  int compareValue = (CPU_HZ / (TIMER_PRESCALER_DIV * frequencyHz)) - 1;
  TcCount16* TC = (TcCount16*) TC3;
  // Make sure the count is in a proportional position to where it was
  // to prevent any jitter or disconnect when changing the compare value.
  TC->COUNT.reg = map(TC->COUNT.reg, 0, TC->CC[0].reg, 0, compareValue);
  TC->CC[0].reg = compareValue;
  SerialUSB.println(TC->COUNT.reg);
  SerialUSB.println(TC->CC[0].reg);
  while (TC->STATUS.bit.SYNCBUSY == 1);
}

void startTimer(int frequencyHz) {

  SYSCTRL->XOSC32K.bit.RUNSTDBY = 1;
  
  REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3) ;
  while ( GCLK->STATUS.bit.SYNCBUSY == 1 ); // wait for sync

  const uint8_t GCLK_SRC = 0;

  TcCount16* TC = (TcCount16*) TC3;

  TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync

  GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN |
            GCLK_GENCTRL_SRC_XOSC32K |
            GCLK_GENCTRL_ID(GCLK_SRC) |
            GCLK_GENCTRL_RUNSTDBY;
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);


  // Use the 16-bit timer
  TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync

  // Use match mode so that the timer counter resets when the count matches the compare register
  TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync

  // Set prescaler to 1024
  TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1024;
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync

  // Set timer to run in standby
  TC->CTRLA.reg |= TC_CTRLA_RUNSTDBY;
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync

  setTimerFrequency(frequencyHz);

  // Enable the compare interrupt
  TC->INTENSET.reg = 0;
  TC->INTENSET.bit.MC0 = 1;

  NVIC_EnableIRQ(TC3_IRQn);

  TC->CTRLA.reg |= TC_CTRLA_ENABLE;
  while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
}

void TC3_Handler() {
  TcCount16* TC = (TcCount16*) TC3;
  // If this interrupt is due to the compare register matching the timer count
  // we toggle the LED.
  if (TC->INTFLAG.bit.MC0 == 1) {
    TC->INTFLAG.bit.MC0 = 1;
    NewMillis++;
    // Write callback here!!!
    //digitalWrite(LED_PIN, isLEDOn);
    //isLEDOn = !isLEDOn;
  }
}

I'm pulling the setup code from

https://forum.arduino.cc/index.php?topic=412465.0

What am I doing wrong that the timer locks up the micro when I called the function to start the timer in setup?

Thanks in advance