> IMHO the only way is to define the interrupt method in the class with
> interrupt attributes and then alias the mangled name to the AVR vector
> so the compiler can find it during global name reconciliation. This 
> would be very neat and simple if we could develop a simple name 
> mangling macro.
> Ron

With advise from Daniel Lohmann, Andrew Haley and Brian Dessent over on the
gcc-help list ("Mangle functions"), using the gcc "asm" keyword considerably
simplifies defining interrupt methods in C++ classes. The asm keyword as it
applies to function names is described in 5.37 of the gcc manual, and
essentially specifies the equivalent assembler name for the target function
name. Its use allows the user to use his or her own names for class
interrupt methods. For avr-gcc it requires two new macros:

#define STRINGIFY(name) #name
#define CLASS_IRQ(name, vector) \
    static void name(void) asm(STRINGIFY(vector)) \
    __attribute__ ((signal, __INTR_ATTRS))

Using the simple example of previous posts on this topic, the interrupt
class header for a '128 TIMER0 overflow looks like:

class CTimer0Interrupt
    CLASS_IRQ(OverflowInterrupt, TIMER0_OVF_vect);

The macro declares the interrupt handler as static because providing a
non-static signal function with a this pointer seems rather hit and miss for
gcc. Mandating a static declaration ensures the programmer is not tempted to
manipulate any local data. Of course there should never be any local data.

The cpp implementation file looks like:

// Timer0Interrupt.cpp
#include "Timer0.h"
#include "Timer0Interrupt.h"

extern CTimer0 Timer0;

    TCCR0 = 0x04;
    TIMSK |= (1<<TOIE0);        // enable overflow interrupts

    TIMSK &= ~(1<<TOIE0);       // disable Timer0 timeout interrupt

void CTimer0Interrupt::OverflowInterrupt(void)
    TCNT0 = TIMER0_TIMEOUT;     // restart the timeout
    Timer0.SetOverflowFlag();   // tell our friend of the event

Note that the interrupt handler is declared just like any other method.

All processing associated with the interrupt is performed in the class
associated with, and responsible for, controlling the peripheral. In this
case the CTimer0 class of which the CTimer0Interrupt class is both class
data and a friend:

class CTimer0
    friend class CTimer0Interrupt;
    int GetTimer0Flags(void);
    void SetOverflowFlag(void);
    volatile int        mTimer0Flags;
    CTimer0Interrupt    mTimer0Interrupt;

Where speed is of the essence, the interrupt class can directly modify the
owning peripheral class data. A simple example is:

void CTimer0Interrupt::OverflowInterrupt(void)
    TCNT0 = TIMER0_TIMEOUT;     // restart the timeout
    Timer0.mTimer0Flags |= TIMER0_OVERFLOW;

To me this seems a good solution for handling interrupts in avr-gcc C++
projects by integrating the handlers into the peripheral class and keeping
with the spirit of C++.


E-mail message checked by Spyware Doctor (
Database version: 5.09100

AVR-libc-dev mailing list

Reply via email to