K (→Siehe auch) |
|||
Zeile 7: | Zeile 7: | ||
indirekt über eine Interrupt-Vektor-Tabelle, welche nur die Startadressen der | indirekt über eine Interrupt-Vektor-Tabelle, welche nur die Startadressen der | ||
unterschiedlichen ISRs enthält bzw. Sprunganweisungen zum Start der jeweiligen ISR. | 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 die ASM-Befehle nicht schon Atomar sind. Je nach µC ist der Zugriff auf einzelne Bits nicht atomar möglich. | ||
+ | |||
+ | 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. | ||
+ | |||
+ | 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 Falg 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. | ||
+ | |||
==Siehe auch== | ==Siehe auch== |
Version vom 8. Juli 2011, 22:53 Uhr
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 die ASM-Befehle nicht schon Atomar sind. Je nach µC ist der Zugriff auf einzelne Bits nicht atomar möglich.
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.
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 Falg 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.