Donnerstag, 24. Februar 2011

Interrupts

Interrupts sind ne feine Sache. Wenn ein Computer Peripheriegeräte wie Tastatur, Maus, UART u.Ä. verwendet, müsste er theoretisch zyklisch diese Geräte abfragen, ob sie neue Daten zur Verfügung haben. Wenn man also schnell auf einen Tastendruck reagieren will, müsste man entsprechend häufig die Tastatur abfragen, um die Reaktionszeit klein zu halten. Dieses ständige Abfragen nennt man Polling. Die Zeit, die für's Polling draufgeht, steht dann nicht mehr für das eigentlich laufende Programm zur Verfügung. Deswegen nimmt man (meistens) ein anderes Prinzip, nämlich Interrupts. Der Z80 hat einen Interrupt-Pin (eigentlich zwei, aber ich benutze nur einen). Der liegt im Normalfall auf High-Pegel. Wird nun eine Taste gedrückt, so wird von der Tastatur der High-Pegel auf low gezogen. Der Prozessor merkt dadurch, dass etwas passiert ist, um das er sich kümmern sollte. Dann kann er die Peripherie "auslesen", um festzustellen, was passiert ist. Er liest also die Tastatur nur dann aus, wenn wirklich eine Taste gedrückt wurde.
Der Z80 hat drei Interrupt-Modi. Modus 0 wurde aus Kompatibilitätsgründen zum Intel 8080 beibehalten. Löst das Gerät einen Interrupt aus, so bekommt es die Möglichkeit, eine Instruktion auf den Datenbus zu legen, die der Prozessor dann ausführt. Dies ist meistens der RST-Befehl, mit dem man ich glaube acht verschiedene (aber a priori festgelegte) Stellen in der Speicherseite 0 anspringen kann.
Im Modus 1 springt der Prozessor im Interruptfall pauschal zu 0x38. Und Modus 2 ist der flexibelste Modus: Der Programmierer legt im Speicher eine Tabelle mit Interruptvektoren an. In das Register I lädt er die Nummer der Speicherseite, in der sich die Tabelle befindet. Beim Interrupt legt nun das Gerät eine Nummer auf dem Datenbus, die dem Eintrag in der Tabelle entspricht. Der Z80 liest nun diesen Interruptvektor ein und springt an diese Adresse. Dort befindet sich dann die entsprechende Routine, die bspw. die Tastatur ausliest. Auf diese Weise lassen sich 128 verschiedene Interrupt-Routinen anspringen.
Soviel zur Theorie. Ich wollte ja eigentlich den Modus 2 benutzen, doch ich habe nen Layoutfehler drauf. Das wird so nicht klappen, weswegen ich erstmal mit Modus 1 Vorlieb nehme. Nur ein Interrupt ist besser als gar keiner :-) Das Problem ist folgendes: Der Interrupt wird ausgelöst. Der Prozessor weiß jedoch erstmal gar nicht, wer denn die Interruptleitung runtergezogen hat, er sieht nur, dass sie low ist. Deswegen löst er einen IORequest parallel zu einem M1 Zyklus aus. Dies signalisiert dem Interrupt-Gerät, nun die Nummer des Interruptvektors auf den Datenbus zu legen. Ich habe nicht bedacht, dass er ja gar keine Geräteadresse auf den Datenbus legt, weswegen kein entsprechendes Chipselect ausgelöst wird.
Ich hätte sogar alle nötigen Logikgatter auf der IOBoard-Platine noch frei um das zu fixen, jedoch wäre das mit einem SMD-Beinchenbiegen und rumpfuschen verbunden, das ist mir erstmal zu heikel. Hab kein Bock, mir wieder ein Pad abzureissen wie bei der Main-Platine. Interrupt-Modus 1 reicht mir erstmal :-)

2 Kommentare:

  1. Tolles Projekt! Bei mir im Keller wartet auch noch ein Z80 endlich mal verbaut zu werden. Die Kombination von Microcontroller und Z80 finde ich gelungen. Mit PICs hab ich es nicht so, bei mir wuerde ein AVR hier reinkommen. Aber das ist Geschmackssache. Bitte weiterposten!

    AntwortenLöschen
  2. Hallo Christoph,
    dann hilft alles nichts, beginne mit Deinem Z80-Projekt und schreibe in einem Blog darüber! ;-)
    Ich arbeite gerade an einer Platine um SD-Karten an mein Z80-System anzubinden, denn für CP/M ist Massenspeicher nötig.
    Bald gibt es da wieder was zu posten, sollte die Platine denn mal funktionieren...

    AntwortenLöschen