Interrupts auf dem Mikroprofessor MPF-1P

  • Ich habe einen MPF-1P mit IOM-MPF



    und PRT-MPF Erweiterungsmodulen. Sehr schönes Teil mit PIO, CTC und 8251 USART. Nur fehlt brauchbare Software dazu. Im ROM des IOM sind Demoprogramme für alle drei Chips, nur nützen die wenig, das CTC Programm stürzt sogar ab...

    Im Manual des IOM wird erwähnt, dass auf dem Printermodul ein Design-Fehler existiert, der verhindert, dass Interrupts funktionieren. Das Signal M1 des Z80 wird bei der Dekodierung der I/O Ports nicht berücksichtigt. Dies führt dazu, dass das Printerboard bei einem Interrupt-Acknowledge Zyklus seine Daten auf den Bus legt und die vom Gerät, das den Interrupt angefordert hat, verfälscht, sofern die ausgeführte Adresse beim Auftreten des Interrupts xxCA oder xxCB (die Portadressen des Printerboards) sind. Die einzige Lösung des Problems ist, entweder die Speisung der Druckerkarte zu unterbrechen oder sämtliche Programmadressen, die mit CA oder CB enden, mit dem Lowbyte des Interrupt-Vektors zu versehen. Etwas aufwändig, aber funktioniert.


    Aber das ist nur die halbe Wahrheit. Den gleichen Fehler haben die Entwickler auch beim IOM gemacht. Hier betrifft es die 8251 USART (standardmässig nicht bestückt, darum wurde es vielleicht nicht beachtet).



    Auch hier fehlt M1 zur Decodierung der I/O Adressen. Für CTC und PIO spielt dies keine Rolle, da diese die Decodierung mit M1 selbst erledigen. Anders beim USART. Der legt frisch-fröhlich seine Registerdaten auf den Bus, sobald ein Interrupt-Ack Zyklus im Adressbereich xx40 - xx60 ausgeführt wird (der 8251 belegt IO-Adressen 60 und 61). Schon wieder ein Crash. Das heisst also, Monitorfunktionen mit laufenden Interrupts sind tabu. Im Anwenderprogramm darf zwischen xx40 und xx60 kein Code sein, der mit Interrupts unterbrochen werden kann. Dies ist übrigens auch der Grund, warum die CTC Demo abstürzt. Nach Verschieben in einen nicht betroffenen Adressbereich funktionierts.


    Ich werde nun versuchen, die wichtigsten Funktionen zum Ablegen im EPROM Printer- und USART sicher zu implementieren.

    Update folgt...

  • Was mich wundert: Die Adressdekodierung ist an der Stelle nicht ganz eindeutig, richtig.

    Aber beim Interrupt Acknowledge der Z80 wird das /RD nicht aktiv. Wieso gibt der 8251 Daten aus?

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)

  • Ich hoffe ich habe den richtigen Schaltplan vom IOM gefunden.


    Kann es eher sein, das während des INTACK keine Daten auf dem Datenbus liegen?

    Kann der 8251 überhaupt INTs auslösen?


    Oder ich hab dich komplett falsch verstanden.

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)

  • Kann es sein, das der PRT-MPF auf IO-Adresse 0xCB (auch) der mögliche Auslöser ist?

    Bei Adr. 0xCB legt der LS367 Daten auf den Datenbus. Unabhängig von M1.

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)

  • Hallo und guten Abend funkenzupfer

    Besten Dank für Deine Reaktionen.


    Zur ersten: Gute Frage. Eigentlich dürfte bei inaktivem /RD vom 8251 nichts auf den Bus kommen. Ich habe das Datenblatt nochmals angeschaut, hier ist das Verhalten von /RD ODER /WR beschrieben, nicht aber wenn beide Signale bei aktivem /CS inaktiv sind, was ja bei einem INTACK Zuklus der Fall ist.

    Möglicherweise ist dies ein für den 8251 verbotener Zustand und er verhält sich undefiniert. Versuche haben jedenfalls ergeben, dass der 8251 für die Abstürze verantwortlich ist. Bei entferntem Chip oder Code im nicht betroffenen Bereich läufts wie erwartet, keine Abstürze.


    Zur zweiten: Keine Daten auf dem Bus würde ich eher ausschliessen. Die Interrupts werden vom CTC und der PIO ausgelöst, der 8251 kann keine Ints erzeugen, die Pins (TxEmpty und RxReady) sind beide nicht angeschlossen. Zudem wäre er inkomatibel zu Z80´s IM2.


    Zur dritten: Ja das trifft zu, und wird im IOM Manual auch so beschrieben. Der Trick mit den NOP´s an Codeadressen xxCA und xxCB hat sich bewährt.


    Ich hab noch das Schema MPF-1P_IOM-Schematics.pdf angehängt, damit wir vom gleichen reden...


    Nochmals vielen Dank

    Tony

  • Zur dritten: Ja das trifft zu, und wird im IOM Manual auch so beschrieben. Der Trick mit den NOP´s an Codeadressen xxCA und xxCB hat sich bewährt.

    Zum vierten ;)

    Auf der IOM gibt bei 0x6C-0x6F noch so einen Bereich, der unabhängig von M1 und RD auf den Datenbus schreibt.

    Aber das hast du ja im ersten Post schon gesagt.



    Und als Workaround verschiebst du den Programmcode, das die Adressen xx6C - xx6F (aus obigem Beispiel) frei bleiben. So kann nie ein INTACK mit den genannten Adressen auf dem Adressbus auftreten.

    Ich glaub' ich hab's verstanden. Tricky.

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)

  • Es ist Zeit für ein Update:


    Der oben erwähnte Trick mit den NOPs an den Codeadressen xxCA und xxCB funktioniert nur bedingt, es passieren zeitweise Abstürze. Ueberspringen der Adressen hingegen funktioniert.


    Trotz der Widrigkeiten mit den ´verbotenen´ Adressen konnte ich es nicht lassen. Ich habe eine kleine Bibliothek erstellt, die ein paar Funktionen, z.T. interruptfähig, zur Verfügung stellt:

    • Initialisieren der IOM Devices USART, CTC und PIO. Die möglichen Betriebsarten sind alle über EQUates vordefiniert. Interrupts müssen ausgeschaltet sein.
    • USART Empfangs- und Sendefunktionen. Es wird nicht auf Bereitschaft gewartet, das ist Aufgabe des Hautprogramms. Der Status wird zurückgegeben.
    • Setzen und Rücksetzen von RTS/DTR.
    • Interrupt Vektortabelle für CTC- und PIO Interrupts.
    • Funktion zum Setzen des Interrupt-Modus und Laden des I-Registers mit dem HiByte der Vektortabelle.
    • Funktion zum Sperren der Interrupts mit Rückgabe, ob die Interrupts bei Aufruf freigegeben waren.
    • Interrupt Handler für alle möglichen Interrupts des IOM Boards. Bei der Initialisierung kann optional für jeden Interrupt eine Callback Adresse definiert werden, die dann bei jedem Interrupt aufgerufen wird. Jeder Handler bedient einen 8-Bit Zähler, woraus das Hauptprogramm sehen kann, ob und wie oft ein Interrupt aufgetreten ist. Das Hauptprogramm löscht diesen Zähler nach Bedarf.
    • Einlesen des DIP-Schalters auf dem IOM mit optionaler Vorgabe einer Maske. Die Funktion gibt dann über das CY zurück, ob sich an den maskierten Bits etwas geändert hat.
    • Konvertierungen binär <-> HEX ASCII mit Angabe der Anzahl Stellen (1..4). Der Monitor kann das auch, aber nicht mit laufenden Interrupts.
    • Konvertierung nach Grossbuchstaben
    • Verifizierung, ob ein Zeichen darstell- und druckbar ist. Falls nicht, Rückgabe eines Space.
    • Ersatz für die Monitor-Beeper Funktionen, die nicht interruptfest sind. Dabei sind ein Beep, der unabhängig von der momentanen Systemeinstellung beept, eine Funktion, die nur beept, wenn vom System freigegeben, eine dritte, bei der die Parameter definiert werden können.
    • Statische Ausgabe gleicher Zeichen an beliebiger Position auf dem Display (analog der Tape-Load Funktion des Monitors). Kann z.B. zur Fortschrittsanzeige während zeitkritischen Prozessen verwendet werden. Muss nicht zyklisch aufgerufen werden.
    • Funktion zur Aktualisierung des Display und Lesen der Tastatur (analog der SCAN1 Funktion des Monitors) mit Uebergabe der ASCII Bufferadresse. CTRL-G ändert den Status des System-Beepers. Wartet nicht auf Eingabe. Muss zyklisch aufgerufen werden, damit das Display sichtbar bleibt.
    • Textzeilen-Editor mit wählbarer Bufferadresse, 20 Zeichen ohne Scrolling. Initialisieren des Buffers wählbar. Blinkender Cursor, mit den Pfeiltasten verschiebbar, wobei Pfeil-auf an den Anfang, Pfeil-ab ans Ende, nach letzter Stelle, die nicht Space ist, bewegt. Ctrl-U erlaubt das Wiederherstellen des Buffers, wie er bei Aufruf war. Ctrl-G ändert des Status des System-Beepers. Da die Funktion auf eine Eingabe wartet, kann von einer Interrupt-Funktion eine Speicherstelle beschrieben werden, die den Editor zwangsweise beendet.
    • Empfangsfunktion für Intel-HEX Dateien mit der USART. Damit können Programme für den MPF auf Fremdsystemen entwickelt werden (wie z.B. diese Library). Prüft die Zeilen-Checksummen und verifiziert die geschriebenen Daten. Die Uebertragungsparameter sind 1200,N,8,1. Diese wurde gewählt, damit ein Uebertragen ohne Handshake möglich ist (wie z.B. CP/M´s PIP).

    Im Anhang ist nebst den Sourcen ein ROM Image für ein 2732 EPROM, das in den normalerweise freien Sockel U6 des PRT-MPF, Adresse 7000H, passt. Darin sind das Empfangsprogramm, Start mit G 7000, und die Library Routinen ab 7800H.


    Damit die Interrupts mit dem Testprogramm ´sichtbar´ werden, die Verdrahtung des IOM. Die Ports A0-A3 des PIO werden von den Interrupt Callbacks angesteuert, B0-B3 vom Hauptprogramm. Dabei ist PB7 ein Eingang, der bei positiver Flanke einen Interrupt auslöst. Deshalb ist dieser mit dem Ausgang PB0 verbunden.



    Viel Spass, mindestens soviel, wie das Entwickeln gemacht hat...

    Tony

  • Der oben erwähnte Trick mit den NOPs an den Codeadressen xxCA und xxCB funktioniert nur bedingt,

    Das ist eigentlich klar. Der PC darf nie xxCA oder xxCB werden. Bei einem IntAck liegt der PC auf dem Bus.



    Kannst du die Beschreibung des Workarounds mal posten? Würde mich mal interessieren.


    Ich überlege gerade.

    Genau genommen darf kein M1 Zyklus, daß auch ein IntAck sein darf, auf der Adressen xxCA, xxCB ausgeführt werden.

    D.h. wenn bei Adresse xxC9 z.B. ein Call mit 3 Bytes beginnt, oder ein JP xxCC ;) wird dieser Befehl bis zum Ende abgearbeitet und es tritt auf xxCA, xxCB kein M1-Zyklus bzw IntAck auf. Das sollte auch bei anderen 3 Byte Befehlen wie LD HL,nnnn funktionieren.


    Bei den 2 Byte Opcodes sollte das auch funktionieren.


    Vielleicht helfen dir diese Überlegungen die Code-Einschränkungen etwas kleiner zu halten als bisher.



    Und deine Lib find ich schon sehr umfangreich.

    Echt cool ! :thumbup:

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)

  • Danke Dir für die Vorschläge. Du liegst genau richtig. Nur die OpCode Adressen düfen nicht in den I/O Bereichen liegen, bei den Operanden spielt´s keine Rolle. Ich hab´s auch so implenentiert. Hier Ausschnitte aus dem List-File:

    Je nachdem, welche Instuktionen vor und an den betroffenen Adressen liegen, müssen die DS nn angepasst werden. Natürlich müssen nach jeder Aenderung im Code, sofern sich die Codelänge ändert, die Skips neu getestet und ggf geändert werden. Etwas mühsam, aber es funktioniert.