avr-chat
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [avr-chat] C++ Interrupts


From: Ron Kreymborg
Subject: RE: [avr-chat] C++ Interrupts
Date: Mon, 4 Feb 2008 03:10:01 +1100

This topic moved to avr-libc-dev and then to gcc-help, but I forgot to post
the conclusion to avr-chat and close off the thread here.

Using the gcc "asm" keyword 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 is mentioned in the asm cookbook section of the
avr-libc user manual. It specifies the equivalent assembler name for the
target function name and its use allows the user to define his or her own
names for class interrupt methods. For avr-gcc it requires the macro:

#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
{
public:
    CTimer0Interrupt();
    ~CTimer0Interrupt();
private:
    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 class local data. The cpp implementation file looks like:

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

extern CTimer0 Timer0;

//---------------------------------------------------------------
CTimer0Interrupt::CTimer0Interrupt()
{
    TCNT0 = TIMER0_TIMEOUT;
    TCCR0 = 0x04;
    TIMSK |= (1<<TOIE0);        // enable overflow interrupts
}

//---------------------------------------------------------------
CTimer0Interrupt::~CTimer0Interrupt()
{
    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;
public:
    CTimer0();
    ~CTimer0();
    int GetTimer0Flags(void);
private:
    void SetOverflowFlag(void);
private:
    volatile int        mTimer0Flags;
    CTimer0Interrupt    mTimer0Interrupt;
};

Where speed is of the essence, the interrupt class can directly modify the
owning peripheral class data. A very 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++.

Ron





E-mail message checked by Spyware Doctor (5.5.0.178)
Database version: 5.09110
http://www.pctools.com/spyware-doctor/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]