2016-08-05 55 views
2

nehme ich an einen Mikrocontroller mit einer Hauptschleife und 1 Millisekunde Alarm haben (wenn Sie nicht wissen, was das ist es nur eine Aufgabe, die die Hauptschleife der Ausführung unterbricht, während es etwas tut ..... und es ist ein 1 Millisekunde Interrupt, weil es jede Millisekunde passiert).Teilweise volatile Variable?

Ich habe eine Variable, die I zwischen der Hauptschleife und Millisekunden- Unterbrechungs verwenden, um zu kommunizieren:

volatile status_t Status; 

Augenblick habe ich einen Abschnitt des Codes in der Hauptschleife, die die Status Variable aktualisiert, die eine tut Tonne Transformationen darauf:

cli(); // This temporarily turns off interrupts, so we don't 
      // modify the variable unsafely 
Status.UpdateStuff(); 
Status.UpdateOtherStuff(); 
//etc. 

sei(); // Turn interrupts back on 

das Problem ist, dass jede dieser Funktion StatusStatus umschreibt nennt ...... der Compiler nicht die Werte der Stellung im lokalen Speicher zwischengespeichert werden kann.

Eine mögliche Lösung für dieses Problem ist folgendes:

cli(); 
status_t* localStatus = (status_t*)&Status; 
localStatus->UpdateStuff(); 
localStatus->UpdateOtherStuff(); 
//etc. 

Status = *localStatus; 
sei(); 

Die eigentliche Frage hier ist diese:

Ist das tun würde, was ich hoffe, es wird tun, oder gibt es einen besseren Weg, um um das Problem des konstanten Auffrischens der Variablen, anstatt es dem Optimierer zu erlauben, die Variable zwischenzuspeichern?

+0

Im zweiten Ausschnitt meinen Sie wohl & Status. Übrigens, ich glaube nicht, dass es viel bessere Alternativen gibt. –

+0

Lassen Sie den Timer Jobs in eine Warteschlange einfügen, und der Hauptthread liest die Warteschlange und verarbeitet die Jobs. Sie brauchen nur einen Mutex in den Warteschlangenoperationen. –

+0

@MatteoItalia Yup, das ist, was ich meinte ... – DarthRubik

Antwort

3

Ihre zweite Version noch an den Mikrocontroller mehrmals schreiben, da der Compiler nicht erkennen, kann es den Wert über Methodenaufrufe cachen kann (es könnte wahrscheinlich nur dies festzustellen, ob die Methoden inline sind). Also schlage ich vor, eine explizite lokale Kopie zu erstellen, nicht nur einen lokalen Zeiger.

+0

Mit diesem Ansatz können Sie möglicherweise die Codespanne, die mit deaktivierten Interrupts ausgeführt werden muss, auf den Code reduzieren, der die neue Version des Status in den freigegebenen Speicherort verschiebt. – nate

0

Ein Beispiel, um zu minimieren, wie viel Zeit der Prozessor mit deaktivierten Interrupts läuft. Dies funktioniert nur, wenn nextStatus keine anderen Nebenwirkungen hat. Wenn dies der Fall wäre, müssten diese aufgezeichnet und ausgeführt werden, sobald der Status erfolgreich festgelegt wurde.

cli(); 
do { 
    auto lastStatus = Status; 
    sei(); 

    auto nextStatus = lastStatus; 
    nextStatus.UpdateStuff(); 
    nextStatus.UpdateOtherStuff(); 
    ... 

    cli(); 
} while (lastStatus != Status); 
Status = nextStatus; 
sei();