Forum: Compiler & IDEs Interrupt unter avr-g++


von Marco S (Gast)


Lesenswert?

Hallo erst mal.

Ist es möglich, den ISR-Code als Memberfunktion einer Klasse anzulegen?

Ziel soll sein, eine Klasse zu haben, die sich exklusiv um bestimmte 
Hardware kümmert. Z.B. eine Zähler, gesteuert von externen Interrupts. 
Dabei möchte ich in der ISR auf Klassenvariablen zugreifen können.

Der Art nach:

class Cnt {
   public:
      Cnt(void): count(0) { ...initialisiere Interrupt... }
      char get(void) { return count; }
   private:
      char count;
      ISR_INT0_VECT;
}

Cnt::ISR_INT0_VECT {
   count++;
}

int main(void) {
   Cnt c;
   tu_etwas();
   PORTB = c.get();
   return 0;
}

, so, daß ISR_INT0_VECT in der Vektortabelle eingetragen wird.

Probiert habe ich das ganze bisher mit avr-g++ (GCC) 4.1.2 20061027 
(prerelease) wie folgt:

1. ISR_INT0_VECT entsprechend <avr/interrupt.h> mit extern "C" void 
INT0_vect...  -> c++ meckert, will das nicht in der Klasse haben.
2. ISR_INT0_VECT ohne extern "C" -> name mangling und der Vektor wird 
nicht verbogen.
3. ISR_INT0_VECT mit __attribute__((naked)) und die ISR in assembler, 
mit
asm (".global __vector_1\n__vector_1:\n"); beginnend funktioniert, ist 
aber kein c/c++.
4. ISR_INT0_VECT als friend von Klasse Cnt hat auch nicht gefruchtet.

Geht das überhaupt; wenn ja, wie?

mfg
Marco

von Karl H. (kbuchegg)


Lesenswert?

> Ist es möglich, den ISR-Code als Memberfunktion einer Klasse anzulegen?

Nein.

Das kann in C++ nicht gehen, da eine ISR nur über die
Funktionsadresse aufgerufen wird. Um eine Memberfunktion
aufzurufen benötigt man zusätzlich noch das Objekt für
welches die Funktion aufzurufen ist.

Einer der Schwachpunkte von C++ im Vergleich zu neueren
Sprachen wie zb C#

Stell es dir so vor:
Wenn du eine Memberfunktion aufrufst
1
class A
2
{
3
  public:
4
    void foo( int arg );
5
6
  private:
7
    int i;
8
}
9
10
void A::foo( int arg )
11
{
12
  this.i = arg;
13
}
14
15
int main()
16
{
17
  A a;
18
19
  a.foo( 5 );
20
}
dann behandelt der Compiler das so:

aus der Memberfunktion wird eine ganz normale Funktion, die
die Adresse des Objektes mitbekommt:
1
void A_foo( A* obj, int arg )
2
{
3
  obj->i = arg;
4
}
5
6
und der Aufruf wird zu:
7
8
int main()
9
{
10
  struct A a;
11
12
  foo( &a, 5 );
13
}

Der Funktion wird also ein Pointer auf das Objekt mitgegeben.
Innerhalb der Funktion kannst du mit dem Schlüsselwort 'this'
auf diesen versteckten Pointer zugreifen. Nur muss der Aufrufer
aber auch das Objekt entsprechend angeben.

Was kannst du tun. Du kannst den Umweg über eine ganz normale
C++ Funktion nehmen und von der das Objekt einsetzen lassen:
1
class Cnt {
2
   public:
3
      Cnt(void): count(0) { ...initialisiere Interrupt... }
4
      char get(void) { return count; }
5
6
      void OnInterrupt();
7
8
   private:
9
      char count;
10
}
11
12
static Cnt* GetsInterrupt;
13
14
ISR( ... )
15
{
16
  if( GetsInterrupt )
17
    GetsInterrupt->OnInterrupt();
18
}
19
20
int main()
21
{
22
  Cnt c;
23
24
  GetInterrupt = &c;    // jetzt werden die Definierten Interrupts
25
                        // von der ISR an das Objekt c weitergereicht
26
27
  ...
28
}


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.