Mikrocomputertechnik


Prof. Jürgen Plate

2 Hardware von Mikrocomputern und -controllern

2.1 Struktur eines Mikrocomputers

Prinzipieller Aufbau

Ein Mikrocomputer hat grundsätzlich die gleichen Eigenschaften, wie ein größeres DV-System, die von-Neumann-Struktur. Die Besonderheiten sind:

Der System-Bus

Bus = Anzahl von Leitungen, an die mehrere Funktionseinheiten parallel angeschlossen sind. Der Informationsaustausch zwischen diesen Einheiten erfolgt zeitmultiplex über den Bus. Zu jedem Zeitpunkt sind immer nur zwei Einheiten (Sender, Empfänger) miteinander verbunden. In Mikroprozessor-Systemen ist (mit Ausnahme des DMA) der Mikroprozessor immer einer der beiden aktiven Bausteine. Die Bus-Leitungen werden in funktionelle Gruppen gegliedert:

Der Bus ist eine ökonomische Verbindung mehrerer Baugruppen. Es sind flexible Erweiterung und systematische Verschaltung möglich (Backplane, Bus-Platine). Der Zugang erfolgt über Steckplätze (Slots). Ein Bus ist aber auch relativ langsam, da keine Parallelarbeit möglich ist und das Fan-Out der sendenden Komponenten ist begrenzt (u.U. spezielle Pufferbausteine = Bus-Treiber, Bus-Extender nötig). Es gibt Systeme, bei denen ein Teil des Busses für verschiedene Funktionen mehrfach genutzt wird → Zeitmultiplex-Betrieb (z. B. 8085: Datenbus/LSB Adressbus)

A-Bus     Adreßbus 
D-Bus     Datenbus 
S-Bus     Steuerbus (Control-Bus) 
RAM Random-Access-Memory (Schreib-Lese-Speicher) ROM Read-Only-Memory (Festwert-Speicher) SIO Serial Input Output PIA Parallel Input Output

Bus-Treiber

Problem bei Bus-Systemen: Es darf immer nur ein einziger Sender am Bus aktiviert sein - alle anderen Sender müssen abgeschaltet sein.

Aufgaben des Bus-Treibers:

Die Ausgänge des Mikroprozessors und der übrigen Bausteine sind i. a. als Tri-State-Ausgänge ausgeführt → direkter Busanschluß möglich. Für Funktionseinheiten ohne Tri-State-Ausgänge und als Bus-Extender gibt es spezielle Treiber-ICs.

Unidirektionaler Treiber (Buffer, Line Driver) z. B. 74244

Bidirektionaler Treiber (Transceiver) z. B. 74245 (8-fach)

Systembeispiel

Aufzugsteuerung mit Mikroprozessor 6802. Auf dem CPU-Chip sind 128 Byte RAM integriert. Somit wird extern nur noch E/A und ROM benötigt.

2.2 Mikroprozessor

Zwischenbemerkung: Die Wahl des Prozessors hängt auch von der Anwendung ab (so ist z.B. für einfache Steuerungen ein 8-Bit-Prozessor vollkommen ausreichend). Die Umstellung des Entwicklers von einem auf den anderen Mikroprozessor ist i.a. nicht allzu schwierig. Im praktischen Teil wird der 8-Bit-Mikroprozessor 6809 verwendet, der sich durch einen einfachen, überschaubaren und orthogonalen Befehlssatz auszeichnet.

Versorgung und Steuerung

Gruppierung der µP-Anschlüsse:

Die Steuer-Signale dienen zur programmunabhängigen Beeinflussung des Mikroprozessors, z. B. Reset, Interrupts. Deren Quittungssignale sind teilweise auch dem S-Bus zuzuordnen.

Die Spannungsversorgung erfolgt heute mit + 5V; früher waren of mehrere Spannungen notwendig (+5V, -5V, +12V).

Der Takt wird entweder mit einem externen Taktgenerator oder intern erzeugt. Normalerweise genügt ein Quarz, bei einfachen Systemen sogar ein R-C-Glied.

Die Taktfrequenz sagt nichts über die tatsächliche Ablaufgeschwindigkeit aus. Bei interner Takterzeugung ist i.a. nur noch ein externer Quarz nötig. Die Quarzfrequenz beträgt ein Vielfaches der Taktfrequenz (2 - 18 * Taktfrequenz).

Steuerungs-Signale

Dierser Abschnitt soll einen Überblick der Signale vermitteln. Nicht jeder Mikroprozessor verfügt über alle genannten Möglichkeiten.

Rücksetzen (Reset)

Herstellen eines definierten Grundzustandes des Prozessors:

Wichtig: Einschaltverhalten der Mikroprozessor beachten! Reset darf erst erfolgen, nachdem die Versorgungsspannung eine bestimmte Zeit stabil anliegt (Einschwingzeit des Quarzoszillators).

Warten (Wait, Memory Ready, MRDY, Ready)

Dieser Anschluß dient der Anpassung an langsame Speicher oder E/A-Bausteine. Erreicht wird eine Verlängerung des Speicherzugriffszyklusses.

Halten (Hold, Halt, Stop)

Anhalten des Programmablaufs nach Beendigung des laufenden Befehls.

Befehlsunterbrechungen (DMA, BREQ)

Anhalten der Ausführung des aktuellen Befehls nach Beendigung des laufenden Zyklusses - also mitten im Befehl.

Befehls-Abbruch (Abort)

Abbruch des laufenden Befehls bei virtueller Speichertechnik

Programm-Unterbrechung (Interrupt)

Unterbrechung des laufenden Programms nach Beenden des laufenden Befehls. Ausführen einer Interrupt-Serviceroutine (ISR).

Arten:

2.3 Arbeitsspeicher

Speicher-Bausteine

Als Speicherbausteine werden Halbleiterspeicher verwendet. Folgenden Begriffe dienen zur Spezifizierung eines Speichers:

Anschlüsse:

Organisationsformen:

Zusammenschalten von Speicherbausteinen

Der Gesamtspeicher wird durch Zusammenschaltung von Speicherbausteinen gebildet (sofern nicht schon ein Baustein ausreicht). Er besteht aus RAM und ROM (PROM, EPROM). Die Zusammenschaltung kann erfolgen: Bei der Zusammenschaltung in Bitrichtung werden alle Bausteine parallel adressiert.

In allen anderen Fälle gilt:

Beispiel 1: Zusammenschaltung in Wortrichtung, uncodierte Bausteinauswahl:

Beispiel 2: Zusammenschaltung in Wortrichtung, codierte Bausteinauswahl, externe Decodierung

Ergänzende Bemerkungen

Ist der Adreßraum des Mikroprozessors breiter als der zur Speicheradressierung eingesetzte Adreßbus, tritt Mehrfachadressierung auf: Adressen, die sich nur in den unbenutzten höherwertigen Bits unterscheiden, sprechen die gleiche Speicherzelle an. Dieser Effekt kann erwünscht sein - das Entwicklungssystem adressiert seinen Daten-Speicher ab $8000, der Steuerungsrechner ab Adresse 0.
Gelegentlich muß noch ein Signal zur zeitlichen Koordination der Speicherzugriffe eingesetzt werden.
Bei ROM-Bausteinen gibt es häufig noch einen Eingang zum Schalten der Ausgänge in den Tri-State-Zustand (OE=Output Enable).

2.4 Ein-/Ausgabe-Bausteine

Struktur von E/A-Bausteinen

Der E/A-Baustein ist Bindeglied zwischen Prozessor und Peripherie. Seine Aufgaben sind unter anderem:

Datentransport, zeitliche Anpasung, Signalumsetzung, Pegelumsetzung, Erweiterung der Belastbarkeit, Datenformat-Anpassung, Codeumsetzung, ...)

Das Einsatzgebiet der E/A-Bausteine reicht von einfacher Byte-orientierter Ein- und Ausgabe bis zur autonomen Verwaltung komplexer Protokolle, wie z. B. die Netzwerkanbindung. E/A-Komponenten werdenin der Regel so entworfen, dass sie jeweils einen möglichst großen Bereich von Anwendungen abdecken. Die Spezialisierung für die Anwendung geschieht durch Initialisierung des Bauteils im System, ein Vorgang, der in Datenblättern und im allgemeinen Sprachgebrauch "Programmierung" genannt wird: Nach jedem Einschalten des Systems müssen bestimmte Steuerregister in diesen Bausteinen von der CPU aus mit bestimmten Werten initialisiert werden.

Bausteine für programmierten E/A-Transfer

Zur bitparallelen Ein/Ausgabe werden von fast jedem Hersteller Bausteine angeboten und nahezu jeder Controller verfügt über parallele E/A. Verschiedene Bezeichnung sind in Gebrauch: Der Baustein besitzt hierzu Steuerregister, deren Inhalte die Datenrichtung, Bedeutung von Steuersignalen (Handshake) und das Interruptverhatten festlegen.

Der Zugriff auf die Peripherie erfolgt entweder programmgesteuert (polling) oder interruptgesteuert. Sie werden am häufigsten verwendet. Auch Bus-Treiber können als sehr einfache E/A-Bausteine eingesetzt werden. So wurde z. B. die Standard-Druckerschnittstelle des IBM-PC mit zwei 8-Bit-Latches und zwei 8-Bit-Bustreibern realisiert. Kaum komplexer sind auch Speicher-Register mit nachgeschalteten Leistungstreibern. Sie übernehmen auch die zeitliche Anpassung. Zum Teil sind sie mit Steuerlogik, Betriebsartenwahl (Ein/Aus) und Interrupt-Auslösung versehen.

Wesentlich flexibler im Einsatz sind programmierbare E/A-Bausteine, wie man sie heute verwendet. Eigenschaften und Funktion sind per Software einstellbar. Programmierbare Eigenschaften können sein:

Diese Bausteine erlauben meist sowohl programmgesteuerten programmierten E/A-Transfer als auch interruptgesteuerten programmierten E/A-Transfer. Für den einfachen E/A-Transfer gibt es zwei Bausteine-Grundtypen:

  1. Parallele Schnittstelle (Parallel Interface Adapter, Parallel Input Output) Schnittstelle für parallelen Datenaustausch (z.B. Centronics-Druckerschnittstelle, Relais-Ausgang, Digital-Analog- und Analog/Digital-Wandler, digitale Eingangssignale). In der Regel sind mehr als ein 8 Bit breiter "Port" vorhanden (meist 2 bis 4). Steuer- oder Statusregister können pro Port separat vorhanden sein.

  2. SIA (Serial Interface Adapter, Serial Input Output) Dies ist eine Schnittstelle für bitseriellen Datenverkehr. Die Bausteine enthalten je einen Parallel-Seriell- und Seriell-Parallel-Wandler (Schieberegister).

    Bei seriellen Schnittstellen kann es sich um einen UART (Universal Asynchronous Receiver/Transmitter) handeln, wie man ihn von der guten alten seriellen Schnittstelle des PC her kenn, aber auch um spezielle Schnittstellen für die Kommunikation zwischen einzelnen ICs, beispielsweise die I2C- oder die SPI-Schnittstelle. Generell gilt:

    Der Baustein enthält einen getrennten Sende- und Empfangsteil, sodass Vollduplexbetrieb möglich ist. Ein USART (Universal Synchronous/Asynchronous Receiver/Transmitter) bietet neben der asynchronen Betriebsweise auch synchrone Betriebsarten. Im synchronen Betrieb einer seriellen Übertragung werden Blöcke von Bytes (z. B. Zeichen oder beliebige Binärinformation) ohne Pausen übertragen. Die Synchronisation zwischen Sender und Empfänger, die beim asynchronen Betrieb für jedes Zeichen am Empfänger neu hergestellt werden muss, bleibt im synchronen Betrieb nicht nur während eines Zeichens erhalten, sondern während eines langen Bitstroms (Datenblock).

    Um die Syrichronisation auch dann aufrecht zu erhalten, wenn der Sender nicht schnell genug weitere Oktets liefern kann, wird solange automatisch ein vorgebbares Synchronisationszeichen übermittelt damit der serielle Bitstrom nie abreißt. Dadurch werden Start- und Stopbits überflüssig, was zu höheren effektiven Datenraten führt. Meist wird auch das Paritätsbit bei jedem Zeichen durch eine CRC-Prüfinfo (CRC = Cyclic Redundancy Check)am Ende einer ganzen Serie von Zeichen ersetzt, wodurch die Effektivität der Datenrate und der Fehlersicherung wesentlich erhöht wird.

Daneben existieren noch viele weitere E/A-Bausteine. Sie sind i.a. wesentlich komplexer aufgebaut und bieten zahlreiche Programmierungsmöglichkeiten. Zum Beispiel:

Zusammenfassung: Aufgaben einer E/A-Schnittstelle

Die Gesamtheit der Einrichtungen, über welche die CPU mit den peripheren Geräten kommuniziert, nennt man E/A-Schnittstelle. Im Allgemeinen findet ein (bidirektionaler) Datentransport zwischen Speicher und Peripherie statt. Neben dem reinen Datentransport ist eine Anpassung der Datendarstellung zwischen CPU und Peripherie erforderlich = Umsetzung der Bus- auf die Peripherieschnittstelle: Zeitliche Anpassung (CPU und Peripherie arbeiten i. a. nicht synchron, d. h. sie sind zeitlich zu entkoppeln).
  • Signalumsetzung (z. B. Pegelanpassung)
  • Datenformatanpassung (z. B. seriell/parallel-Wandlung)
  • Codewandlung
  • Fehlererkennung und -korrektur Schnittstellen können von unterschiedlicher Komplexität sein:

    Steuerung von E/A-Bausteinen

    Steuersingnale von der CPU: Steuersignale von der Peripherie: Steuerleitungen vom E/A-Baustein zur CPU:

    Anschluß von E/A-Bausteinen

    Die Steuersignale werden mit dem Steuer-Bus verbunden. Aus dem Adreß-Bus werden die Cchip-Select- und Register-Select-Signale abgeleitet. Normalerweise werden die RS-Signale mit den niederwerigen Adreßleitungen verbunden (RS0 mit A0, RS1 mit A1, usw.). Über den Daten-Bus erfolgt der eigentliche Datenaustausch.

    Da i. a. mehrere E/A-Bausteine (mit mehreren Registern) an ein System angeschlossen werden, ist eine Adressierung der E/A-Bausteine nötig. Es gibt dafür zwei Methoden:

    1. Getrennte Adressierung (Isolated I/O, I/O-Mapped I/O)
      Der Rechner verfügt über spezielle E/A-Befehle und einen eigenen E/A-Adreßraum. Die E/A-Adresse wird oft auch Port genannt. Sie wird entweder auf separaten Adressleitungen zu den Schnittstellen geführt oder über den normalen Adreßbus geleitet. In diesem Fall gibt es (eine) zusätzliche Steuerleitung(en) zur Unterscheidung zwischen E/A- und Speicheradressen. Da i.a. der E/A-Adreßraum kleiner als der Speicheradreßraum ist, wird nur ein Teil der A-Bus-Leitungen verwendet (z. B. 8080/8085: 8 Bit, 80386: 10 Bit).

    2. Speicheradressierung (Memory Mapped I/O)
      Der E/A-Adreßraum wird in den Speicher-Adreßraum abgebildet, d.h. bestimmte Adressen stellen keine Speicheradressen, sondern E/A-Adressen dar geringfügige Einschränkung des Speicheradreßraums. Die E/A-Adressen werden von der CPU genauso behandelt und angesprochen, wie Speicheradressen. E/A-Operationen werden mit den normalen Transportbefehlen durchgeführt (z. B. Load, Store) Einsparung zusätzlichen Aufwandes für Adreß-/Steuerleitungen und für spezielle E/A-Befehle.

    Programmgesteuerter E/A-Transfer (Polling)

    Einfache E/A-Schnittstellen für programmierten E/A-Transfer bestehen wesentlich aus: Sie ist normalerweise an den Systembus der CPU angeschlossen. Das EADR dient zur Zwischenspeicherung des zu übertragenden Datenwerts (zeitliche Anpassung). Neben den zu übertragenden Daten braucht die Schnittstelle Signale zur richtigen Abwicklung des Datentransfers:

    Diese Signale werden - soweit sie für längere Zeit zur Verfügung stehen müssen - im EASR gespeichert. Das EASR kann auch aus separaten Registern für Status- und Steuersignale bestehen. Normalerweise verfügt ein Computer über mehr als eine E/A-Schnittstellen Adressierung erforderlich. Im allgemeinen erhalten EADR und EASR eine eigene, separate Adresse. Beide sind am Datenbus angeschlossen. Steuersignale werden wie Datenwerte ins EASR geschrieben, Statussignale werden wie Datenworte aus dem EASR gelesen - die Verarbeitung muss in der CPU durch geeignete Befehle erfolgen (z.B. logische Verknüpfung).

    Die E/A-Befehlsfolge steht innerhalb eines Programms und wird im Rahmen der normalen Programmausführung abgearbeitet. Die gesamte Initiative zur E/A geht vom Programm aus. Zeigt der Inhalt des EASR an, dass keine neuen Daten im EADR stehen, muss das Programm erneut das EASR abfragen Warteschleife, "Polling". Dabei können zwei "Randbereiche" Probleme verursachen:

    Direktspeicherzugriff (DMA = Direct Memory Access)

    Beim DMA steuert die E/A-Schnittstelle den Transfer nach Anstoß durch die CPU selbstständig und ohne Zuhilfenahme der CPU Datentransport zwischen Speicher und Peripherie unter Umgehung der CPU. Selbst, wen die CPU in dieser Zeit nichts anderes tut, ist ein wesentlich schnellerer Datentransport möglich (weitgehender Wegfall der Verwaltungsarbeit). Daher ist DMA für den schnellen Transfer großer Datenmengen besonders geeignet. Zum Anstoßen des DMA-Transfers übermittelt die CPU der DMA-Schnittstelle: Die DMA-Schnittstelle benötigt zwei weitere Register:

    Da während des DMA-Transfers anstelle der CPU die DMA-Schnittstelle die Kontrolle über den Systembus besitzt, muss sie zusätzlich über eine Bus-Steuerlogik verfügen (Konkurrenz zwischen DMA Schnittstelle und CPU um den Bus).

    Ablauf eines DMA-Transfers:

    Man unterscheidet verschiedene DMA-Modi:

    2.5 Timer (Zeitgeber)

    Zur Gruppe der Port-Level-Controller gehören auch die sehr häufig eingesetzten Zähler- und Zeitgeber-Bausteine. Da in den meisten Systemen Impulse gezählt oder erzeugt werden bzw. die Dauer von Impulsen gemessen werden muss, stellt es eine große Entlastung der CPU dar, wenn diese Vorgänge nicht per Programm gesteuert, sondern durch zusätzliche Hardware unterstützt werden.

    Ein Timer besteht aus einem programmierbaren (voreinstellbaren) Rückwärts-Zähler mit eigenem, vom Prozessor unabhängigen, Takt. Der Takt kann über Steuerregister freigegeben bzw. gesperrt werden. Der aktuelle Zählerstand kann jederzeit von der CPU ausgelessen werden. Bei Zählerstand 0 wird ein maskierbarer Interrupt erzeugt. Der Timer hat in der Regel mehrere Modi:

    Anwendungen:

    2.6 Systemkonfigurationen

    Dieses Kapitel zeigt die Zusammenschaltung von Speicher (RAM, ROM) und E/A-Bausteinen zu einem Mikrocomputer-System. Die zeitliche Koordination wied hier nicht behandelt (da von Prozessor zu Prozessor verschieden).

    Aufteilung des Adreßraums

    Hierbei geht es um die Zuordnung verschiedener Speicher- und E/A-Bereiche zu den Adressen. Man unterscheidet: In der Praxis finden sich häufig Mischformen (Teildecodierung), d. h. es wird nur soweit decodiert, daß alle Bausteine einen eigenen Adreßraum besitzen - also eindeutig ansprechbar sind. Dabei kann es durchaus sein, daß ein Baustein unter mehreren Adressen ansprechbar ist → Bauteileersparnis beim Decodieren.
    Oft erfolgt die Vergabe bestimmter Bereiche für bestimmte Gruppen von Bausteinen, z. B. ROM: 0 - $7FFF, RAM: $8000 - $8FFF, E/A: F000 - FFFF.
    Die Vergabe ist vom Prozessor abhängig (8080: ROM bei 0, 6800: ROM bei $FFFF wegen Reset-Vektor). In letzteren Fall kann man durch Teildecodierung erreichen, daß das ROM sowohl bei 0, als auch bei $FFFF adressierbar ist.

    Systembeispiel

    Minimalsystem mit 6802:

    Beispiele zur Systemkonfiguration

    1. Volldecodierung:

    Prozessor mit eingebautem RAM
    CS vom ROM active low!

    2. Volldecodierung, erweitert

    CS von ROM und RAM active low!

    3. Minimaldecodierung

    CS vom ROM und PIO active low!

    Adressierung modulo $1000!
    ROM erscheint bei $0000, $1000, $2000, ..., $D000, $E000, $F000

    4. Minimaldecodierung ROM und E/A

    Adressierung modulo $1000!
    ROM erscheint bei $0000, $1000, $2000, ..., $7000
    PIO erscheint bei $8000, $8004, $8008, ..., $FFFF

    5. Teildecodierung (Volldecodierung mit Lücken)

    µP, D­ und S­Bus aus Platzgründen weggelassen!
    CS active low!

    RAM erscheint bei $0000, $4000, usw.
    ROM erscheint bei $1000, $5000, usw.
    PIO 1 belegt den gesamten Bereich $2000 - $2FFF, $6000 - $6FFF, usw.
    PIO 2 belegt den gesamten Bereich $3000 - $3FFF, $7000 - $7FFF, usw.

    2.7 Programmunterbrechungen (Interrupts)

    Um auf ein (Hardware-) Ereignis rechtzeitig reagieren zu können, muss dieses Ereignis zuverlässig erfasst werden. Die kann, wie schon geschildert, durch regelmäßiges Abfragen einer Schnittstelle (Polling) erfolgen. Treten jedoch mehrere Ereignisse in relativ kurzer Zeit auf, ergeben sich unter Umständen Wartezeiten bei der Bearbeitung oder es wird schlimmstenfalls auf ein E/A-Signal gar nicht reagiert. Durch sehr häufige Abfragen wird zudem der Prozessor stark belastet. Es bedarf somit einer sinnvollen Alternative zum Polling:

    Eine Programmunterbrechung (Interrupt) ist zunächst einmal ein Signal, das eine sofortige Reaktion fordert. Die Behandlung des signalisierten Ereignisses erfolgt in einem speziellen Unterprogrann, der sogenannten Interrupt Service Routine. Programmunterbrechungen können durch Signale aus der Rechnerumgebung (z.B. vom gesteuerten Prozeß) ausgelöst werden, um quasi "die Aufmerksamkeit" des Rechners auf sich zu lenken. Insbesondere auf dringende, aber relativ selten auftretende Ereignisse können so die entsprechenden Programme (Interrupt Service Routinen) schnell reagieren. In der Regel führt die Ablaufsteuerung nach der Beendigung des gerade ausgeführten Befehls die Programmunterbrechung durch und setzt nach der Abarbeitung der Interrupt Service Routine (ISR) das unterbrochene Programm fort.

    Die Aufgaben der Interruptbehandlung im einzelnen:

    1. Aufnehmen und Überprüfen der Unterbrechungsanforderung:
      Im einfachsten Fall hat das Unterbrechungswerk nur eine einzige Eingangsleitung für die Unterbrechungsanforderungen. Diese führt auf ein Flip-Flop, das durch ein Anforderungssignal auf 1 gesetzt wird und bei Bedienung des Interrupts sofort wieder gelöscht werden muß um evtl. weitere Interrupt-Anforderungen aufnehmen zu können. Dieses FF ist notwendig, um die zu beliebigen Zeitpunkten ankommenden Interrupt-Anforderungen (Interrupt-Request) so lange zu speichern, bis sie vom Leitwerk am Ende der Befehlszyklen abgefragt werden.

      Häufig darf jedoch eine Interrupt-Anforderung nicht sofort zur Unterbrechung führen, z.B. während der Ausführung zeitkritischer Programmabschnitte. Eine einfache Möglichkeit besteht in der "Maskierung" des Signals mit Hilfe eines Masken-FF's und eines Gatters. Nur wenn das Masken-FF gesetzt ist, führt eine "anstehende" Unterbrechungsanforderung auch zu einem Interrupt. Das Masken-FF kann i.a. durch Maschinenbefehle gesetzt und gelöscht werden ("enable" bzw. "disable interrupt").

      Normalerweise gibt es bei jeder CPU auch einen nicht maskierbaren Interrupt (non maskable interrupt, NMI), der nicht mehr makiert/abgeschaltet werden kann, sofern er einmal nach dem Reset aktiviert wurde. In Grunde ist auch der Reset ein solcher nicht maskierbarer Interrupt.

    2. Identifizierung des Interrupt-Verursachers:
      Typische Anwendungen mit mehreren Quellen für Interrupt-Anforderungen verlangen, daß für jedes Signal auch ein spezifisches Unterbrechungs-Bearbeitungs-Programm (ISR = Interrupt Service Routine) vorhanden ist, da ja auf jedes Signal anders zu reagieren ist. Damit ergibt sich das Problem der Interrupt-Identifizierung als Voraussetzung für die Zuordnung der richtigen ISR und für das Löschen des richtigen Interrupt-Anforderungs-Flip-Flops.

      Die beiden wichtigsten Grundprinzipien der Interrupt-Identifizierung sind:

      • Polling: Der Interrupt-Verursacher kann sich nicht selbst zu erkennen geben; am Prozessor erscheint lediglich das Anforderungssignal und es ist die Aufgabe des Interrupt-Bearbeitungs-Programms, über eine Kette von Abfragen an die in Frage kommenden Peripherie-Bausteine, den aktuellen Interrupt-Verursacher herauszufinden. Mit "Abfragen" ist hier das Lesen der Statusregister der Peripheriebausteine gemeint, in denen die Tatsache der Interrupt-Anforderung jeweils in einem bestimmten gesetzten Bit (Interrupt-Request-Bit) vermerkt ist.
      • Interrupt-Vectoring: Der Interruptverursacher liefert (im Zuge der Bussequenzen bei der Interrupt-Annahme durch den Prozessor) einen "Kenn-Code" mit ab (meist über den Datenbus), an dem der Prozessor erkennen kann, um welchen Interrupt es sich handelt. Dieser sogen. "Interrupt-Vektor" wird i.a. gleich als (indirekte) Startadresse der zugehörigen ISR verwendet. Damit entfällt das zeitraubende Abfragen, die sogenannte Interrupt-Reaktionszeit wird kürzer.
    3. Vorrangsteuerung der Interruptverursacher:
      Nicht alle Interrupts sind mit der gleichen Dringlichkeit zu bearbeiten; so muß z.B. die Interrupt-Anforderung, die den Zusammenbruch der Netzspannung anzeigt, vorrangig behandelt werden gegenüber einer Interrupt-Anforderung, die lediglich zur Übernahme eines Datenwortes von einer Eingabeschnittstelle auffordert.
    4. Retten und Rückspeichern des Prozessorzustandes:
      Wenn eine Programmunterbrechung ausgeführt werden soll, so muß auf jeden Fall der Zustand des Prozessors gerettet werden. Denn das Interrupt-Service-Programm benutzt ja ebenfalls den Prozessor und verändert dabei dessen Zustand. Soll anschließend das unterbrochene Programm fortgesetzt werden, so ist es unbedingt nötig, vorher den Zustand wieder herzustellen, wie er bei Auftreten der Unterbrechung herrschte. Die Prozessorzustände, die während einer Befehlsausführung durchlaufen werden, sind nur sehr aufwendig zu beschreiben (z. B. mitten in einer Multiplikation). Entsprechend groß wäre der Aufwand zur Rettung des Prozessorzustandes, wenn man Unterbrechungen mitten im Befehlszyklus zuließe. Man läßt deshalb Unterbrechungen i. a. nur am Ende eines Befehls zu, denn dann ist der Prozessorzustand vollständig durch den Inhalt der Prozessorregister definiert.
      In einer typischen Interrupt-Service-Routine werden die Inhalte von Prozessor-Registern verändert. Aber selbst wenn keine derartigen Befehle in der ISR vorkommen, so müssen doch zumindest zwei Register gerettet werden: der Programmzähler und das Prozessor-Status-Register, denn die Inhalte dieser Register ändern sich in jedem Fall. Man bezeichnet diese beiden Register auch als "Zustandsvektor". Die einfachste Möglichkeit, den Zustandsvektor zu retten, besteht darin, ihn in bestimmte reservierte Speicherzellen zu schreiben, und ihn von dort nach Beendigung der ISR wieder zu lesen. Dies hat den offensichtlichen Nachteil, daß keine Verschachtelung (Nesting) von Programmunterbrechungen möglich ist, d.h. man müßte das Unterbrechen einer ISR verbieten, weil sonst der gerettete Zustandsvektor überschrieben würde.
      Wesentlich besser eignet sich zum Retten des Zustandsvektors ein sogenannter Kellerspeicher (engl. stack, oder auch LIFO = last in first out). Das Stackprinzip kann hardwaremäßig realisiert sein (spezielle Chips) oder in einem reservierten Bereich des normalen Arbeitsspeichers nachgebildet sein. Zu diesem Zweck existiert ein Zeigerregister, das immer den letzten Eintrag im Stack adressiert (Stackpointer zeigt immer auf den "Top of Stack", d.h. auf den letzten Eintrag).
      Mit jeder neuen (geschachtelten) Programmunterbrechung wächst der Kellerspeicher um die entsprechenden Einträge, mit jedem Rücksprung in ein vorher unterbrochenes Programm reduziert er sich wieder entsprechend, so daß das zuletzt unterbrochene Programm nach Beendigung des laufenden wieder aufgenommen wird. Der Stack wächst und schrumpft mit jedem Eintreten/Verlassen von ISRs, man sagt, der Stack "pulsiert". Häufig müssen außer den beiden o.g. Registern (PC und Prozessor-Status-Register) auch noch andere gerettet und rückgespeichert werden, nämlich dann, wenn sie von der ISR verändert werden. Auch hier bringt die Verwendung eines Stacks die gleichen Vorteile wie oben erwähnt. Da diese Register jedoch nicht immer gerettet werden müssen besteht hier die Möglichkeit, sie entweder genau wie den Zustandsvektor per Hardware (d.h. per Ablaufsteuerung) zu retten oder per Maschinenbefehl(e), also programmgesteuert.
      Während bei der Hardware-Lösung sämtliche Register gerettet werden müssen (sie "weiß" je nicht, welche es sein müssen), kann die programmierte Lösung sich auf genau die Register beschränken, die in der ISR verändert werden (der Programmierer weiß welche - hoffentlich!). Die sicherere und meist auch schnellere, jedoch auch aufwendigere Methode ist die Hardware-Lösung.

    Die Notwendigkeit, bei der Ausführung einer Programmunterbrechung zunächst den Zustand des unterbrochenen Programms zu retten, kann also eine Reihe von Transportoperationen benötigen; vom Moment des Eintreffens der Unterbrechnungsanforderung vergeht daher einige Zeit, die Interrupt-Reaktionszeit, bis der erste produktive Befehl der ISR ausgeführt wird. Diese Reaktionszeit setzt sich aus den folgenden Komponenten zusammen:

    Unterbrechungsgesteuerter E/A-Transfer

    Die E/A-Befehlsfolge wird durch einen von der E/A-Schnittstelle ausgelösten Interrupt gestartet. Der Interrupt wird von der Schnittstelle abgesetzt, wenn ein Datenwort empfangen wurde und im EADR steht (bzw. wenn ein Datenwort aus dem EADR abgeholt wurde). Die CPU braucht nicht in einer Programmschleife zu warten, sondern kann in der Zwischenzeit ein anderes Programm bearbeiten, das durch den Interrupt kurzzeitig unterbrochen wird. Der interruptgesteuerte Transfer gestattet zudem die quasi-simultane Bedienung mehrerer langsamer Schnittstellen. Zur Realisierung muß eine Interrupt-Leitung von der E/A-Schnittstelle (EASR) zum Unterbrechungswerk der CPU vorhanden sein.

    Vorteil des programmierten Transfers: Sehr einfache Schnittstellen, die übersichtlich und leicht zu verwenden sind.

    Nachteil des programmierten Transfers: Für den Transfer jedes einzelnen Datenworts wird die CPU benötigt. Diese muss dabei relativ viel Verwaltungsaufwand leisten (Laden/lesen EASR, Interrupt-Behandlung) die maximale Datenrate ist sehr begrenzt.

    Durch den Interupt wird auch der Befehlszyklus erweitert. Nach Abarbeitung des Befehls wird das Vorhandensein eines Interrupts geprüft und ggebenenfalls in die Interrupt-Serviceroutine (ISR) verzweigt. Dabei werden alle Register auf dem Stack abgelegt und beim Beenden der ISR wieder restauriert.

    Man unterscheidet bei der Adressangabe für die ISR zwei Möglichkeiten:

    Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt


    Copyright © FH München, FB 04, Prof. Jürgen Plate
    Letzte Aktualisierung: 07. Okt 2012