Titelbild Mikrocontroller

2.7. Reset und Interrupt Behandlung

Der ATmega8 bietet eine Vielzahl verschiedener Interruptquellen. Diese Interruptquellen haben ebenso wie der Reset-Vektor separate Einsprungadressen im Programmspeicher. Alle Interrupts können separat freigegeben werden, indem sie mit einer logischen 1 in den dazugehörigen Registern beschrieben werden. Außerdem müssen alle Interrupts durch Setzten des Globalen Interrupt Freigabe Bits im Status-Register freigegeben sein. Abhängig vom Wert des Program Counter (PC) werden Interrupts automatsich gesperrt, wenn die Lock-Bits BLB02 oder BLB12 programmiert sind. Dadurch kann eine höhere Softwaresicherheit erreicht werden.

Die unteren Adressen im Programmspeicher sind als Reset- und Interrupt-Vektoren vor-eingestellt. Die vollständige Liste der Einsprungadressen und der Interrupt-Prioritäten sind im Teil Interrupt beschrieben. Allgemein gilt, dass die niedrigsten Einsprungadressen die höchste Priorität haben. Somit hat der Reset mit der Einsprungadresse 0000h die höchste Priorität.

Die Interrupt-Vektoren können an den Beginn des Boot-Sektors verschoben werden, indem das Interrupt Vektor Select (IVSEL) Bit im General Interrupt Control Register (GICR) gesetzt oder indem die BOOTRST Fuse programmiert wird.

Wenn ein Interrupt auftritt, wird das Global Interrupt Freigabe Bit (I-Bit) automatisch gelöscht, so dass keine weiteren Interrupts akzeptiert werden. Wenn das I-Bit durch die Software wieder auf 1 gesetzt wird, können weitere Interrupts die laufende Interrupt-Routine unterbrechen. Das I-Bit wird durch das Beenden einer Interrupt-Routine (RETI-Befehl) automatisch wieder gesetzt.

Man unterscheidet grundsätzlich zwei Arten von Interrupts. Die erste wird durch ein Ereignis getriggert und setzt dadurch ein Interrupt-Flag. In diesem Fall wird der Program Counter mit dem dazugehörigen Interrupt-Vektor geladen um die Interrupt-Routine auszuführen. Gleichzeitig wird das dazugehörige Interrupt-Flag durch die Hardware wieder gelöscht. Das Interrupt-Flag kann aber auch dadurch gelöscht werden, indem eine 1 an die Position des Flags geschrieben wird. Wenn ein Interrupt auftritt, während der dazugehörige Interrupt gesperrt ist, wird das Interrupt-Flag trotzdem gesetzt. Es erinnert also so lange an das aufgetreten Ereignis, bis der Interrupt freigegeben wird oder das Flag durch die Software gelöscht wird. Das gleiche gilt für Interrupts, die auftreten, während alle Interrupts global gesperrt sind. In diesem Fall werden nach der globalen Freigabe alle zwischenzeitlich aufgetretenen Interrupts entsprechend ihrer Priorität abgearbeitet.

Die zweite Art von Interrupts hat nur für die Dauer des Auftretends ihres auslösenden Ereignisses Gültigkeit. Diese Interrupts haben nicht notwendigerweise ein Interrupt-Flag. Somit wird ein Interrupt nicht ausgeführt, wenn das Ereignis wieder verschwindet, bevor der dazugehörige Interrupt freigegeben wird.

Wenn eine Interrupt-Routine beendet wird, wird immer das Hauptprogramm wieder aufgerufen und mindestens ein weiterer Befehl des Hauptprogramms ausgeführt, bevor ein wartender Interrupt abgearbeitet wird. Das Status-Register wird beim Aufruf der Interrupt-Routine nicht automatsich gesichert, daher muss dies durch die Software sichergestellt werden.

Wenn der CLI-Befehl verwendet wird, um die Interrupts zu sperren, dann wirkt diese Sperre sofort, so dass keine weiteren Interrupts ausgeführt werden, auch dann nicht, wenn der Interrupt zeitgleich mit dem CLI-Befehl auftritt.
Codebeispiel Interrupt sperren

Codebeispiel Interrupt sperren


Wenn der SEI-Befehl ausgeführt wird, um die Interrupts global freizugeben, dann wird auf jeden Fall erst noch der Befehl nach dem SEI-Befehl ausgeführt, bevor ein wartender Interrupt behandelt wird.
Codebeispiel Interrupt freigeben

Codebeispiel Interrupt freigeben

Impressum