I'm seeing some interesting interactions which suggests to me that there are some subtleties about using TCC interrupts that I don't understand. Here's my test code:
void setup()
{
// if you uncomment the following 2 lines, the interrupts don't start until you open the serial monitor
// Serial.begin(9600);
// while (!Serial);
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK4
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Feed GCLK4 to TCC0 and TCC1
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
//set up TCC0
REG_TCC0_PER = 24000; // Set the frequency of TCC0 to 2kHz
while (TCC0->SYNCBUSY.bit.PER); // Wait for synchronization
NVIC_SetPriority(TCC0_IRQn, 128); // Set the Nested Vector Interrupt Controller (NVIC) priority for TCC0 to 128 (middle)
NVIC_EnableIRQ(TCC0_IRQn); // Connect TCC0 to Nested Vector Interrupt Controller (NVIC)
REG_TCC0_INTFLAG |= TCC_INTFLAG_OVF; // Clear the interrupt flag
REG_TCC0_INTENSET = TC_INTENSET_OVF; // Enable TCC0 interrupts
// Divide the 48MHz signal by 1 giving 48MHz (20.83ns) TCC0 timer tick and enable the outputs
REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 64
TCC_CTRLA_ENABLE; // Enable the TCC0 output
while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
// if you uncomment the following 2 lines, the interrupts start, but the pin 9 looks like it's high impedance when it's written low
// Serial.begin(9600);
// while (!Serial);
pinMode(9, OUTPUT);
}
void TCC0_Handler() // Interrupt Service Routine (ISR) for timer TCC0
{
static bool high = false;
// Check for overflow (OVF) interrupt
if (TCC0->INTFLAG.bit.OVF && TCC0->INTENSET.bit.OVF) {
digitalWrite(9, high? LOW : HIGH);
high = !high;
REG_TCC0_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag
}
}
void loop() { }
As is, the interrupts start up at the expected frequency and I get a nice 1 kHz square wave on pin 9. If I initialize Serial before all the register initialization, interrupts don't start until I open the serial monitor. If instead I wait until after the register initialization to initialize Serial, it looks like pin 9 is going high-impedance when it is written LOW because I'm seeing that characteristic 2.2RC curve (see attached picture). In this state, if I open the serial monitor, the signal on pin 9 becomes square again! What am I misunderstanding?