1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ I'm not familiar with Atmel, but couldn't you give each timer their own callback which would just call into the common callback with an ID? like void timer1_cb() { common_callback( TIMER_1 ); } \$\endgroup\$ – Ryan Johnson May 13 '14 at 13:55
  • \$\begingroup\$ @RyanJohnson I thought about that. My function is like a library, which the user may pass any timer to. That would mean that I would need as many callbacks as the device has timers. That's doable, but I'm wondering if there's a better way \$\endgroup\$ – varesa May 13 '14 at 14:12
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Separate callbacks is the way I went with. Thanks for the clarification on clearing the interrupts. I also read through that source code and did not find anything that touches the flags. I think somewhere in ASF documentation they said they clear the flags... \$\endgroup\$ – varesa Jun 13 '14 at 10:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.