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