Warum sind hier Interrupts zu deaktivieren?

7
%Vor%

Ich verstehe, dass mehrere Aufgaben möglicherweise versuchen, die SPI-Ressource zu verwenden. spiTxRxByteCount ist eine globale Variable, die verfolgt, ob der SPI gerade von einer anderen Task verwendet wird. Wenn ein Task den SPI benötigt, kann er den Status von spiTxRxByteCount prüfen, um zu sehen, ob der SPI verwendet wird. Wenn eine Task mit dem SPI ausgeführt wird, ruft sie diese Funktion auf und löscht das Bit, um anzuzeigen, dass der SPI nun frei ist. Aber warum zuerst die Interrupts deaktivieren und danach wieder aktivieren? Nur Paranoia?

    
user1843409 28.11.2012, 20:52
quelle

2 Antworten

14

Das & amp; = führt eine Lese-Modifizier-Schreib-Operation aus - es ist nicht atomar. Sie wollen nicht, dass ein Interrupt Dinge in der Mitte ändert, was dazu führt, dass das Schreiben mit einem falschen Wert überschrieben wird.

    
JasonD 28.11.2012, 21:04
quelle
8

Sie müssen Interrupts deaktivieren, um atomaren Zugriff zu gewährleisten. Sie möchten nicht, dass ein anderer Prozess auf diese Variable zugreift und sie möglicherweise ändert, während Sie sie lesen.

Aus Einführung in Embedded Computing :

  

Die Notwendigkeit für den atomaren Zugriff

     

Stellen Sie sich dieses Szenario vor: Vordergrundprogramm, das auf einem 8-Bit-μC läuft,   muss eine 16-Bit-Variable untersuchen, nennen Sie es X. So lädt es das Hoch   Byte und lädt dann das Low-Byte (oder umgekehrt, die Reihenfolge   spielt keine Rolle) und untersucht dann den 16-Bit-Wert. Nun stell dir ein   Interrupt mit einem zugeordneten ISR, der diese 16-Bit-Variable modifiziert.   Stellen Sie sich vor, dass der Wert der Variablen 0x1234 bei ist   eine bestimmte Zeit in der Programmausführung. Hier ist die sehr schlechte Sache   das kann passieren:

     
  • Vordergrund lädt hohes Byte (0x12)
  •   
  • ISR tritt auf, ändert X zu 0xABCD
  •   
  • Vordergrund lädt Low-Byte (0xCD)
  •   
  • Vordergrundprogramm sieht einen 16-Bit-Wert von 0x12CD.
  •   

Das Problem ist, dass ein vermeintlich unteilbares Datenstück, unser   Variable X, wurde tatsächlich in den Prozess des Zugriffs geändert,   weil die CPU-Anweisungen für den Zugriff auf die Variable teilbar waren.   Und so wurde unsere Ladung der Variablen X beschädigt. Sie können sehen, dass   Die Reihenfolge der gelesenen Variablen spielt keine Rolle. Wenn die Bestellung war   Umgekehrt in unserem Beispiel wäre die Variable falsch gelesen worden   als 0xAB34 anstelle von 0x12CD. In beiden Fällen ist der gelesene Wert keines   der alte gültige Wert (0x1234) noch der neue gültige Wert (0xABCD).

     

Das Schreiben von ISR-referenzierten Daten ist nicht besser. Diesmal nehmen wir an, dass   Im Vordergrund des Programms steht für die ISR die   vorheriger Wert 0x1234 und muss dann einen neuen Wert 0xABCD schreiben. Im   In diesem Fall ist die VBT wie folgt:

     
  • Vordergrund speichert neues High-Byte (0xAB)
  •   
  • ISR tritt auf, liest X als 0xAB34
  •   
  • Vordergrund speichert neues Low-Byte (0xCD)
  •   

Noch einmal sieht der Code (diesmal die ISR) weder das vorherige noch   gültiger Wert von 0x1234, noch der neue gültige Wert von 0xABCD, sondern   der ungültige Wert von 0xAB34.

Während spiTxRxByteCount &= ~0x0100; in C wie eine einzelne Anweisung aussehen kann, sind es tatsächlich mehrere Anweisungen an die CPU. In GCC zusammengestellt, sieht das Assembly-Listing so aus:

%Vor%

Wenn zwischen diesen Anweisungen ein Interrupt auftritt und die Daten ändert, kann Ihr erster ISR möglicherweise den falschen Wert lesen. Daher müssen Sie Interrupts deaktivieren, bevor Sie daran arbeiten, und außerdem die Variable volatile deklarieren.

    
embedded.kyle 28.11.2012 21:23
quelle

Tags und Links