intel 8049 / MCS-48 Hardware-Debugger & Monitor
Vor einigen Monaten fiel mir wieder einmal die Stange mit den 8049-µCs in die Hand und im Lauf der Zeit - unterstützt durch gelegentliche Lektüre im "intel 8-Bit Embedded Controllers"-Handbuch von 1990 - wuchs doch eine gewisse Neugier, ob diesem wirklich archaischen Mikrocontroller überhaupt noch Lebenszeichen zu entlocken sein würden.
Zum ersten Ziel - und es war zu diesem Zeitpunkt kaum absehbar, ob es nicht auch das letzte Ziel werden würde - wurde eine Möglichkeit, irgendwie ein RAM mit einem Programm vom steuernden Personal Computer aus zu laden, das dann der 8049 eigenständig, ohne Möglichkeit von Aussen einzugreifen, ausführt. Wenigstens keine (E)EPROMs mehr (wo ist eigentlich das vor vielen Jahren zuletzt genutzte EPROM-Programmiergerät?).
Erstmal wurde nur eine Stromversorgung angeschlossen und als einzige On-Chip-Hardware der Oszillator bei *RESET=L und EA=H in Betrieb genommen. Der 8049 µC generiert sogar im Reset-Zustand (*RESET=L) Signale an seinen ALE- und *PSEN-Anschlüssen und gibt kontinuierlich die Adresse 0x000 auf BUS und P2 aus : leider sehr ungünstig, um ein RAM vom 8049 isoliert während des Reset-Zustands mit Daten zu laden - wie ich mir das ursprünglich als einfachste Möglichkeit vorgestellt hatte (später entdeckte ich, dass dieses Verhalten in einem leicht zu übersehenden Satz u.a. im "intel 8-Bit Embedded Controllers"-Handbuch von 1990 beschrieben ist : "[...]ALE and PSEN (if EA = 1) are active while in Reset." Quelle: "intel 8-Bit Embedded Controllers"-Handbuch (1990); Kap."Single Component MCS48-System" / "2.12 Reset"; S.1-10).
Bild: *PSEN und ALE bei *RESET=low und EA=high
Die einfachste Möglichkeit für einen weiteren Test ist eine "NOP-Schleife" ("No OPeration") : die CPU findet nur "NOP"-Anweisungen in ihrem Adressraum vor. Werden diese "NOP"-Befehle durch die CPU ausgeführt, kann das Hochzählen des Befehlszählers (PC/Program Counter), der stets auf die Programmspeicher-Adresse des nächsten auszuführenden Befehls zeigt, an den externen Adress-Signalen beobachtet werden.
Funktionieren müssen dafür :
Um auch dafür kein EPROM o.ä. programmieren zu müssen und da es ja nur um den Opcode für "NOP" (0x00) geht, wurde ein 74HC541 (Octal 3-State Buffer) als festverdrahteter "Befehlsspeicher" eingesetzt, der während *PSEN=low den Opcode für "NOP" (0x00) auf die BUS-Leitungen legt.
Statt des von intel vorgeschlagenen "Transparent Latch" (74LS373) für das Zwischenspeichern der unteren 8 Adressbits von BUS wurde, wie auch für das untere Nibble (P2.0 bis P2.3) von P2, ein flankengesteuertes D-FlipFlop mit Tri-State Ausgängen vorgesehen, da sich so ein wesentlich störärmerer Adressbus erzielen lässt.
Da die Adressleitungen des RAM während des Ladens mit Daten über das Interface zwischen Personal Computer und der Debugger-/Monitor-Hardware vom 8049 isoliert werden müssen, waren die Tri-State-Ausgänge dieser D-FFs natürlich auch sehr willkommen.
Und weil der bidirektionale Datenbus des RAMs ebenfalls vom 8049 getrennt werden können muss, kam dort ein "Bi-Directional 8-Bit Bus-Transceiver", 74HC245, als Trennstelle auch gleich beim NOP-Schleifen-Test zum Einsatz. *PSEN, *RD, *WR, ALE wurden provisorisch gepuffert, so dass auch bei größeren Unfällen auf diesen Leitungen dem 8049 möglichst kein Schaden drohte.
Bild: Ausführen der NOP-Schleife (D0...D7, P2.0...P2.3, ALE, *PSEN, *RESET)
Nachdem diese Trockenübungen ohne echten Programmspeicher zur vollen Zufriedenheit verliefen, kam der Gedanke auf, das zukünftig als externen Programmspeicher eingesetzte RAM auch als externen Datenspeicher, der über die "MOVX"-Befehle und die "*RD"- und "*WR"-Steuerleitungen des Mikrocontrollers beschrieben und gelesen werden kann, zu nutzen. Dafür werden mit Hilfe eines UND-Gatters die beiden Signale "*PSEN" und "*RD" zusammengeführt (es entsteht eine ODER-Verknüpfung der beiden Low-aktiven Signale zum ebenfalls Low-aktiven "*OE"-Signal des RAMs) und das "*PSEN"-Signal zur Bildung des Adress-Signals A16 herangezogen. Bei einem Zugriff auf den Programmspeicher ist dieses "L", bei einem Zugriff auf den Datenspeicher ist es "H", sodass sich der externe Programmspeicher von der physikalischen RAM-Adresse 0x00000 bis Adresse 0x0FFFF und der externe Datenspeicher von der physikalischen RAM-Adresse 0x10000 bis Adresse 0x1FFFF (mit Debugger bis 0x1FDFF) erstreckt - wenn nicht der später beschriebene "memory mapped I/O"-Bereich eingeblendet wird. Der 8049 kann mit den maximal 12 unter seiner Kontrolle stehenden Adressleitungen 4kByte adressieren, die fehlenden Adress-Bits werden durch zwei zusätzliche 4Bit-D-FlipFlops bereitgestellt, die das Ansprechen von jeweils bis zu 16 4kB-Bänken - unabhängig voneinander für Programm- und Datenspeicherbereich unter Softwarekontrolle auszuwählen - ermöglicht. Die Hardware zur Bereitstellung der zusätzlichen Adress-Bits wird mit Hilfe des in der Regel ungenutzten "PROG"-Signals und der entsprechenden, im Befehlssatz bereits vorhandenen Befehle vom 8049 angesteuert (siehe "3.10.0 DeMon48_128k Speicherorganisation / MMU").
Als Mikrocontroller zur Steuerung des DeMon48_128k-Systems und als Interface zum Personal Computer fiel die Wahl auf einen betagten, ebenfalls noch als Restbestände hier vorhandenen PIC16F874. Die Hardware wurde zunächst, um Signale am PIC-Mikrocontroller und Verbindungen beim Aufbau auf dem Steckbrett ("Solderless Breadboard") zu sparen, auf Schieberegistern zur Parallel- zu Seriell- bzw. Seriell- zu Parallel-Wandlung basierend (74HC165, 74HC595) geplant.
Die erste Test-Firmware für den PIC16F874 hatte folgende Funktion :
Es sollten sich nach Start also die gleichen Signale auf den Adress- und Datenleitungen des 8049 messen lassen, wie beim Test mit dem 74HC541 als "Programmspeicher", nur dass jetzt wirklich von unterschiedlichen Adressen des RAMs gelesen wird.
Da sich das gewünschte Resultat auf Anhieb einstellte, kam ein weiteres Testprogramm zur Ausführung durch den 8049 µC zum Einsatz. Es beschreibt eine 256Byte-Seite im Datenbereich des RAM mit dem Komplement der jeweiligen Adresse, also Adresse 0x00 mit 0xFF, Adresse 0x01 mit 0xFE, Adresse 0x02 mit 0xFD bis zur Adresse 0xFF und dem geschriebenen Wert 0x00 :
Es sollte damit vor allem die Trennung zwischen Programm- und Datenbereichen im RAM durch Heranziehen von *PSEN als zusätzliche Adressleitung getestet werden. Sollte diese Trennung nicht funktionieren, würde sich das Programm selbst überschreiben, was u.a. durch das Ausbleiben der Low-Impulse auf der *WR-Leitung nachweisbar wäre, sobald der "MOVX @R0,A" Befehl überschrieben ist. Auch dieser Test wurde unspektakulär bestanden.
Bild: 256Byte Page Write (D0...D7, P2.0...P2.3, ALE, *PSEN, *RD, *WR)
Bild: 256Byte Page Write (D0...D7, P2.0...P2.3, ALE, *PSEN, *RD, *WR) (Fortsetzung)
Im nächsten Schritt wurde die Hardware durch die von intel beschriebene Einzelschritt-Schaltung um das 74HC74 D-FlipFlop ergänzt.
Die Einzelschritt-Schaltung (74HC74, 74HC00) ist bei H-Pegel am *SET-Eingang des dem *SS-Eingang des 8049 nächstgelegenen D-FFs aktiv. Liegt hier L-Pegel an, wird der Ausgang des D-FFs ständig auf H-Pegel
gesetzt. Durch den H-Pegel am *SET-Eingang kann der Ausgang des D-FFs durch L-Pegel des invertierten ALE-Signals ("Address Latch Enable") des 8049 auf L-Pegel gesetzt werden, wodurch der *SS Eingang des 8049
aktiviert wird.
Der 8049 beendet nun die Ausführung des gerade laufenden Befehls (im Fall von Befehlen, die 2 Befehlszyklen zur Ausführung benötigen, wird das Ende des zweiten Befehlszyklus abgewartet) und
signalisiert den aktiven Einzelschritt-Modus durch H-Pegel an ALE. Während dieses Zustands, für den es seitens des 8049 keine zeitliche Beschränkung gibt, wird auf BUS und der unteren Hälfte von P2 die
Adresse des nächsten auszuführenden Befehls ausgegeben.
Um in einem Programm den nächsten Befehl auszuführen, wird durch einen L-zu-H-Wechsel am Takteingang des D-FFs der ständig am D-Eingang des D-FFs anliegende H-Pegel in das FF geladen und erscheint an dessen Ausgang,
der mit *SS des 8049 verbunden ist. Dadurch wird die Einzelschritt-Logik im 8049 freigegeben, der nächste Befehl wird adressiert, durch den beim Zwischenspeichern der unteren 8-Bit der Adress-Signale entstehenden
L-Pegel an ALE des 8049 wird das D-FF wieder zurückgesetzt, *SS wird auf L-Pegel gesetzt und das System befindet sich am Ende wieder in der Wartephase des Einzelschritt-Modus.
Das Verlassen des Einzelschrittmodus kann jederzeit durch dauerhaften L-Pegel am *SET-Eingang des D-FFs erzwungen werden.
Bild: Single-Step Hardware
Bild: Single-Step Aktivierung durch *S=H des D-FFs (letzter Befehl besteht aus 2 ALE-Zyklen)
Bild: Ausführen einzelner Befehle (1&2 Zyklen) durch Impulse am CLK-Eingang des D-FFs
Zu diesem Zeitpunkt war erreicht, dass ein Programm in das RAM geladen und vom 8049 entweder mit der durch die Oszillatorfrequenz vorgegebenen Geschwindigkeit oder Befehl für Befehl mit Hilfe des Einzelschritt-Modus der vom Anwender-PC via Debug-Mikrocontroller gesteuert wird. Wurde ein Schritt ausgeführt, signalisiert der Debug-µC an den steuernden Personal Computer die auf den entsprechenden 8049-BUS- und -P2-Leitungen anliegende Adresse des nächsten, noch nicht ausgeführten Befehls, so dass die Ausführung des Programms durch den Anwender über die sich ändernde Adressinformation beobachtet werden konnte.
An ein Überschreiten der internen 2kB-Programmspeicherbank-Grenze durch "SEL MBx"-Befehle, an eine Nutzung des Timers-/Counters oder an Interrupts war zu diesem Zeitpunkt allerdings noch überhaupt nicht zu denken.
Um die Codeausführung bei Nutzung der Soft-Breakpoints zu beschleunigen, wurde die gesamte Hardware neugestaltet und von seriellem auf parallelen Austausch zwischen PIC-Mikrocontroller und restlicher Hardware umgestellt. Die Einzelschritt-Ausführung mit aktivierten Soft-Breakpoints funktionierte nun etwa 100% schneller als mit der seriellen Lösung.
Parallel dazu lauerte noch eine Besonderheit des 8049 : Das "SEL MBx"-Problem.
Die Mitglieder der MCS48-Familie unterstützen einen bis zu 12 Bit breiten Adressbus (A0 bis A11), so dass maximal 4kByte adressiert werden können. Allerdings sind diese 4 kByte in 2 Bänke à 2 kByte
aufgeteilt, und nur innerhalb dieser 2 kB großen Speicherbänke kann durch "JMP"- und "CALL"-Befehle linear, also "am Stück", adressiert werden.
Zum Wechsel zwischen diesen Speicherbänken gibt es im MCS48-Befehlssatz die Befehle "SEL MB0" (Auswahl der Speicherbank 0 : Adressbereich 0x000 bis 0x7FF (0 bis 2047 dezimal)) und "SEL MB1"
(Auswahl der Speicherbank 1 : Adressbereich 0x800 bis 0xFFF (2048 bis 4095 dezimal)). Wird einer dieser Befehle ausgeführt, wird im 8049 ein Flipflop, dessen offizielle Bezeichnung "DBF : Memory Bank Flip-Flop"
lautet (intel 8-Bit Embedded Controllers Handbook 1990; Kap. "MCS(R)-48 Instruction Set, Symbols and Abbreviations Used"; S.3-7), für das 12. Bit (A11) des Programmzählers (PC) durch "SEL MB1" gesetzt oder durch
"SEL MB0" zurückgesetzt. Sobald ein unbedingter Sprung per "JMP"- oder "CALL"-Befehl ausgeführt wird, werden die unteren 11 Bits (A0 bis A10) des Programmzählers mit der im Sprungbefehl angegebenen Zieladresse geladen
und als 12. Bit des Programmzählers (A11) wird der Zustand des oben genannten Vorbereitungsflipflops ("DBF"/"Memory Bank FlipFlop"/"MB-FlipFlop"/"MB-FF") übernommen.
Nach Ausführen des folgenden Codes hat der Programmzähler ("PC") den Wert 0x800 (Bit11 = 1) :
Wird danach Folgendes ausgeführt, wird der Programmzähler auf 0x000 (Bit11 = 0) gesetzt :
Es kann natürlich sein, dass der Aufruf der DeMon48-Monitor-Software nach einem SEL MBx-Befehl, aber vor dem Ausführen eines "JMP" oder "CALL"-Befehls erfolgt. Da in der Monitor-Software auch unbedingte Sprünge ausgeführt werden, würde ohne besondere Maßnahmen nach dem Verlassen der Monitor-Software Chaos herrschen, da die Speicherbank bereits durch das Ausführen der Monitor-Software gewechselt wurde und das MB-Flipflop nicht wie gewünscht beim nächsten "JMP"- oder "CALL"-Befehl wirksam ist. Verschärft wird das Problem noch durch die Tatsache, dass zwischen "SEL MB0"/"SEL MB1" und "JMP" oder "CALL" mehrere Befehle stehen können, wie z.B.:
Es ist also nicht ausreichend, nur dafür zu sorgen, dass die Programmausführung in der vor dem Aufruf der Monitor-Software gewählten Speicherbank fortgesetzt wird, da dann in o.g. Beispiel der Befehl "JMP 00A" zur Adresse 0x00A und nicht, wie beabsichtigt und ohne Monitor-Software vom 8049 auch ausgeführt, zur Adresse 0x80A springt. Es muss beim Beenden der Monitor-Software unbedingt neben Bit0 bis Bit11 des Programmzählers (PC) auch der Zustand des MB-Flipflops im Moment des Aufrufs der Monitor-Software wiederhergestellt werden.
Bild: Prinzipdarstellung der internen Logik zur Erzeugung des 12. Adress-Bits, PC.11
Bild: Ausführen des "SEL MB1"-Befehls (0xF5) und Wirkung auf P2.3 nach "JMP 000" (0x04,0x00)
Eine weitere Besonderheit ergibt sich durch die Bankumschaltung per "SEL MBx"-Befehlen im Zusammenhang mit Interrupts. Durch das Auslösen eines Hardware-Interrupts werden zwar alle Programmspeicher-Zugriffe auf die Speicherbank 0 (0x000...0x7FF) begrenzt, der Zustand des MB-FlipFlops bleibt jedoch erhalten.
Besondere Vorsicht ist übrigens bei µCs der MCS-48-Familie geboten, wenn ein Bankwechsel im Zusammenhang mit einem Unterprogramm-Aufruf per "CALL" stattfindet. Da alle 12 Adress-Bits auf dem Stack gespeichert und durch den Rücksprungbefehl "RET" wiederhergestellt werden, ist der Inhalt des Programmzählers (PC) zwar danach wieder korrekt, jedoch wird das MB-Flipflop durch "RET" nicht beeinflusst. Das kann zu unerwarteten Ergebnissen führen :
Tatsächlich wird der letzte Sprungbefehl "JMP 010" den Programmzähler auf 0x810 setzen, da das MB-Flipflop noch gesetzt ist !
("[...]Since all twelve bits of the program counter including bit (11) are stored in the stack when a Call is executed, the user may jump to subroutines across the 2K boundary and the proper bank will be restored upon return. However, the bank switch flipflop will not be altered on return." Quelle: "intel MCS-48 Family of Single Chip Microcomputers User's Manual" (1980); Kap. "3.1.2 Extended Program Memory Addressing (Beyond 2K)" / "Program Memory Bank Switch"; S. 3-2).
Siehe auch "6.6.0 Schaltfläche 'AS' " zur Bankwechsel-Automatik des AS-Macroassemblers.
Eine weitere Auswirkung des eigentlich nur 11 Bit breiten Programmzählers (PC) ist, dass, im Fall des Überlaufs des Programmzählers, auf Adresse 0x7FF Adresse 0x000 folgt und entsprechend auf Adresse 0xFFF Adresse 0x800 folgt. Bedingte Sprungbefehle speichern nur eine 8-Bit Adresse im entsprechenden Befehl und in der Regel muss das Ziel innerhalb derselben 256-Byte-Page liegen. Es gibt, wie könnte es anders sein, einen Sonderfall, wenn der Sprungbefehl in der höchsten Adresse einer 256-Byte-Page liegt : dann liegt das Ziel durch das Inkrementieren des Programmzählers während S2 (1. Befehls-Zyklus) oder S3 (2. Befehls-Zyklus) in der nächsten 256-Byte-Page.
Der Timer-/Counter-Interrupt ist eine weitere "liebenswerten Eigenheit" der daran nicht armen MCS48-Mikrocontroller (ursprünglich wollte ich mich sogar auf den Ratschlag beschränken, Programme, die Hardware-Interrupts des 8049 nutzen, nicht im Einzelschritt-Modus auszuführen - aber das wäre doch sehr unbefriedigend).
Zum Timer-/Counter-Interrupt in Mikrocontrollern der intel MCS-48-Familie schrieb 1979 John F. Wakerly in "0018-9162179/0020-0022$00.75 IEEE COMPUTER February 1979; 'The Intel MCS-48 Microcomputer Family : A Critique' " : "[...]At the time of this writing, the T1 interrupt input is generally useless for counting or timing asynchronous external events, because the current chip features a poorly designed synchronizer[...]". Zusätzlich zu dem dort beschriebenen Problem, dass zu zählende Ereignisse zum Teil nicht erkannt werden, existieren offenbar Schwierigkeiten bei durch den Timer/Counter ausgelösten Interrupts, da zum Teil anliegende Timer-/Counter-Interrupts erst nach einigen Maschinenzyklen verarbeitet werden und diese Latenz auch von der Art der Codeausführung (beispielsweise Soft-/Hardware-Breakpoint) abhängig ist.
Um den zur Verfügung stehenden, 128kB umfassenden Speicherplatz im statischen RAM des DeMon48_128k-Systems vollständig nutzen zu können, reichen die vom 8049-Adresszähler (PC) und MB-FF
gelieferten 12 Bit Adressinformationen offensichtlich nicht aus (2^12 = 4096dez.).
Daher werden von 2 74HC173 4fach D-FlipFlops unabhängig voneinander 4 Bit für Programmspeicherzugriffe und 4 Bit für Datenspeicherzugriffe als Adress-Signale bereitgestellt, die das sonst nur für den Betrieb der heute
eher obsoleten 8243-Portexpander (16 zusätzliche I/O-Leitungen in einem großen (600mil) 24pol.-DIL Gehäuse) benötigte "PROG"-Signal nutzen, um den gewünschten Zustand der zusätzlichen 2x 4 Adressleitungen softwaregesteuert
zu übernehmen.
Die 17. Adressleitung A16 wird durch die MMU (Memory Management Unit) in Abhängigkeit der aktuellen Speicherkonfiguration (siehe: "5.0.0 Speicherkonfigurationen") bereitgestellt.
Da die Erzeugung der zusätzlichen Adress-Bits unter voller Kontrolle eines auf dem 8049 ablaufenden Anwender-Programms erfolgt, können tatsächlich Programme erstellt werden, die bis zu 16 4kB-Bänke (=64kB) des Programm- und bis zu 16 4kB-Bänke (=64kB) des Daten-Speicherbereichs nutzen (der Debugger belegt 512 Byte im RAM).
Die Auswahl der aktiven Programmspeicher-Bank erfolgt über das "PBR" (Program Bank Register), die Auswahl der aktiven Datenspeicher-Bank erfolgt über das "DBR" (Data Bank Register).
Bild: Zugriff auf das DBR via PROG und Wirkung auf A12...A15
Bei einem Wechsel der Programmspeicherbank können aufgrund der MMU-Hardware alle 16 Adressbits gleichzeitig beeinflusst werden, so dass zum Beispiel ein Sprung von 0x08E7 nach 0x53F0 durchgeführt wird :
Der "SEL MBx"-Befehl zu Beginn der Sequenz ist in anderen Fällen optional, aber die Reihenfolge "MOVD/ORLD" gefolgt von einem Befehl zur Beeinflussung des Befehlszählers ist unbedingt einzuhalten, andere Befehle dürfen keinesfalls auf "MOVD/ORLD" folgen !
Die MMU unterstützt Unterprogrammaufrufe per "CALL" über Bankgrenzen hinweg, allerdings muss die Bank, zu der mit "RET" zurückgekehrt werden soll, beispielsweise in einem Register hinterlegt werden :
Bild: Wechsel von Programmspeicherbank 7 zu Bank 8
Soll eine Hardware, die einen oder mehrere 8243-Portexpander nutzt, mit Hilfe des Debuggers getestet werden, kann die Erzeugung der zusätzlichen Adressbits durch das "PROG"-Signal mit einem Jumper abgeschaltet werden (siehe "5.0.0 Speicherkonfigurationen"). Das System verhält sich dann wie ein 8049 mit 4kB Programm- und 3,75kB bis 4kB (abhängig davon, ob noch ein I/O-Bereich eingeblendet wird) Datenspeicher und das "PROG"-Signal ist zur Ansteuerung der 8243-Portexpander frei.
Über die MMU kann erzwungen werden, dass alle Speicherzugriffe des 8049 mit A16=low erfolgen, unabhängig davon, ob es sich aus Sicht des 8049 um Programm- oder Daten-Speicherzugriffe handelt.
Dafür wird über "ORLD Pp,A"-Befehle das Signal DA16 (Data Address 16) auf "Low" gesetzt. Damit wird etwas normalerweise Unmögliches erreicht, nämlich dass der 8049 seinen eigenen
Programm-Speicherbereich unter Softwarekontrolle beschreiben kann. Das ermöglicht später unter anderem das Laden von Programmen durch Software, die auf dem 8049 selbst läuft.
Natürlich kann DA16 auch wieder durch geeignete Softwarekommandos auf "High" gesetzt werden, so dass bspw. erst ein Programm mit DA16=low geladen werden kann und dann während dessen Ausführung durch DA16=high
wieder 64kB als Programmspeicher und zusätzlich bis zu 64kB als Datenspeicher zur Verfügung stehen.
Ausserdem ist durch diese Umschaltmöglichkeit aus der nativen Harvard-Architektur der MCS48-µCs ein echter Harvard-/von-Neumann-Architektur-Zwitter entstanden. Es besitzt eine von-Neumann-Architektur mit einem für Programm und Daten gemeinsam genutzten Speicher, wenn DA16=Low und eine Harvard-Architektur mit zwei logisch getrennten Speichern für Programm und Daten, wenn DA16=High.
Für zukünftige Hardwareerweiterungen können zusätzlich an die mit Hilfe des "PROG"-Signals realisierte Schnittstelle 2 4Bit "Expansion Registers", 2 zusätzliche 4Bit D-FlipFlops, angeschlossen werden.
DA16 = H, A16 = normal :
MOVD P4,A | Load Program Bank Register |
MOVD P5,A | Load Data Bank Register |
MOVD P6,A | Load Expansion Register #0 |
MOVD P7,A | Load Expansion Register #1 |
DA16 = L, A16 = forced low :
ORLD P4,A | Load Program Bank Register |
ORLD P5,A | Load Data Bank Register |
ORLD P6,A | Load Expansion Register #0 |
ORLD P7,A | Load Expansion Register #1 |
Zugriff auf Programmspeicher :
A16 | A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MM16 | PBR.3 | PBR.2 | PBR.1 | PBR.0 | PC.11 | PC.10 | PC.9 | PC.8 | PC.7 | PC.6 | PC.5 | PC.4 | PC.3 | PC.2 | PC.1 | PC.0 |
Zugriff auf Datenspeicher und I/O :
A16 | A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MM16 | DBR.3 | DBR.2 | DBR.1 | DBR.0 | P2.3 | P2.2 | P2.1 | P2.0 | Ri.7 | Ri.6 | Ri.5 | Ri.4 | Ri.3 | Ri.2 | Ri.1 | Ri.0 |
Zugriff auf die Programm- und Datenspeicher des Debuggers :
A16 | A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
"1" | "1" | "1" | "1" | "1" | "1" | "1" | "1" | MM8 | PC.7 | PC.6 | PC.5 | PC.4 | PC.3 | PC.2 | PC.1 | PC.0 |
Ausführen des Befehls in Adresse 0x1FE09 im Debug-Programmspeicher :
A16 | A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
"1" | "1" | "1" | "1" | "1" | "1" | "1" | "1" | MM8 | "0" | "0" | "0" | "0" | "1" | "0" | "0" | "1" |
Signal | Funktion |
---|---|
MM16 | A16 Ausgang der MMU |
PBR | Program Bank Register |
DBR | Data Bank Register |
PC | Program Counter |
P2 | Niederwertige Bits (0...3) der auf Port2 geschriebenen I/O Information |
Ri | Inhalt des zur Adressierung in "MOVX"-Befehlen genutzten Indexregisters (R0, R1) |
MM8 | A8 Ausgang der MMU |
"1" | Wird vom Debug-µC auf logisch "1" (+5V = H) gehalten |
"0" | Wird vom Debug-µC auf logisch "0" (0V = L) gehalten |
Adressraum der Grundkonfiguration (siehe auch "5.0.0 Speicherkonfigurationen"):
Start (h) | Ende (h) | Bezeichnung |
---|---|---|
00000 | 0FFFF | 8049 Programmspeicher |
10000 | 1FCFF | 8049 Datenspeicher (extern) |
1FD00 | 1FDFF | Memory Mapped I/O |
1FE00 | 1FEFF | Debug Programmspeicher |
1FF00 | 1FFFF | Debug Datenspeicher |
Mit Hilfe eines "8-Bit Equality Comparator" 74HC688 wird aus den Adress-Signalen A8 bis A16 das Signal IO/*M gewonnen, das das Einblenden von 256 I/O-Adressen in den Adressraum für den externen Datenspeicher erlaubt. Externe I/O-Einheiten können damit wie ein externes RAM über die "MOVX"-Befehle des MCS48-Befehlssatzes angesprochen werden, so dass 256 * 8 Bit (=2048 Bit) zur Ausgabe und 256 * 8 Bit (=2048 Bit) zur Eingabe adressierbar sind. Das Signal IO/*M führt H-Pegel im I/O-Adressbereich und L-Pegel, wenn das externe RAM angesprochen wird.
Bild: Erzeugung des IO/*M-Signals für memory-mapped-I/O mit DeMon48
Informationen zu den gezeigten Jumpern : siehe "5.0.0 Speicherkonfigurationen".
Das DeMon48-System bietet derzeit die Möglichkeit, einen Hardware-Breakpoint (evtl. kommt später ein Breakpoint-RAM) zu aktivieren, was die Ausführung von Code bei aktiviertem Breakpoint ohne Geschwindigkeitsverlust ermöglicht.
Mit Hilfe zweier RC-Netzwerke wird das *X_PSEN-Signal verzögert und verkürzt, so dass der Zeitpunkt, an dem der Adressbus abgefragt wird, in etwa in die Mitte des ursprünglichen *PSEN-Signals verschoben wird.
Bild: Hardware-Breakpoint Schaltung
Bild: Verzögertes und verkürztes Gate-Signal für die "74HC688" 8Bit-Komparatoren