Technische Informatik; Hardwarenahe Programmierung
Interrupt Beschreibung
Busy waiting¶
Busy waiting ist eine Methode den Prozessor für eine bestimmte Zeit zu blockieren, z.B. mit der Funktion wait(). Dies ist eine effektive Methode, um Zeitverzögerungen zu verursachen. Sie ist jedoch ineffizient, da sie Prozessorzeit verschwendet und den Prozessor für die Dauer der Wartezeit auf voller Leistung hält. Ticker und Timer sind eine weitere oft bessere Methode, ein Zeitintervall zu erstellen, da während des wartens anderer Code ausgeführt werden kann.
Polling¶
Beim Polling fragt man Signale regelmäßig innerhalb der Schleife ab und wertet diese Signale aus. Polling bezeichnet in der Informatik die Methode, den Status eines Geräts aus Hard- oder Software oder das Ereignis einer Wertänderung mittels zyklischem Abfragen zu ermitteln. Polling eignet sich in der Praxis nur für spezielle Anwendungsfälle, wie z.B. das Abfragen eines Tasters:
polling.cpp
#include "mbed.h" DigitalOut led1(LED1); DigitalIn button(BUTTON1); int main() { int zeit = 200; while(1) { led1 = 0; wait_ms(zeit); led1 = 1; wait_ms(zeit); if(button) { zeit = 500; } } }
Ein großer Nachteil beim Polling ist allerdings, dass auf Signale nicht sofort reagiert werden kann, sondern erst mit einer Verzögerung. So kann es im schlechtesten Fall passieren, dass man ein Signal gerade abgefragt hat und kurz nach dieser Abfrage das externe Signal am entsprechenden Port anliegt. In dieser Situation kann es relativ lange dauern, bis der Port wieder abgefragt wird, je nach dem wie lange die Verarbeitung der Befehle in der while-Schleife dauert. Bei kritischen Signalen, beispielsweise einer kritischen Fehlersituation, bei der sofort reagiert werden muss, kann das untragbar sein.
Man bedenke z.B. die vielen verschwendeten Takte die benötigt würden, um ständig zu testen, ob die Maus bewegt oder eine Taste gedrückt wurde.
In diesen Fällen soll wirklich nur dann etwas unternommen werden, wenn ein Ereignis (engl. Event) eingetreten ist. Tritt ein Ereignis auf, wird die reguläre Arbeit der CPU kurzzeitig unterbrochen; es wird ein Interrupt ausgelöst.
Interrupt¶
Bei Interrupts wird sofort reagiert. Wenn ein Interrupt-Signal auftritt, wird der aktuelle Befehl des Hauptprogramms beendet, die nötigen Register auf den Stack gerettet und dann anschließend sofort die ISR (Interrupt Service Routine) aufgerufen. Gleichzeitig wird GIE (gloabl interrupt enable - der Interrupt-Hauptschalter) auf 0 gesetzt, um einen weiteren Interrupt während des Interrupts zu verhindern. Die ISR läuft nun ab und löscht das ausgelöste Interrupt-Flag. Die ISR beendet sich durch einen Rücksprung (RETFIE), der das Rückspeichern des alten Befehlszählers und der Registerinhalte vom Stack bewirkt und der dadurch wieder seinen Stand wie vor der Unterbrechung hat (so als wäre nichts gewesen). Setzen des GIE-Flags auf 1, wodurch wieder Interrupts erlaubt werden. Anm.: durch setzen von Prioritäten können auch ISR unterbrochen werden.
Technische Realisierung der Interrupts¶
- der Prozessor besitzt einen oder mehrere spezielle Interrupt Eingänge
- wird eine Interruptleitung aktiviert, so führt dies zum Auslösen der zugehörigen Programmunterbrechung
- "richtige" Rechner verwenden oft sog. Interruptcontroller, welche verschiedene Interruptquellen managen
Z.B. die Tastenabfrage mittels ISR; Statt DigitalIn wird mit InterruptIn
der Taster definiert. Die ISR wird wie eine Funktion ohne Parameter und Rückgabewert (void change()) definiert. Zum Datenaustausch wird eine globale Variable (toggle) verwendet.
Zur Programmierung von Interrupts in Mbed-C++ siehe InterruptIn.
Ticker und Timer¶
Als Timer oder auch Counter bezeichnet man ein Modul, welcher beim Zählen von Ereignissen, Messen von Zeitabständen und periodischen Ausführen von Programmteilen eine wichtige Hilfe darstellt. Möchte man zum Beispiel eine Uhr realisieren, dann konfiguriert man den Timer so, dass z.B. exakt 100 mal pro Sekunde ein Interrupt ausgelöst wird. In der ISR kann man dann eine Variable hochzählen und nach 100 Interrupts die Zeitanzeige aktualisieren.
Der Ticker wird zum Einrichten eines wiederkehrenden Interrupts zum wiederholten Aufrufen einer Funktion mit einer bestimmten Rate verwendet. Es gelten dieselben Randbedingungen wie beim Interrupt. Wir werden später sehen, dass Sie die Verwendung des mbed RTOS-Timers anstelle eines Tickers in Erwägung ziehen sollten. Auf diese Weise wird die periodische Funktion nicht in einem ISR ausgeführt, wodurch mehr Freiheit und Sicherheit im Code erhalten wird. Ebenso stehen in Mbed-RTOS Threads zur Verfügung deren Code quasi parallel zu anderen Code ausgeführt wird (siehe auch Threads in der Informatik).
ACHTUNG bei Funktionen
- In der ISR darf keine wait-Funktionen, Endlosschleifen oder blockierende System Calls verwendet werden.
- No printf, malloc, or new in ISR
Keine Bibliotheksfunktionen, die nicht re-entrant sind.
Fragen¶
- Welche Nachteile besitzt busy waiting?
- Welche Funktion wird von Mbed-C++ für bussy waiting verwendet?
- Welche Vorteile haben eine Interrupt fähige Bearbeitung?
- Vergleichen Sie Polling mit Interrupt-Bearbeitung?
- Welche Nachteile besitzt Polling?
- Welche Klasse von Mbed steht für die Interrupt-Bearbeitung zur Verfügung?
- Erklären Sie mit Hilfe einer Skizze den Ablauf beim Abarbeiten eines Interrupt-Programms.
- Erklären Sie den genauen Ablauf beim Abarbeiten eines Interrupt-Programms. (Beschreibung + Skizze) Welche Rolle spielt dabei der Stack-Speicher?
- Wofür können Timer, Ticker, oder Timeout verwendet werden?
- Welche Code-Teile sollten in jeder ISR vermieden werden?