mikrocontroller.net

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


Autor: Marco S (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
class A
{
  public:
    void foo( int arg );

  private:
    int i;
}

void A::foo( int arg )
{
  this.i = arg;
}

int main()
{
  A a;

  a.foo( 5 );
}
dann behandelt der Compiler das so:

aus der Memberfunktion wird eine ganz normale Funktion, die
die Adresse des Objektes mitbekommt:
void A_foo( A* obj, int arg )
{
  obj->i = arg;
}

und der Aufruf wird zu:

int main()
{
  struct A a;

  foo( &a, 5 );
}

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:
class Cnt {
   public:
      Cnt(void): count(0) { ...initialisiere Interrupt... }
      char get(void) { return count; }

      void OnInterrupt();

   private:
      char count;
}

static Cnt* GetsInterrupt;

ISR( ... )
{
  if( GetsInterrupt )
    GetsInterrupt->OnInterrupt();
}

int main()
{
  Cnt c;

  GetInterrupt = &c;    // jetzt werden die Definierten Interrupts
                        // von der ISR an das Objekt c weitergereicht

  ...
}


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.