Nano Every TCA0 does not jump into ISR (CMP / OVF)

Hi,
I spent all day long trying to fix my problem, that the ISRs seem not to be called.
I figured out, that the counter runs (print() in the mainloop), and the Interrupt flags are set at the "right" compare / overflow point. But It doesn't go into my ISRs. Does anyone has an idea what I do wrong?

The basic thing I want to do is to some kind of software pwm. One requirement is that both pins are never high at the same time. So my Idea was to set 0<CMP0 < CMP1 < CMP2 < OVF interrupt and switch my first pin on at CMP0 Interrupt and switch it out at CMP1 Interrupt. For my second pin I want to do the same with CMP2 and OVF interrupt.
If so. has a much better Idea, you're welcome :slight_smile:

#define PIN1 12 //definiert den PIN1 für die Anwendung
#define PIN2 11 //definiert den PIN2 für die Anwendung


void setup() {
  // Init Pins
  pinMode(PIN1, OUTPUT);
  digitalWrite(PIN1, LOW);
  pinMode(PIN2, OUTPUT);
  digitalWrite(PIN2, LOW);

  cli();  //disable global interrupts
  TCA0.SINGLE.CTRLA = 0;  // stop/reset Timer 
  TCA0.SINGLE.CTRLB = 0;
  TCA0.SINGLE.CTRLC = 0;
  TCA0.SINGLE.CTRLD = 0;
  TCA0.SINGLE.EVCTRL = 0;
  TCA0.SINGLE.CNT = 0;


  TCA0.SINGLE.CMP0 = (64-1);  //10% von 640 -1
  TCA0.SINGLE.CMP1 = (320-1);  // 50% von 640 -1 
  TCA0.SINGLE.CMP2 = (384-1);  // 60 % von 640-1
   TCA0.SINGLE.PER= (640-1); // Value Overflow TCA (640-1 @ 16 MHz --> 25 kHz) // overflow bei 639 bzw 0

  TCA0.SINGLE.CTRLA |= (0x01<<1); // Clk Prescaler =1
  TCA0.SINGLE.CTRLB &= ~((uint8_t)(0x7F));  //normal mode, Waveformoutputs und LUTs disabled
  TCA0.SINGLE.CTRLD = 0; //not split mode;

// enable Interrupts for CMP0..2 and OVF
  TCA0.SINGLE.INTCTRL |= (1<<TCA_SINGLE_OVF_bm)|(1<<TCA_SINGLE_CMP2EN_bm)|(1<<TCA_SINGLE_CMP1EN_bm)|(1<<TCA_SINGLE_CMP0EN_bm);

  TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm; //enable Timer TCA in single mode
  
  sei(); //enable global interrupts
 
 
  Serial.begin(9600);
  Serial.print("Config done");
  TCA0.SINGLE.INTFLAGS |= 0x113; //clear flags once (doesn't help)

}

void loop() 
{
  volatile uint16_t i;
  i++;

    Serial.print(TCA0.SINGLE.CNT); // shows if counter runs properly
    Serial.print("\n");
    Serial.print(TCA0.SINGLE.INTFLAGS); 
    Serial.print("\n");
    //TCA0.SINGLE.INTFLAGS |= 113;
  
}


ISR(TCA0_CMP0_vect)
{
    digitalWrite(PIN1, HIGH);
    Serial.print("PIN1 High\n");
    TCA0.SINGLE.INTFLAGS |= TCA_SINGLE_CMP0_bm;
}

ISR(TCA0_CMP1_vect)
{
    digitalWrite(PIN1, LOW);
     Serial.print("PIN1 Low\n");
    TCA0.SINGLE.INTFLAGS |= TCA_SINGLE_CMP1_bm;

}
ISR(TCA0_CMP2_vect)
{
    digitalWrite(PIN2, HIGH);
    Serial.print("PIN2 High\n");
    TCA0.SINGLE.INTFLAGS |= TCA_SINGLE_CMP2_bm;
}
ISR(TCA0_OVF_vect)
{
    digitalWrite(PIN2, LOW);
    Serial.print("PIN2 Low\n");
    TCA0.SINGLE.INTFLAGS |= TCA_SINGLE_OVF_bm;

}


Perhaps you meant:

  static uint16_t i = 0;
  i++;
  if (i==0) // Once every 65536 loops...
  {

the main loop is actually not so meaningful, as it stands here. Since "clean up" for posting and change something still got mixed up.
But it doesn't change my actual problem. The main loop is actually completely without function here. It should run only with the ISR and it doesn't jump into it.

I just changed it a little according to your post. the volatile makes the compiler not to optimize it away and I don't wanted to have a delay() function in the main. So it's just a little bit like doing nothing. :slight_smile:

Kind regards

What happens if you remove the Serial prints from the ISR's?

What happens if you remove the Serial prints from the ISR's?
nothing :slight_smile:
I changed the sketch a little, so I only wanted to have the OVF interrupt. I put the Trace in the mainloop and that is what comes on the serial monitor:

#define PIN1 12 //definiert den PIN1 für die Anwendung
#define PIN2 11 //definiert den PIN2 für die Anwendung

#include <ArduinoTrace.h>
volatile uint8_t debug;

void setup() {
  // Init Pins
  pinMode(PIN1, OUTPUT);
  digitalWrite(PIN1, LOW);
  pinMode(PIN2, OUTPUT);
  digitalWrite(PIN2, LOW);

  cli();  //disable global interrupts
  TCA0.SINGLE.CTRLA = 0;  // stop/reset Timer 
  TCA0.SINGLE.CTRLB = 0;
  TCA0.SINGLE.CTRLC = 0;
  TCA0.SINGLE.CTRLD = 0;
  TCA0.SINGLE.EVCTRL = 0;
  TCA0.SINGLE.CNT = 0;
  TCA0.SINGLE.INTCTRL = 0;

  //TCA0.SINGLE.CMP0 = 1000;  //10% von 640 -1
  //TCA0.SINGLE.CMP1 = 30000;  // 50% von 640 -1 
  //TCA0.SINGLE.CMP2 = 40000;  // 60 % von 640-1
   TCA0.SINGLE.PERBUF= 60000; // Value Overflow TCA (640-1 @ 16 MHz --> 25 kHz) // overflow bei 639 bzw 0
/*
  TCA0.SINGLE.CMP0 = (64-1);  //10% von 640 -1
  TCA0.SINGLE.CMP1 = (320-1);  // 50% von 640 -1 
  TCA0.SINGLE.CMP2 = (384-1);  // 60 % von 640-1
   TCA0.SINGLE.PER= (640-1); // Value Overflow TCA (640-1 @ 16 MHz --> 25 kHz) // overflow bei 639 bzw 0
*/
  TCA0.SINGLE.CTRLA |= (0x07<<1); // Clk Prescaler =1
  TCA0.SINGLE.CTRLB &= ~((uint8_t)(0x7F));  //normal mode, Waveformoutputs und LUTs disabled
  TCA0.SINGLE.CTRLD = 0; //not split mode;

// enable Interrupts for CMP0..2 and OVF
  TCA0.SINGLE.INTCTRL = (1<<TCA_SINGLE_OVF_bm);//|(1<<TCA_SINGLE_CMP2EN_bm)|(1<<TCA_SINGLE_CMP1EN_bm)|(1<<TCA_SINGLE_CMP0EN_bm);

  TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm; //enable Timer TCA in single mode
  
  sei(); //enable global interrupts
 
 
  Serial.begin(9600);
  Serial.print("Config done");
  TCA0.SINGLE.INTFLAGS = 113; //clear flags once (doesn't help)

}

ISR(TCA0_OVF_vect)
{
    digitalWrite(PIN2, LOW);
    debug++;
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
    

}
void loop() 
{
  volatile static uint16_t i=0;
  i++;
  DUMP(TCA0.SINGLE.CNT);
  DUMP(TCA0.SINGLE.INTFLAGS);
  DUMP(debug);
  TRACE();
}

The output looks like this:

sketch_oct4b.ino:65: debug = 0
sketch_oct4b.ino:66: void loop()
sketch_oct4b.ino:63: (*(TCA_t *) 0x0A00).SINGLE.CNT = 58726
sketch_oct4b.ino:64: (*(TCA_t *) 0x0A00).SINGLE.INTFLAGS = 113
sketch_oct4b.ino:65: debug = 0
sketch_oct4b.ino:66: void loop()
sketch_oct4b.ino:63: (*(TCA_t *) 0x0A00).SINGLE.CNT = 1826
sketch_oct4b.ino:64: (*(TCA_t *) 0x0A00).SINGLE.INTFLAGS = 113
sketch_oct4b.ino:65: debug = 0
sketch_oct4b.ino:66: void loop()
sketch_oct4b.ino:63: (*(TCA_t *) 0x0A00).SINGLE.CNT = 4910
sketch_oct4b.ino:64: (*(TCA_t *) 0x0A00).SINGLE.INTFLAGS = 113
sketch_oct4b.ino:65: debug = 0

I don't understand, why the flags of all interrupts are set (maybe this trace libary does not look it up correctly) and the debug var shows, that the ISR is never entered.

OK I don't know which part exactly now solved my problem, but I did a reboot on the pc (since I installed the IDE today), and I changed some of the register accesses to the syntax as in the coding example of atmel http://ww1.microchip.com/downloads/en/AppNotes/TB3217-Getting-Started-with-TCA-90003217A.pdf

(instead |= I only took = )

the code works now. Thanks for all your support.

#define PIN1 12 //definiert den PIN1 für die Anwendung
#define PIN2 11 //definiert den PIN2 für die Anwendung


void setup() {
  // Init Pins
  pinMode(PIN1, OUTPUT);
  digitalWrite(PIN1, LOW);
  pinMode(PIN2, OUTPUT);
  digitalWrite(PIN2, LOW);

  TCA0.SINGLE.CTRLA = 0;  // stop/reset Timer 
  TCA0.SINGLE.CTRLB = 0;
  TCA0.SINGLE.CTRLC = 0;
  TCA0.SINGLE.CTRLD = 0;
  TCA0.SINGLE.EVCTRL = 0;
  TCA0.SINGLE.CNT = 0;
  TCA0.SINGLE.INTCTRL = 0;


  TCA0.SINGLE.CMP0 = (64-1);  //10% von 640 -1
  TCA0.SINGLE.CMP1 = (320-1);  // 50% von 640 -1 
  TCA0.SINGLE.CMP2 = (384-1);  // 60 % von 640-1
   TCA0.SINGLE.PER= (640-1); // Value Overflow TCA (640-1 @ 16 MHz --> 25 kHz) // overflow bei 639 bzw 0

  TCA0.SINGLE.CTRLA = (0x07<<1);// Clk Prescaler =1
  TCA0.SINGLE.CTRLB = 0x00;  //normal mode, Waveformoutputs und LUTs disabled
  TCA0.SINGLE.EVCTRL &= ~(TCA_SINGLE_CNTEI_bm);
  TCA0.SINGLE.CTRLD = 0; //not split mode;

// enable Interrupts for CMP0..2 and OVF
  TCA0.SINGLE.INTCTRL =TCA_SINGLE_OVF_bm|TCA_SINGLE_CMP0EN_bm|TCA_SINGLE_CMP2EN_bm|TCA_SINGLE_CMP1EN_bm;

  TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm; //enable Timer TCA in single mode
  

 
 
  Serial.begin(9600);
  Serial.print("Config done");
  TCA0.SINGLE.INTFLAGS = 0xFF; //clear flags once (doesn't help)

}

ISR(TCA0_OVF_vect)
{
  digitalWrite(PIN2, LOW);
  TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
}

ISR(TCA0_CMP0_vect)
{

    digitalWrite(PIN1, HIGH);
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP0_bm;
}

ISR(TCA0_CMP1_vect)
{
    digitalWrite(PIN1, LOW);
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP1_bm;

}
ISR(TCA0_CMP2_vect)
{
    digitalWrite(PIN2, HIGH);
    TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP2_bm;
}

void loop() 
{

}

/*


*/



If this is one of the cases where you clear flags but writing a 1, you probably dont want to use the |= form since it may clear other interrupts as well. Just use =.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.