Aus RN-Wissen.de
Version vom 9. Juli 2011, 20:21 Uhr von Besserwessi (Diskussion | Beiträge) (Empfehlungen für Code in der ISR)

Wechseln zu: Navigation, Suche
Rasenmaehroboter fuer schwierige und grosse Gaerten im Test

Programm-Code, der beim Auftreten einer freigeschalteten Interrupt-Anforderung (IRQ) ausgeführt wird. Dazu wird der normale Programmfluss unterbrochen, die Interrupt Service Routine (ISR) ausgeführt, und danach das Programm an der unterbrochenen Stelle fortgeführt.

Je nach Hardware bzw. deren Konfiguration wird die ISR direkt betreten oder indirekt über eine Interrupt-Vektor-Tabelle, welche nur die Startadressen der unterschiedlichen ISRs enthält bzw. Sprunganweisungen zum Start der jeweiligen ISR.

Empfehlungen für Code in der ISR

In der ISR kann im Prinzip ein beliebiger Code stehen. Damit es nicht zu Störungen im Hauptprogramm kommt, sollte man aber ein paar Empfehlungen beachten:

Die ISR sollte relativ schnell beendet werden. Entsprechend sollte man langsame Teile wie explizites warten oder das Warten auf externe Ereignisse vermeiden. Dazu gehört meist auch die Ausgabe auf ein LCD Display. Auch Rechnungen mit Fließkommazahlen brauchen relativ lange. Einfache Änderungen an IO-Registern sind dagegen relativ schnell, auch wenn man dafür relativ viele Zeilen schreibt.

Wenn das Hauptprogramm und die ISR auf die gleiche Variable oder ein IO Register zugreifen, muss das Hauptprogramm aufpassen, das nicht zu einem ungeeigneten Zeitpunkt die ISR dazwischen kommt. Die Zugriffe sollten "atomar" gestaltet sein, z.B. durch ein CLI() und SEI(), wenn der Zugriff nicht von sich aus schon Atomar ist, z.B. durch einen einzigen ASM Befehl. Je nach µC ist der schreibende Zugriff auf einzelne Bits nicht atomar möglich: erst wird das ganze Byte gelesen, dann das gewünschte Bit manipuliert und dann das ganze Byte zurück geschrieben.

Damit es mit der Optimierung keine Probleme gibt, müssen in C die gemeinsam genutzten Variablen, die in einer ISR verändert werden als volatile gekennzeichnet werden. Bei einer volatilen Variable lohnt es sich ggf. in der ISR eine lokale nicht volatile Kopie anzulegen.

Um Platz auf dem Stack zu sparen, sollte man Funktionsaufrufe in der ISR vermeiden, also besser den Code direkt einfügen. Einige Unterprogramme sind ggf. nicht "reentrant", dürfen also nicht 2 mal gleichzeitig aufgerufen werden - eventuell aus dem Hauptprogramm und dann noch mal aus der ISR. Dies passiert z.B. wenn globale Variablen für Zwischenwerte benutzt werden.

Der oft genannte Hinweis in der ISR nur ein Flag zu setzen, und dann die ganze Rechnung im Hauptprogramm zu machen hilft oft auch nicht weiter. Zum einen setzt die Hardware schon von sich aus meistens ein Flag in einem IO-Register, wenn ein Interrupt ausgelöst werden könnte. Nur um ein Flag zu setzen braucht man also den Interrupt meist gar nicht, ein Flag hat die Hardware schon gesetzt. Es geht dann also besser ganz ohne Interrupt. Wenn eine andere ISR zeitkritisch ist, kann man ggf. in der ISR Interrupts freigeben und so geschachtelte Interrupts erlauben. Der Code kann dann weiter in der logischen Reihenfolge bleiben und man spart sich die dauernde Abfrage des Flags im Hauptprogramm. Wenn der selbe Interrupt noch mal kommt, hat man mit dem Flag im Hauptprogramm auch ein Problem.

Aufgaben wie die Ausgabe mehrerer Bytes per UART oder an ein ähnliches langsames Gerät wie ein LCD löst man da besser, indem man die Ausgabe Puffert und in einen extra Interrupt verlagert, die dann jeweils 1 Byte ohne Wartezeiten ausgibt. Viele kurze Interrupts sind meist das kleinere Problem als eine langsame ISR. Die Koordination mit ggf. vorhanden Ausgaben des Hauptprogramms ist dabei noch eine andere Baustelle.

Siehe auch


LiFePO4 Speicher Test