Wird flüchtig benötigt, wenn auf Variablen von> 1 ISRs zugegriffen wird, diese jedoch nicht außerhalb von ISRs gemeinsam genutzt werden?


9

Es ist klar dokumentiert, dass beim Teilen globaler Daten mit einem ISR und dem Hauptprogramm die Daten deklariert werden volatilemüssen, um die Speichersichtbarkeit zu gewährleisten (und dies reicht nur für 1-Byte-Daten aus; alles, was größer ist, erfordert spezielle Vorkehrungen, um auch die Atomizität zu gewährleisten). . Hier haben wir gute Regeln:

  • Variablen, die nur außerhalb eines ISR verwendet werden, sollten nicht flüchtig sein.
  • Variablen, die nur innerhalb eines ISR verwendet werden, sollten nicht flüchtig sein.
  • Variablen, die sowohl innerhalb als auch außerhalb eines ISR verwendet werden, sollten volatil sein.

Aber wird volatilebenötigt , wenn die Variable aus zugegriffen wird> 1 ISRs, aber nicht außerhalb ISRs geteilt? Zum Beispiel habe ich eine Funktion, die den internen Status mithilfe einer staticVariablen beibehält :

void func() {
    static volatile long counter; // volatile or not?
    // Do stuff with counter etc.
}

Diese Funktion wird auf zwei Arten aufgerufen: vom Pin-Interrupt und von der TimerOne-Bibliothek :

  1. attachInterrupt(0, func, CHANGE);
  2. Timer1.attachInterrupt(func);

Es gibt keine Atomprobleme, da bei der Eingabe eines ISR Interrupts automatisch deaktiviert werden. Dies volatileist jedoch eher eine Compiler-Frage: Was wird zwischengespeichert und was nicht.

Natürlich sicherer als leid ...

Antworten:


9

volatile Informiert nur den Codegenerator des Compilers darüber, dass die Variable möglicherweise durch etwas anderes als den generierten Code geändert wird, sodass nicht davon ausgegangen werden kann, dass eine Kopie davon korrekt bleibt.

ISR-Code muss unter der Annahme geschrieben / generiert werden, dass er bei der Eingabe keinen Kontext hat, und den Kontext der CPU um den eigenen Betrieb (ISR) herum beibehalten. Wie bei der Unteilbarkeit nichtatomarer Operationen hängt die Volatilität in diesem Fall * davon ab , ob Interrupts verschachtelt werden dürfen oder nicht. Wenn die Nichtverschachtelung garantiert ist, kann sich die gemeinsam genutzte Variable während ihrer eigenen Ausführung nur durch diesen ISR ändern. Wenn Ihr ISR eines Tages in einer Umgebung verwendet wird, in der Interrupts verschachtelt werden dürfen, gilt diese Einschränkung nicht mehr.

* in diesem Fall :
Ich gehe hier von einer von der Software gepflegten Variablen aus. Wenn es sich um eine Variable handelt, die durch ein Hardware-Ereignis aktualisiert werden kann, beispielsweise ein Timer-Register, sind alle Wetten deaktiviert: Die Variable ist auf jeden Fall volatil.


Solange ich das Standardverhalten von Arduino "Interrupts nicht verschachteln" nicht ändere, muss die Variable dies nicht sein volatile, da sie nur durch den generierten Code geändert wird. Der Compiler kann "annehmen", dass der ISR linear ausgeführt wird, und dies tut er, solange Interrupts nicht verschachtelt sind. Das macht Sinn. Vielen Dank!
Joonas Pulakka
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.