-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Volatile und Interrupt

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.08.2004
    Ort
    Zwolle
    Alter
    61
    Beiträge
    531

    Volatile und Interrupt

    Anzeige

    Hallo,

    Wenn in eine normalen Funktion ein oder mehere variabelen benutzt werden und irgendwo lauft ein Interrupt Funktion der seinen eigenen lokalen variabelen benutzt, welche variabelen in die normalen Function soll ich dann wie 'volatile' deklarieren damit die ubereinstimmende processor-register nicht vom Interrupt Funktion zerstohrt werden?

    Wer hilft mich raus?

    Gruss

    Henk

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    50
    Beiträge
    1.195
    Alle die variablen werden volatile deklariert, die von beiden Routinen gelesen oder geschrieben werden:

    volatile uint8_t readOrWriteMe;

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Die lokalen Variablen brauchen nicht als volatile (flüchtig) deklariert zu werden. volatile ist eine Variable/Zugriff dann, wenn sich der Inhalt "unbemerkt" ändern kann, also wenn Hardware oder Interrupt-Service-Routine den Wert ändern. Volatile stellt sicher, daß bei jedem Zugriff die Variable wirklich gelesen/geschrieben wird.

    Werden Daten zwischen einer normalen Funktion und einer ISR ausgetauscht, dann muss die globale Variable/Struktur volatile sein.

    Zusätzlich muss der Zugriff atomar sein, wenn das Übergabe-Objekt länger als ein Byte ist.
    Disclaimer: none. Sue me.

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.08.2004
    Ort
    Zwolle
    Alter
    61
    Beiträge
    531
    Die lokalen Variablen brauchen nicht als volatile (flüchtig) deklariert zu werden.
    Ich stelle mich folgendes vor:

    Eine function (A) mit 40 normalen (nicht-volatile) Variabelen.
    Der compiler der ist intelligent, der nutzt fur jeden variabele ein anderes Register. Da aber die 30 Atmega Register nicht 40 unterschiedene Variabelen speichern konnen werden schon einige automatisch 'unterwasser' als volatile angewendet.

    Gibt es nur 20 Variabelen dan genugen die 30 Atmega Register um jeden Variabele in ein specifischen Register zu speichern und nur die Register an zu sprechen.

    Aber, wenn jetzt ein Interrupt passiert der auch viele register benutzt da kann ich mich folgendes vorstellen: die Register die im Interrupt verwendet werden werden am anfang vom Interrupt zuerst auf die Stack ge'pushed'.

    Wenn meine 40-variabele function (A) ein eindere Funtion (B) anruft werden alle Register die von (B) benutzt werden zuerst in (A) in ihren originalen Speichplatze zuruck geschrieben.

    Stimmt dieses so ein Bisschen?

    Gruss

    Henk

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Die Phase, in der ein Compiler sich entscheidet, welche Variable er in welches Register ablegt, nennt man Reload-Phase.

    Sounds trivial, aber es ist eine der komplexesten und trickreichsten Phasen beim Compilieren -- zumindest dann, wenn man es gut machen will und die Compilerbauer nicht faul sind.

    Aus einer lokalen Variable kann folgendes werden:
    • Sie wird in einem Register gehalten
    • Sie wird auf dem Stack angelegt. Bei vielen lokalen Variablen braucht die Funktion einen Frame, in dem lokale Variablen angelegt werden.
    • Sie wird wegoptimiert und belegt überhaupt nix, ist nicht mal von einem Debugger aus lesbar
    • statische lokale Variablen werden im RAM angelegt und "überleben" Funktionsaufrufe

    Was Funktionen angeht, so wird in der ABI (Application Binary Interface) beschrieben, welche Register durch eine Funktion einfach benutzt werden und verunstaltet werden dürfen (call-used bzw. call-clobbered Regs) und welche einen Funktionsaufruf unbeschadet überstehen (call-saved Regs).

    Bei einer Funktion mit 40 Variablen wird keine als volatile angelegt, es sei denn, du sagst es.

    Eine Interrupt Service Routine (ISR) sichert die verwendeten Register sowie das SREG, vor Verlassen der ISR werden die Regs wieder hergestellt. Teilweise werden aber mehr Register gesichert als wirklich nötig wäre, etwa wenn in einer ISR eine Funktion aufgerufen wird. Der Compiler sieht die Funktion nur als Black Box, er weiß i.d.R. nicht was darin abgeht; muss also auch alle call-used Regs sichern, weil die Funktion sie zerstören darf bzw. kann.

    Ähnlich geht eine Funktion vor, wenn sie ein call-save Reg verwenden will. damit es nach ihrem Aufruf den ursprünglichen Wert hat, wird es im Prologue gesichert und im Epilogue wieder hergestellt.
    Disclaimer: none. Sue me.

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.08.2004
    Ort
    Zwolle
    Alter
    61
    Beiträge
    531
    Dass ist ja alles machtig interressant und compliziert!

    Kannst Du mir erklaren wass hier geschiedt?

    • //Mein Program

      typedef volatile struct{
      //mehere volatile Variabelen
      volatile signed int A;
      }MyStructA;

      typedef volatile struct{
      //mehere volatile Variabelen
      volatile signed int B;
      }MyStructB;

      volatile MyStructA MyA;
      volatile MyStructB MyB;

      int main(void){

      unsigned char CopyA,CopyB;

      CopyA=MyA.A;
      CopyB=MyB.B;

      }


    Das Program compiliert zu:

    lds r24,MyA+20
    lds r25,(MyA+20)+1
    lds r24,MyA+20
    lds r25,(MyA+20)+1

    Die '20' is okay denn in mein Program sind A und B die 20e byte im structure.

    Da kann mann doch einfach erkennen dass beide Variabelen MyA.A und MyB.B anschliessend (ohne code dazwischen) dieselben register r24/r25 benutzen???

    Dieses Program (hier stark vereinfachtet) lauft nur wenn ich CopyA und CopyB wie 'volatile' declariere. Die generierten code sieht dann auch ganz anders aus!

    Wo gibt's hier ein Denk Fehler???

    Gruss

    Henk

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.08.2004
    Ort
    Zwolle
    Alter
    61
    Beiträge
    531
    Noch dazu,
    wenn CopyA,CopyB wie 'volatile' definiert sind dann compiliert es sich zu:
    • lds r24,MyA+20
      lds r25,(MyA+20)+1

      std Y+1,r24

      lds r24,MyA+20
      lds r25,(MyA+20)+1

      std Y+2,r24


    Gruss

    Henk

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.08.2004
    Ort
    Zwolle
    Alter
    61
    Beiträge
    531
    Und nochmal

    Hatte MyA geschrieben statt MyB...

    es sollte sein:



    • lds r24,MyA+20
      lds r25,(MyA+20)+1
      lds r24,MyB+20
      lds r25,(MyB+20)+1



    und


    • lds r24,MyA+20
      lds r25,(MyA+20)+1

      std Y+1,r24

      lds r24,MyB+20
      lds r25,(MyB+20)+1

      std Y+2,r24



    Gruss

    Henk

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Ich vermite mal, für main wurde ein Frame angelegt. Y ist der Frame-Pointer, über den auf lokale Variablen zugegriffen wird.

    Die Variablen im Frame liegen dann bei Y+1, Y+2, Y+3, ... etc, zumindest dann, wenn es Bytes sind. Sind die Typen größer, werden auch die Offsets größer, wobei das untere Byte des Frames immer bei Y+1 liegt. Steht dort ein int, dann fängt die nächste Variable bei Y+3 an, etc.

    Der Code ist doch in Ordnung. Zu Bedenken ist nur, daß CopyX ein char ist (1 Byte), MyX.X jedoch ein int (2 Bytes). Daher wird von MyX.X nur das untere Byte gespeichert.

    Wenn die Variablen nicht volatile sind und du Zuweisungen machst, die zugewiesenen Werte aber nicht benutzt werden, dann wird das wegoptimiert und es gibt keinen Code, der der den C-Anweisungen entspricht.

    Es genügt übrigens volatile einmal hinzuschreiben, bei dir steht's dreimal! (Bei der Strukturkomponente, im der Typdefinition und bei der Variablendefinition...)
    Disclaimer: none. Sue me.

  10. #10
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.08.2004
    Ort
    Zwolle
    Alter
    61
    Beiträge
    531
    Kan jemand noch etwas hierzu sagen?

    Folgendes Program (etwas symbolisch).
    Da laufen einige interrupts im Hintergrund.

    • unsigned char MeinArray[20];
      unsigned char MeinIndex;
      unsigned char MeinVar;

      main(){

      MeinIndex=12;
      MeinVar=MeinArray[MeinIndex];

      switch(MeinVar){
      }

      }

    Die Wert in MeinVar ist nicht immer stabiel.
    Die Variabelen werden NICHT vom Interrupt Functionen benutzt.

    Wenn alle Variabelen wie
    - global und volatile
    oder
    - local und static
    deklariert werden laufts ohne Probleme.

    Wie ist dass zu erklaren?

    (Oder gibts hier ein bug im gcc.exe compiler???, da werde ich immer mehr archwohnisch)

    gruss

    Henk

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •