Go Down

Topic: (Serial and digitalWrite interactions with TCC interrupts) what !Serial tests (Read 2059 times) previous topic - next topic

jameslo

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:

Code: [Select]

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?

Juraj


jameslo

Ah, OK, that makes perfect sense.  I thought I was waiting for serial to be initialized, not waiting for it to make a connection.

Go Up