Im trying to get the TCC4 on the atxmega16e5 to work. My problem is that the compare channel interrupts are only triggering once. The Interrupt flags are even beeing set but the ISR never get executed. I enabled the overflow interrupt, which is working just fine all the time. I've tested it both in the simulator and on my actual chip with the same result. I am using the Atmel Software Framework. I really get the feeling that im missing something fundemental and i just cant figure it out.
Here is the code:
#define TIMER_TC TCC4
#define TIMER_INT_LVL TC45_INT_LVL_LO
int main (void) {
sysclk_init();
eeprom_enable_mapping();
board_init();
pmic_init();
timer_init();
timer_set_top(100);
cpu_irq_enable();
timer_start();
while(1) {}
}
void timer_cca(void) { //Breakpoint here - reached just once
}
void timer_ccb(void) { //Breakpoint here - reached just once
}
void timer_ccc(void) { //Breakpoint here - reached just once
}
void timer_ccd(void) { //Breakpoint here - reached just once
}
void timer_overflow(void) { //Breakpoint here - reached multiple times
}
void timer_init() {
tc45_enable(&TIMER_TC);
tc45_set_wgm(&TIMER_TC, TC45_WG_NORMAL);
tc45_enable_cc_channels(&TIMER_TC, TC45_CCACOMP | TC45_CCBCOMP | TC45_CCCCOMP | TC45_CCDCOMP);
tc45_set_cca_interrupt_callback(&TIMER_TC, &timer_cca);
tc45_set_cca_interrupt_level(&TIMER_TC, TIMER_INT_LVL);
tc45_set_ccb_interrupt_callback(&TIMER_TC, &timer_ccb);
tc45_set_ccb_interrupt_level(&TIMER_TC, TIMER_INT_LVL);
tc45_set_ccc_interrupt_callback(&TIMER_TC, &timer_ccc);
tc45_set_ccc_interrupt_level(&TIMER_TC, TIMER_INT_LVL);
tc45_set_ccd_interrupt_callback(&TIMER_TC, &timer_ccd);
tc45_set_ccd_interrupt_level(&TIMER_TC, TIMER_INT_LVL);
tc45_write_cc(&TIMER_TC, TC45_CCA, 1);
tc45_write_cc(&TIMER_TC, TC45_CCB, 1);
tc45_write_cc(&TIMER_TC, TC45_CCC, 1);
tc45_write_cc(&TIMER_TC, TC45_CCD, 1);
tc45_set_overflow_interrupt_level(&TIMER_TC, TC45_INT_LVL_LO);
tc45_set_overflow_interrupt_callback(&TIMER_TC, &timer_overflow);
}
void timer_start() {
tc45_write_clock_source(&TIMER_TC, TC45_CLKSEL_DIV64_gc);
}
void timer_set_top(uint16_t top) {
tc45_write_period(&TIMER_TC, top);
}
Here's the link to the ASF quickstart documentation for handling channel compare interrupts using TC45: http://asf.atmel.com/docs/3.11.0/xmegae/html/xmega_tc45_quickstart.html#xmega_tc45_qs_cc
Looks like you're close. The only real difference I see is they declare the ISRs as static void and passed them directly into the set_callback function, rather than passing a pointer:
tc45_set_cca_interrupt_callback(&TIMER_TC, timer_cca);
instead of:
tc45_set_cca_interrupt_callback(&TIMER_TC, &timer_cca);
I would also add parentheses around the cc channel enable for peace of mind:
tc45_enable_cc_channels(&TIMER_TC, (TC45_CCACOMP | TC45_CCBCOMP | TC45_CCCCOMP | TC45_CCDCOMP));
Try increasing the compare values. The debugger may not be fast enough to catch a compare value of 1 after it resets the counter and services the overflow interrupt.
If you're still having trouble try manually clearing the CCxIF in the ISRs. Maybe it's not doing it automatically like it's supposed to.