 |
Mikrocomputertechnik
Prof. Jürgen Plate |
2 Hardware von Mikrocomputern
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:
- CPU ist in einem Chip integriert (Mikroprozessor)
- Der Arbeitsspeicher zerfällt i.A. bei Steuerungsrechnern in
Programmspeicher (ROM, PROM, EPROM,...) und Datenspeicher (RAM)
- Das E/A-Werk besteht aus speziellen E/A-Bausteinen, die als IC zahlreich und
passend für den verwendeten Mikroprozessor-Typ angeboten werden
Mikroprozessor-Familie:
- einfache serielle/parallele E/A-Bausteine,
- DMA-, CRT-, Floppy- und Platten-Controller,
- E/A-Prozessoren,
- Arithmetikprozessoren,
- Timer,
- Speicherverwaltungsbausteine,
- usw.
- Die Verbindung der einzelnen Komponenten erfolgt durch eine Bus-Struktur. (
teilweiser Verzicht auf Parallelarbeit einzelner Komponenten).
- Ein einfacher Mikrocomputer besteht aus relativ wenigen, hochintegrierten Bausteinen.
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.
- unidirektionaler Bus: Information geht nur in einer Richtung (i.a. nur 1 Sender)
- bidirektionaler Bus: Informationsaustausch in beiden Richtungen (mehrere Sender)
In Mikroprozessor-Systemen ist (mit Ausnahme des DMA) der Mikroprozessor immer einer
der beiden aktiven Bausteine. Die Bus-Leitungen werden in funktionelle Gruppen gegliedert:
- Adreß-Bus (A-Bus):
unidirektional, 8-32 Leitungen, Auswahl von Speicherzellen, Bausteinen, E/A-Registern
- Daten-Bus (D-Bus):
bidirektional, 8-32 Leitungen, Datentransport zw. Mikroprozessor und Speicher/Peripherie
- Steuer-Bus (Control-Bus, S-Bus):
Unterschiedliche Übertragungsrichtungen - aber jede Leitung für sich unidirektional,
4-20 Leitungen, Steuerung der Zusammenarbeit der einzelnen Baugruppen
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:
- An-und Abschalten der angeschlossenen Funktionseinheiten am Bus
- Durchschalten der gewünschten Übertragungsrichtung bei bidirektionalen
Busanschlüssen
- Erhöhung des Fan-Out (Anschlußkapazität) eines Busses
Bustreiber sind heute in der Regel Gatter mit Tri-State-Ausgang: Der dritte Zustand
(Z-State) ist ein hochohmiger Zustand = Trennen des Treibers vom Bus. Die Umschaltung
des Z-State erfolgt mit einem Enable-Steuersignal.
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.
- nicht überlappender Zweiphasentakt (wegen der internen Ablaufsteuerung und
des Rechenwerks)
- Mindestfrequenz darf bei einigen Modellen nicht unterschritten werden (Register
sind als dynamische Speicher realisiert).
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:
- Meist durch fallende Flanke am Reset-Anschluß des Mikroprozessors
- BZ auf definierten Anfangswert setzen (0, festen Wert oder durch Vektor definierten
Wert)
- Prozessor startet Befehlszyklus mit diesem Wert
- Interrupts sperren (Freigabe muß durch Programm erfolgen)
- Nicht immer: Rücksetzen der Register
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.
- gezielte Verlängerung einzelner Taktphasen (z. B. 6809)
- Einschieben leerer Zyklen (synchron) (80x86, "Wait States")
- Warten auf Fertigmeldung (asynchron) (68000)
Halten (Hold, Halt, Stop)
Anhalten des Programmablaufs nach Beendigung des laufenden Befehls.
- Bus geht in den Tri-State-Zustand
- Mikroprozessor nach außen inaktiv (intern weiter aktiv)
- Anwendungen:
- einfache DMA-Möglichkeit
- Start/Stop von außen (Test)
- Einzelschrittsteuerung
- Stop bei bestimmter Adresse
- "Aufwecken" nur durch Reset oder Interrupt
Befehlsunterbrechungen (DMA, BREQ)
Anhalten der Ausführung des aktuellen Befehls nach Beendigung des laufenden
Zyklusses - also mitten im Befehl.
- Bus geht in den Tri-State-Zustand
- Anwendung: DMA
- Nach Beendigung der Unterbrechung wird der unterbrochene Befehl fortgesetzt
Befehls-Abbruch (Abort)
Abbruch des laufenden Befehls bei virtueller Speichertechnik
- Wegspeichern des Programmstatus
- Seitenwechsel durchführen
- Programmstatus wiederherstellen
- abgebrochenen Befehl neu aufsetzen
Programm-Unterbrechung (Interrupt)
Unterbrechung des laufenden Programms nach Beenden des laufenden Befehls. Ausführen
einer Interrupt-Serviceroutine (ISR).
- Abspeichern des Programmstatus
- Setzen BZ auf feste oder vektorisierte Adresse
- Sperren weiterer Interrupts
- Auslösung durch Flanke oder Pegel
- Lokalisierung durch Polling oder HW-Vektor (z.B. bei 8080)
- Abarbeiten der ISR
- Restaurieren des Programmstatus und Fortsetzung des Programms
Arten:
- bedingter (maskierbarer) Interrupt
- unbedingter Interrupt
2.3 Arbeitsspeicher
Speicher-Bausteine
Als Speicherbausteine werden Halbleiterspeicher verwendet. Folgenden Begriffe
dienen zur Spezifizierung eines Speichers:
- a Adreßbreite
- d Wortbreite
- s Speicherkapazität; s = 2a
- tacc Zugriffszeit
- tcyc Zykluszeit
Anschlüsse:
- CS - Chip Select: Leitung(en) zur Bausteinauswahl
- R/W - Write Enable: Festlegung der Datentransportrichtung 1 = Lesen, 0 = Schreiben
- Adreß- und Datenleitungen
Organisationsformen:
- d = 1: bitorganisierter Speicher, z.B. 64K x 1
- d > 1: Nibble (d = 4)-, Byte (d = 8)- oder Wort (d = 8, 16, 32, 64)-organisierter
Speicher
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:
- in Wortrichtung (d = Wortbreite des Mikroprozessors)
- in Bitrichtung (d = 1 oder d < Wortbreite des Mikroprozessors)
- gemischt (Wort- und Bitrichtung)
Bei der Zusammenschaltung in Bitrichtung werden alle Bausteine parallel adressiert.
In allen anderen Fälle gilt:
- Zur Wortadressierung innerhalb des Bausteins dient nur ein Teil der Adresse
- Der Rest der Adresse dient zur Bausteinanauswahl:
- Uncodierte Bausteinauswahl
- Decodierung auf dem Baustein (mehrere CS-Eingänge)
- externe Decodierung (nur 1 CS nötig)
- Kombination externe/interne Decodierung
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, ...)
Bausteine für programmierten E/A-Transfer
Hier erfolgt der Zugriff auf die Peripherie 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:
- Datenrichtung
- Übertragungsgeschwindigkeit
- Übertragungsformat
- Paritätsprüfung
- Art des Interrupt-Signals von der Peripherie
- Interrupt-Maske
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:
- 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.
- 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).
Daneben existieren noch viele weitere E/A-Bausteine. Sie sind i.a. wesentlich komplexer
aufgebaut und bieten zahlreiche Programmierungsmöglichkeiten. Zum Beispiel:
- Interrupt-Controller: Erweiterung der Interruptmöglichkeiten
(Priorisierung, Vektorgenerierung)
- Programmierbare Zähler (Timer, Counter)
Auslösung von Interrupts in regelmäßigen Zeitabständen
Erzeugen von Einzelimpulsen definierter Länge
Erzeugung von Rechteckimpulsen
- spezielle Steuerbausteine
Memory Management, Floppy-Disk, Festplatte, Bildschirm, LC-Display, ...
- Bausteine für DMA-Transfer
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:
- Im einfachsten Fall bestehen sie aus einer oder mehreren einfachen
nicht-intelligenten E/A-Schnittstellen zur rein
hardwaremäßigen Anpassung und Umsetzung. Die gesamte
Steuerung des Datentransfers erfolgt durch die CPU
programmierter E/A-Transfer.
- Komplexere Schnittstellen können den Datentransfer autonom
durchführen. Sie werden von der CPU nur angestoßen und
wickeln den Datentransfer ohne weitere Hilfe der CPU ab
Direkt- Speicher-Zugriff (DMA = Direct Memory Access) ohne Ablauf
eigener Programme.
- Flexiblere und leistungsfähigere Schnittstellen besitzen
einen speziellen E/A-Prozessor, der nach einem Anstoß durch
die CPU unabhängig vom (Haupt-)Prozessor mit eigenem Programm
arbeitet und getrennten Zugriff zum Speicher besitzt.
Steuerung von E/A-Bausteinen
Steuersingnale von der CPU:
- Rücksetzen (Reset, RES)
- Freigabe, Aktivierung (Enable, E, CE)
- Baustein-Auswahl (Chip Select, CS)
- Register-Auswahl (Register Select, RS)
- Datenrichtung (Read/Write, R/W)
Steuersignale von der Peripherie:
- Interruptleitungen (Erzeugung IRQ-Signal für CPU)
- weitere Steuersignale (z.B. Handshakeleitungen bei SIA)
Steuerleitungen vom E/A-Baustein zur CPU:
- Interrupt-Anforderung (Interr. Request, IRQ)
- Weitergabe des IRQ von der Peripherie zur CPU (Maskierungsmöglichkeit)
- Erzeugung eines IRQ-Signals durch E/A-Baustein selbst
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:
- 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).
- 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:
- E/A-Datenregister (EADR)
- E/A-Steuer- und Statusregister (EASR)
- Adreß- und Steuerlogik
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:
- Statussignale von der Peripherie
z. B. Anzeige, dass das Peripheriegerät einen neuen Wert ins
EADR geliefert hat oder bereit ist, den nächsten Wert zu
übernehmen.
- Steuersignale zur Peripherie
z. B. Anzeige, dass der vorhergehende Datenwert gelesen wurde und
die Peripherie einen neuen Wert ins EADR einschreiben kann.
- Steuersignale zur Schnittstelle selbst
z. B. Signale zum Einstellen bestimmter Betriebsmodi bei
programmierbaren Schnittstellen.
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:
- Die Zeit, die das Programm braucht, um einen Eingabewert
zu bearbeiten ist manchmal (oder sogar immer) länger als
die Zeitspanne innerhalb der sich das Eingangssignal ändern
kann
es werden Ereignisse "übersehen".
- Bei "langsamen" Peripheriegeräten ist der
Computer während der Übertragung eines Datenblocks die
meiste Zeit mit Abfragen bschäftigt, die in den meisten
Fällen negativ ausfallen.
2.5 Timer (Zeitgeber)
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:
- Rechteckgenerator: Beim Erreichen des Zählerstandes 0 wird ein Interrupt
erzeugt und automatisch wieder der Startwert geladen. Somit erfolgt ein Interrupt
in regelmäßigen Zeitabständen.
- One-Shot: Nach Erreichen des Zählerstandes 0 wird ein Interrupt
erzeugt und dann bleibt der Timer inaktiv, bis wieder ein Startwert geladen wird.
- Frequenz- oder Periodendauermessung: Der Interrupt erfolgt, wenn die Freqenz
bzw. Periodendauer eines an einem externen Eingang angelegten Signals länger
dauert, als die Timerperiode. Durch Variation des Startwertes kann die Frequenz
bzw. Periodendauer gemessen werden.
- Rechtecksignal mit variablem Tastverhältnis
I und andere ...
Anwendungen:
- Erzeugen von Interrupts in festen Zeitabständen
- Rechteckgenerator mit programmierbarer Frequenz
- Monoflop mit programmierbarer Zeit
- Pulsweiten-Modulation
- "Watch-Dog" (Reseterzeugung, wenn nicht regelmäßig per Software
nachgetriggert wird
automatisches Rücksetzen bei Störungen)
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:
- Voll-Decodierung
Die Adressierung jedes Bausteins wird unter Verwendung aller Adreßleitungen
decodiert. Weitere Bausteine sind problemlos zuschaltbar.
Vorteil: Adreßraum nur soweit nötig gebraucht, Erweiterung problemlos
Nachteil: Mehr Hardware nötig
- Minimaldecodierung:
Es wird nur eine Minimalzahl von Adreßleitungen ausgewertet. Der Speicher und die
E/A-Schnittstellen erscheinen mehrmals unter verschiedenen Adressen.
Vorteil: Minimaler Schaltungsaufwand
Nachteil: Adreßraum wird vollständig verbraucht
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:
- Prozessor 6802 (mit 128 Byte RAM)
- EPROM 2732 als Programmspeicher (4K x 8)
- PIA 6821 als E/A-Baustein
- Adreßraum:
- RAM: $0000 - $007F
- ROM: $F000 - $FFFF
- PIO: $0080 - $0083 (memory mapped I/O)
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 SBus 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
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:
- 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").
- 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.
- 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.
- 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:
- T1: Durchschaltezeit (der Anforderung bis zur Unterbrechungsanmeldung) aufgrund
einer gesetzten Sperre (z.B. auch dann, wenn gerade eine Interrupt-Service-Routine
bearbeitet wird). Diese Zeit kann u.U. recht lang sein!
- T2: Wartezeit bis zur Beendigung des gerade ausgeführten Befehls (maximal
die des längsten vorkommenden Befehls)
- T3: Zeit zum Retten des Programm-Zustandes und Laden des Unterbrechungs-Vektors.
Selbst wenn die Durchschaltung der Anforderung unmittelbar erfolgt (T1 = 0, weil
keine Sperre gesetzt ist), kann die Summe von T2 und T3 für zeitkritische
Echtzeitanforderungen doch noch zu groß sein.
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:
- vektorisierter Interrupt: Es kann der ISR eine beliebige Adresse
zugeordnet werden, welche von der CPU eingelesen wird.
- nicht vektorisierter Interrupt: Der ISR wird eine feste Startadresse zugeordnet.
Copyright © FH München, FB 04, Prof. Jürgen Plate
Letzte Aktualisierung: 16. Apr 2008