How to detect which timer interrupt called callback when using ASF

avrinterruptstimerxmega

I have a general function, which gets passed among others a timer. It initializes the timer using common callback function:

void setup(config_t* config) {
    ...
    tc_enable(config.timer);
    tc_set_overflow_interrupt_callback(config.timer, common_callback);
    ...
}

That function might be called a few times with different configurations, timers included. In the interrupt callback I'd like to somehow identify which timer caused the callback.

void common_callback() {
    // Which timer called?
}

I did not find an asf tc_ function that would give me some kind of id.

  • I tried looking at TCXX.INTFLAGS, but the overflow flags seems to get reset by the asf code.
  • A hacky approach I could come up with is comparing the count register

Is there a simple way to do this using Atmel Software framework. I assume asf has an internal interrupt handler that does thing like reset the interrupt flags before calling the user defined callback. Another approach would be write similar tc_set_overflow_interrupt_callback-function that would keep some of that information.

Best Answer

The Atmel Studio Framework doesn't clear any of the flags and the underlying code is quite straightforward in that area. The callback routines get setup as follows:

void tc_set_overflow_interrupt_callback(volatile void *tc,
        tc_callback_t callback)
{
#ifdef TCC0
    if ((uintptr_t) tc == (uintptr_t) & TCC0) {
        tc_tcc0_ovf_callback = callback;
    } else
#endif
#ifdef TCC1
    if ((uintptr_t) tc == (uintptr_t) & TCC1) {
        tc_tcc1_ovf_callback = callback;
    } else
#endif
... etc for other timers

And the actual interrupt code is:

ISR(TCC0_OVF_vect)
{
    if (tc_tcc0_ovf_callback) {
        tc_tcc0_ovf_callback();
    }
}
... etc for other timers

The XMEGA is a little different to some processors in that some of the flags get cleared before the interrupt code is called rather than on return. For example the following is the description of the OVFIF flag:

This flag is set either on a TOP (overflow) or BOTTOM (underflow) condition, depending on the WGMODE setting. OVFIF is automatically cleared when the corresponding interrupt vector is executed. The flag can also be cleared by writing a one to its bit location.

One implication of using ASF is that the #ifdef directives above cause all interrupt vectors applicable to a device to be included once you include the timer/counter driver in the project.

But back to your original question as you've found those flags get cleared before the interrupt routine is called. After re-checking the documentation and taking a look at the various timer / interrupt flags before and after an interrupt in a debugger I can't see any way to achieve exactly what you're after. You might have to stick with a seperate callback for each timer that calls the main handler with a parameter. At least the code overhead shouldn't be too great because all the vectors are already included.