ctr

DeMon48_128k

intel 8049 (8048, 8748, 8749, 8035, 8039) / MCS-48 Hardware-Debugger & Monitor

Dokumentation - Kapitel 2


2.0.0 8049-Primer

Dieses Kapitel beschreibt nur einige Eigenschaften der intel MCS-48 Familie beziehungsweise des 8049 Mikrocontrollers. Zum vollständigen Verständnis ist die Lektüre der entsprechenden, von intel herausgegebenen Literatur - wie Datenblätter - erforderlich. Diese findet man leicht mit Hilfe einer Internet-Suchmaschine als elektronische Dokumente, zum Beispiel im üblichen PDF-Format.

2.1.0 Die MCS-48 Mikrocontroller Familie

Der 8049-Mikrocontroller gehört zur intel MCS-48 Single Chip Microcomputer Familie, die ab 1976 eingeführt und damals sinngemäß als "Erster vollständiger Computer auf einem Chip" (von intel) beworben wurde. Sie wurde in NMOS-Technologie gefertigt und ließ sich mit einer maximalen Oszillatorfrequenz von 6MHz, später 11MHz, betreiben.

Beim Betrieb mit 11MHz ergibt sich eine Befehlszykluszeit von 1,36µs (T[µs] = 15 / fosc[MHz]), in denen 1-Byte-/1-Zyklus-Befehle, deren Anteil mehr als 50% an dem aus 96 Befehlen bestehenden Befehlssatz beträgt, ausgeführt werden.

Spätere Ausführungen wurden in intels HMOS-II-Prozess (High density, short channel MOS) mit geringerer statischer Leistungsaufnahme, geringeren Strukturgrößen (Kanallänge ca. 2µm) und Gatterverzögerungen (ca. 0,5ns) gefertigt. CMOS-Versionen wurden beispielsweise 1979 von Intersil angeboten.

Die µCs der intel MCS-48 Familie sind für eine Harvard-Architektur ausgelegt, also zur Nutzung von logisch und physisch getrenntem Befehls- und Datenspeicher.

2.1.1 MCS-48 µC Family Members & On-Chip Ressources (1979)

DevicePackageROMEPROMRAMI/ONotes
8035DIP40--6427RAM-Standby
8048DIP401k-6427RAM-Standby
8748DIP40-1k6427-
8039DIP40--12827RAM-Standby
8049DIP402k-12827RAM-Standby
8749DIP40-2k12827-
8040DIP40--25627RAM-Standby
8050DIP404k-25627RAM-Standby
8021DIP281k-6420-
8022DIP402k-6426 + 2xAD-
8041DIP401k-6418Master interface
8741DIP40-1k6418Master interface

2.1.2 Erwähnung der MCS48-Familie in Publikationen der 1970er und -80er Jahre

ZeitpunktTitel (Thema)Publikation
1976 / 02"Intel prepares 8-bit processor for low end""Electronics", 05.02.1976
1976 / 11"Single-chip 8- bit microcomputer fills gap between calculator types and powerful multichip processors" (8048 (Mask ROM) / 8748 (EPROM); 1kB ROM, 64bytes RAM; 6MHz max. clock frequency)"Electronics", 25.11.1976
1976 / 11"For the low end of the market we are promised two minimum chip families: the MCS48 and the MCS41.""Electronics Today International (AU)",
11 / 1976
1977 / 03"Intel to double microcomputer chip program memory" (2kB 8049 / 8039)"Electronics", 03.03.1977
1977 / 03"Programmer added for MCS-48 family" (Prompt-48)"Electronics", 31.03.1977
1977 / 06"The [...] control computer features an eight-bit CPU (i.e. the Intel 8048) with BCD arithmetic capabilities 1 k of ROM, 64 words of internal RAM, interrupt, oscillator and clock driver circuits and an internal timer and event counter.[...] US prices are $249 with ROM and $399 with EROM."
(IMSAI 8048)
"Electronics Today International (AU)",
06 / 1977
1978 / 02"Single-chip µC has twice memory of MCS-48s" (2kB 8049 / 8039)"Electronic Design", 15.02.1978
1978 / 04"IBM receives license for MCS-48, UPI-41 architectures and software""Electronics", 27.04.1978
1978 / 05"Intel's 8022 packs a-d converter, plus""Electronics", 11.05.1978
1978 / 05"Intel speeds up 8049 and 8039 by 80% to 11 MHz""Electronics", 11.05.1978
1978 / 05"Microcontroller includes a-d converter for lowest-cost analog interfacing" (8022)"Electronics", 25.05.1978
1979 / 01"A look at Intel's [...] MCS-48 µP family.""Radio Electronics",
01 / 1979
1979 / 05"Intersil's C-MOS drive" (MCS-48 C-MOS devices; 87C48, 87C41, 80C48, 80C41, 80C49, 80C35)"Electronics", 10.05.1979
1979 / 12"Microcomputer with A/D converter - Intel's 8022 is the first low-cost single-IC microcomputer that includes an A/D converter.""Radio Electronics",
12 / 1979
1980 / 02"Valvo, the Hamburg-based component-producing subsidiary of NV Philips Gloeilampenfabrieken, is now gearing up for production of the 8048 microcomputer""Electronics", 28.02.1980
1980 / 02"8048 to be made with Intel's HMOS process""Electronics", 28.02.1980
1980 / 09"National Semiconductor quadruples memory of 8048 microcomputer" (INS8050: 4kB ROM, 256bytes RAM)"Electronics", 25.09.1980
1981 / 03"Intel announced [...] a [...] 'automotive grade' version of its MCS-48 single-chip microcomputer family (able to operate at -40° to +100°C)""Electronics", 24.03.1981

2.2.0 Der 8049 Mikrocontroller

Der 8049 µC besteht neben den Bestandteilen der eigentlichen CPU (ALU, Register etc.) aus :

  • einem als maskenprogrammiertes ROM ausgeführten internen 2kByte Programmspeicher
  • 128 Byte RAM (eigene Standby-/LowPower-Versorgung möglich)
  • einem 8-Bit Timer/Counter
  • drei 8-Bit Ports (BUS, P1, P2)
  • Oszillator-Hardware
  • Interrupt-Logik : 2 Quellen (externer Interrupt und Timer-/Counter-Überlauf), 1 Ebene

Zusätzlich verfügt er über zwei "Test" Anschlüsse (T0 und T1), die je nach Programmierung für bedingte Sprünge abgefragt, als Eingang für den 8-Bit-Zähler oder als Ausgang für das "CLK"-Signal (fclk = fosc / 3), mit dessen Frequenz die interne Zustandsmaschine zur Erzeugung der S1 bis S5 Zustände, aus denen ein Maschinenzyklus besteht, getaktet wird, dienen können.

Enable T0-Clock-output
Bild: Ausführen des "ENT0 CLK"-Befehls (Opcode 0x75) zur Ausgabe von CLK an T0

Indem man an den "EA"-Anschluss (External Access) H-Pegel legt, lässt sich das interne ROM abschalten und ein externer Speicherbaustein als Programmspeicher mit der Basisadresse 0x000 verwenden : der 8049 µC verhält sich dann exakt wie der sonst identische, aber ROM-lose Typ 8039.

Zum Zugriff auf einen externen Programmspeicher werden die Signale von BUS und der unteren Hälfte von P2 (P2.0 bis P2.3) herangezogen. Auf BUS liegen im Zeitmultiplexverfahren abwechselnd die unteren 8-Bit der Adresse und Daten an, das untere Nibble (die niederwertigen 4Bit) von P2 signalisiert die oberen 4Bit der Adresse bzw. zu bestimmten Zeitpunkten während eines Befehlszyklus, der aus den fünf Zuständen S1 bis S5 der CPU-Zustandsmaschine besteht, die auf P2 geschriebene I/O-Information (siehe Zeichnungssatz, "MCS-48 Logic Analyzer Traces").

MCS-48 Machine States S1 to S5
Bild: S1 bis S5 der CPU-Zustandsmaschine

2.2.1 PSW (Program Status Word)

Im PSW sind die CPU-Flags und der Stack-Zeiger abgelegt.

Es kann vollständig nur durch "MOV PSW,A"-Befehle (Opcode 0xD7) beschrieben und "MOV A,PSW"-Befehle (Opcode 0xC7) gelesen werden, da es ein vom internen RAM unabhängiges Hardware-Register ist.

BitFunktion
7CYCarry FlagIn A hat ein Überlauf stattgefunden
6ACAuxiliary Carry FlagIn A hat ein Überlauf von Bit3 zu Bit4 stattgefunden
5F0User Flag 0Wird mit "CLR F0" gelöscht, mit "CPL F0" invertiert und mit "JF0" für bedingte Sprünge ausgewertet
4BSRegister Bank Select0: Registerbank0 aktiv; 1: Registerbank1 aktiv
3'1'Ist im Ergebnis eines Lesezugriffs auf das PSW immer 1
2S2Stack Pointer Bit 2Stack-Zeiger-Bit mit der dezimalen Wertigkeit 4
1S1Stack Pointer Bit 1Stack-Zeiger-Bit mit der dezimalen Wertigkeit 2
0S0Stack Pointer Bit 0Stack-Zeiger-Bit mit der dezimalen Wertigkeit 1

2.2.2 Internes RAM

Das interne statische RAM umfasst bei den intel 8035-, 8048- und 8748-Typen 64 Byte, bei den 8039-, 8049- und 8749-Typen 128 Byte und beim 8050 256 Byte.

Es beinhaltet zwei 8 Byte große Registerbänke, innerhalb derer über die Angabe Rr (R0 ... R7) in einem geeigneten Befehl direkt auf den Inhalt der entsprechenden RAM-Adresse zugegriffen werden kann (z.B. : "MOV R5,A" zum Zugriff auf RAM-Adresse 0x05, wenn BS im PSW = 0 ist, beziehungsweise auf RAM-Adresse 0x1D, wenn BS im PSW = 1 ist). Die Auswahl der aktiven Registerbank erfolgt über das "BS"-Flag (Register Bank Select) im PSW (Program Status Word) beziehungsweise über den "SEL RB0"-Befehl (Opcode 0xC5) zur Auswahl der Registerbank 0 und den "SEL RB1"-Befehl (Opcode 0xD5) zur Auswahl der Registerbank 1. Es kann auch indirekt über die Indexregister R0 und R1 auf die RAM-Adressen der beiden Registerbänke zugegriffen werden.

Dadurch, dass zwei unabhängige Registerbänke zur Verfügung stehen, können unter anderem effektive Interrupt-Service-Routinen erstellt werden, indem beispielsweise die Registerbank 0 im Hauptprogramm und Registerbank 1 in der Interrupt-Routine verwendet wird.

Auf alle anderen Adressen des internen RAMs kann nur indirekt über die Indexregister R0 und R1 zugegriffen werden. Zum Beispiel transportiert ein "MOV @R0,A"-Befehl den Inhalt des Akkumulators in die RAM-Adresse 0x20, wenn R0 = 0x20 ist.

Zusätzlich enthält es den 8 Ebenen umfassenden Stack-Bereich.

Adresse (hex)FunktionAnmerkung
20...3F
20...7F
20...FF
RAM8035,8048,8748 = 32 Byte
8039,8049,8749 = 96 Byte
8050 = 224 Byte
1FR7'Registerbank1 (PSW.4 = 1)
1ER6'Registerbank1 (PSW.4 = 1)
1DR5'Registerbank1 (PSW.4 = 1)
1CR4'Registerbank1 (PSW.4 = 1)
1BR3'Registerbank1 (PSW.4 = 1)
1AR2'Registerbank1 (PSW.4 = 1)
19R1'Registerbank1 (PSW.4 = 1)
18R0'Registerbank1 (PSW.4 = 1)
17Stack Level 7 MSB (*) / RAMSP (PSW.0...PSW.2) = 7
16Stack Level 7 LSB (*) / RAMSP (PSW.0...PSW.2) = 7
15Stack Level 6 MSB (*) / RAMSP (PSW.0...PSW.2) = 6
14Stack Level 6 LSB (*) / RAMSP (PSW.0...PSW.2) = 6
13Stack Level 5 MSB (*) / RAMSP (PSW.0...PSW.2) = 5
12Stack Level 5 LSB (*) / RAMSP (PSW.0...PSW.2) = 5
11Stack Level 4 MSB (*) / RAMSP (PSW.0...PSW.2) = 4
10Stack Level 4 LSB (*) / RAMSP (PSW.0...PSW.2) = 4
0FStack Level 3 MSB (*) / RAMSP (PSW.0...PSW.2) = 3
0EStack Level 3 LSB (*) / RAMSP (PSW.0...PSW.2) = 3
0DStack Level 2 MSB (*) / RAMSP (PSW.0...PSW.2) = 2
0CStack Level 2 LSB (*) / RAMSP (PSW.0...PSW.2) = 2
0BStack Level 1 MSB (*) / RAMSP (PSW.0...PSW.2) = 1
0AStack Level 1 LSB (*) / RAMSP (PSW.0...PSW.2) = 1
09Stack Level 0 MSB (*) / RAMSP (PSW.0...PSW.2) = 0
08Stack Level 0 LSB (*) / RAMSP (PSW.0...PSW.2) = 0
07R7Registerbank0 (PSW.4 = 0)
06R6Registerbank0 (PSW.4 = 0)
05R5Registerbank0 (PSW.4 = 0)
04R4Registerbank0 (PSW.4 = 0)
03R3Registerbank0 (PSW.4 = 0)
02R2Registerbank0 (PSW.4 = 0)
01R1Registerbank0 (PSW.4 = 0)
00R0Registerbank0 (PSW.4 = 0)
(*) Stack LSB = PC.0 ... PC.7; Stack MSB = PC.8 ... PC.11 (Bit0 ... 3), PSW.4 ... PSW.7 (Bit4 ... 7)

2.2.3 Stack im internen RAM

Im internen RAM befindet sich von Adresse 0x08 bis 0x17 ein bis zu 16 Byte großer Stack-Bereich zur Ablage von Rücksprungadressen und PSW-Flags durch die CPU.

Die "CY"-, "AC"-, "F0"- und "BS"-Flags (PSW.7 ... PSW.4) werden bei einem Unterprogrammaufruf per "CALL"-Befehl oder durch eine Interruptanforderung zusammen mit dem aktuellen Inhalt des Programmzählers (PC.0 ... PC.11) im durch den Stack-Zeiger (PSW.0 ... PSW.2) adressierten Byte-Paar des Stack-Bereichs im RAM hinterlegt.

Der Stack-Zeiger in PSW.0 bis PSW.2 wird nach der Ausführung eines "CALL"-Befehls oder einer Interrupt-Anforderung automatisch inkrementiert und bei der Ausführung eines "RET"- oder "RETR"-Befehls dekrementiert. Bei einem Überlauf des Stack-Zeigers wechselt er vom Wert 0x07 zum Wert 0x00 und entsprechend bei einem Unterlauf vom Wert 0x00 zum Wert 0x07.

Bei der Ausführung eines "RETR"-Befehls werden neben dem Programmzähler auch die auf dem Stack gesicherten oberen 4 Bit des PSW (PSW.4 ... PSW.7) wiederhergestellt, was bei der Ausführung eines "RET"-Befehls nicht geschieht.

Mit Hilfe des bis zu 16 Byte umfassenden Stack-Bereichs können Unterprogramme maximal 8fach verschachtelt aufgerufen werden, ohne dass es zu einem Stack-Überlauf und zur Zerstörung des Stack-Inhalts kommt.

Nicht genutzte Stack-Positionen stehen zur Nutzung als allgemeines RAM zur Verfügung.

Belegung eines Stack-Byte-Paars :

BitStack-Offset+0 (*)Stack-Offset+1 (*)
7PC.7PSW.7
6PC.6PSW.6
5PC.5PSW.5
4PC.4PSW.4
3PC.3PC.11
2PC.2PC.10
1PC.1PC.9
0PC.0PC.8
(*) Stack-Offset = Stack-Pointer * 2 + 8

Beispiel 1 :

PSW.2 = PSW.1 = PSW.0 = 0

Stack-Offset = 0 * 2 + 8 = RAM-Adresse 0x08

Beispiel 2 :

PSW.2 = 0

PSW.1 = PSW.0 = 1

Stack-Offset = 3 * 2 + 8 = RAM-Adresse 0x0E

2.3.0 8049-Minimalsystem mit externem Programmspeicher

8049 Minimalsystem mit externem EPROM
Bild: Mit dieser Schaltung lässt sich das Programm im externen EPROM 2732 ausführen

BauteilFunktion
8049Mikrocontroller
74LS373"Octal D-Type Latch With 3 State Output" zum Zwischenspeichern von A0...A7
2732"32 Kbit (4Kb x 8) UV EPROM" als Programmspeicher

2.4.0 8049-Steuersignale, -Ports, -Timing

2.4.1 EA

Wenn der EA-Eingang (External Access) an Pin 7 des µCs auf High-Potential (+5V) gelegt ist, erfolgen alle Programmspeicherzugriffe mittels ALE, *PSEN, BUS, P2.0, P2.1, P2.2 und P2.3 auf externe Speichereinheiten, der interne Programmspeicher ist deaktiviert.

2.4.2 *RESET

*RESET ist ein Low-Pegel-aktiver Initialisierungseingang mit Schmitt-Trigger Eigenschaft und im µC integrierten Pullup-FET mit ca. 80kOhm Impedanz an Pin 4 des µCs. Muss mindestens 10ms aktiviert (Low) werden, nachdem Vcc, Vdd und Vss stabil anliegen. Muss mindestens 5 Maschinen-Zyklen (T(Reset)[s] = 75 / fosc[Hz]) aktiviert (Low) werden, wenn sich der Oszillator des µC bereits stabilisiert hat.

Durch Aktivieren des Reset-Eingangs wird folgender Zustand hergestellt :

  1. PC = 0 (Program Counter)
  2. SP = 0 (Stack Pointer, S0, S1, S2)
  3. RB = 0 (Register Bank Flag)
  4. MB = 0 (Memory Bank Flip-Flop)
  5. P1 = P2 = Input Mode (Port1, Port2)
  6. Interrupts werden deaktiviert (T und *INT)
  7. Timer wird gestoppt
  8. Timer Flag = 0
  9. F0 = F1 = 0 (User Flag0, User Flag1)
  10. Stoppt die Ausgabe von CLK (fosc/3) an T0 (Test0)

Aufgrund des im µC integrierten Pullup-FETs reicht im Minimalfall die Beschaltung mit einem externen 1µF-Kondensator aus, um einen Power-On-Reset zu realisieren.

2.4.3 *INT

*INT ist ein Low-Pegel-aktiver Eingang für externe Interrupt-Anforderung an Pin 6 des µC. Muss mindestens 3 Maschinen-Zyklen (T(*INT)[s] = 45 / fosc[Hz]) aktiviert (Low) sein, um eine zuverlässige Funktion der Interruptanforderung zu gewährleisten. Nachdem der µC die Interrupt-Anforderung erkannt hat, werden PC und PSW auf dem Stack gesichert und PC wird mit Adresse 0x003 geladen - auch wenn gerade der obere 2kB-Block 0x800 bis 0xFFF durch einen "SEL MB1"-Befehl aktiviert oder vorbereitet ist. Zur Rückkehr aus der ISR ist der "RETR"-Befehl zu nutzen.

Nach einem Reset ist die Auslösung eines Interrupts durch den *INT-Anschluss deaktiviert und kann durch den Befehl "EN I" (Opcode 0x05) aktiviert werden. Auch wenn Interrupts durch den *INT-Eingang deaktiviert sind, kann der Pegel am *INT-Anschluss über den "JNI"-Befehl für bedingte Sprünge ausgewertet werden. Die Erkennung von Interrupt-Anforderungen am *INT-Eingang kann im Programm durch Ausführen des "DIS I"-Befehls (Opcode 0x15) deaktiviert werden.

2.4.4 ALE

Die fallende Flanke des ALE-Ausgangs (Address Latch Enable) an Pin 11 des µCs zeigt an, dass gültige Adressinformation auf BUS vorhanden ist und kann zur Übernahme der Adresse in einen FlipFlop-Zwischenspeicher genutzt werden. Zum Zeitpunkt der steigenden Flanke des ALE-Signals sind immer die zuletzt geschriebenen I/O-Informationen an P2.0 bis P2.3 verfügbar und können ebenfalls in ein entsprechendes FlipFlop übernommen werden.

Timing MCS-48 Instruction Fetch

2.4.5 *PSEN

Mit Hilfe des Low-aktiven *PSEN-Ausgangs (Program Store Enable) an Pin 9 des µCs wird aus einem externen Programmspeicher gelesen. Die vom Programmspeicher bei *PSEN=Low auf BUS gelegte Information wird vor der steigenden Flanke von *PSEN in den µC übernommen.

2.4.6 *RD

Der Low-aktive *RD-Ausgang (Read) an Pin 8 des µCs dient zur Übernahme von Informationen von einer externen Einheit (RAM / IO etc.). Wenn *RD Low wird, legt die externe Einheit die Informationen auf BUS, wo sie dann vor der steigenden Flanke des *RD-Signals in den µC übernommen werden. Zur Erzeugung des *RD-Signals kommen bei EA=High nur die "MOVX A,@Ri"-Befehle (1 Byte, 2 Zyklen) in Frage.

Timing MCS-48 Data Read

2.4.7 *WR

Der Low-aktive *WR-Ausgang (Write) an Pin 10 des µCs dient zur Übernahme von Informationen in eine externen Einheit (RAM / IO etc.). Wird *WR Low, legt der µC die an die externe Einheit zu übermittelnde Information auf BUS, wo sie dann bei der steigenden Flanke des *WR-Signals stabil anliegt und von der externen Einheit übernommen wird. Zur Erzeugung des *WR-Signals kommen bei EA=High nur die "MOVX @Ri,A"-Befehle (1 Byte, 2 Zyklen) in Frage.

Timing MCS-48 Data Write

2.4.8 PROG

Die fallende Flanke des PROG-Ausgangs an Pin 25 des µCs signalisiert, dass an P2.0 bis P2.3 ein Befehlscode und eine Portadresse ausgegeben wird. Die zugehörigen Daten werden bei der steigenden Flanke des PROG-Signals in eine externe Einheit oder vor der steigenden Flanke des PROG-Signals vom µC übernommen.

Der Befehlscode wird durch den eingesetzten Befehl des MCS-48 Befehlssatzes bestimmt Die Portadresse wird durch den in diesem Befehlscode angegebenen Port bestimmt
BefehlP2.3P2.2
MOVD A,Pp00
MOVD Pp,A01
ORLD Pp,A10
ANLD Pp,A11
pP2.1P2.0
400
501
610
711

Die Daten entsprechen bei Schreibzugriffen dem unteren Nibble (Bit0...Bit3) des Akkumulator-Inhalts bzw. werden bei Lesezugriffen mit Hilfe des PROG-Signals durch den µC in das untere Nibble des Akkumulator-Inhalts übernommen.

Timing MCS-48 Portexpander Read

Timing MCS-48 Portexpander Write

2.4.9 P1, P2

P1 und P2 sind quasi-bidirektionale, statische Ein-/Ausgabeports mit jeweils 8 Portleitungen. Die Quasi-Bidirektionalität wird erreicht, indem an jede Portleitung ein ständig aktiver Pullup-FET mit ca. 65kOhm Impedanz angeschlossen ist und gleichzeitig zwei FETs mit niedriger Impedanz, die die Portleitung auf "0"- oder "1"-Pegel legen können. Der FET zum Anlegen des "1"-Pegels ist bei einem Schreibzugriff nur etwa 1/5 eines Maschinen-Zyklus (ALE-Zyklus) aktiv um die Flankensteilheit bei einem "0"-zu-"1"-Wechsel zu erhöhen, danach wird der "1"-Pegel von dem hochimpedanten Pullup-FET aufrecht erhalten. Der FET zum Anlegen des "0"-Pegels bleibt nach einem Schreibzugriff auf eine Portleitung mit "0" bis zu einem Schreibzugriff mit "1" ständig aktiv.

Um eine Portleitung als Eingang zu nutzen, muss dafür im entsprechenden Ausgangsregister eine "1" enthalten sein, so dass nur der Pullup-FET mit hoher Impedanz wirksam ist und die Portleitung von einem externen Signal auf "0"-Pegel gelegt werden kann. Für jede Portleitung kann so einzeln festgelegt werden, ob sie als Eingang oder als Ausgang dienen soll.

Timing MCS-48 P1, P2 Write

2.4.10 BUS

BUS ist ein bidirektionaler, statischer Ein-/Ausgabeport mit 8 Portleitungen D0 bis D7. Bei einem Schreibzugriff durch einen
"OUTL BUS,A"- oder "MOVX @Ri,A"-Befehl wird die *WR-Leitung aktiviert (Low), durch deren steigende Flanke signalisiert wird, dass sich gültige Daten auf D0 bis D7 befinden und von einer externen Einheit übernommen werden können.

Bei einem Lesezugriff durch einen "INS A,BUS"- oder "MOVX A,@Ri"-Befehl wird die *RD-Leitung aktiviert (Low), vor deren steigender Flanke die durch eine externe Einheit auf D0 bis D7 gelegte Information vom µC übernommen wird.

Es ist ohne zusätzliche Hardware nicht zulässig, bei der Verwendung eines externen Programmspeichers "OUTL BUS,A"- oder
"INS A,BUS"-Befehle auszuführen.

2.4.11 8049-Timing

MCS-48 Timing

2.5.0 Logik-Analysator Aufzeichnungen

MCS-48 Program-Memory access
Bild: Zugriff auf externen Programmspeicher

MCS-48 external RAM access
Bild: Zugriff auf externes RAM

MCS-48 PROG access
Bild: Schreibzugriff mit "PROG"-Signal

MCS-48 Port Write
Bild: Schreibzugriff auf Port1 und Port2

MCS-48 JMP / CALL address instructions
Bild: Unbedingter Sprung mit "JMP" oder "CALL"

MCS-48 RET instruction
Bild: Ausführen des "RET"-Befehls

Bemerkenswert ist, dass bei der Ausführung eines "RET"-Befehls (Return from subroutine) für den zweiten Befehlszyklus *PSEN (Program Store Enable) aktiviert (Low) wird, obwohl es sich um einen 1Byte-Befehl handelt, also im zweiten Befehlszyklus nichts aus dem Programmspeicher gelesen wird.

MCS-48 JMPP @A instruction
Bild: Indirekter Sprung auf einer 256Byte-Page mit "JMPP @A"

MCS-48 MOVP A,@A / MOVP3 A,@A instructions
Bild: Lesen von Konstanten aus dem Programmspeicher mit "MOVP A,@A" und "MOVP3 A,@A"

Umfangreichere und höher aufgelöste Grafiken befinden sich im Zeichnungssatz des Projekts.
(Auch die als PDF verfügbare Download-Version der Dokumentation bietet eine bessere Bildqualität.)

2.6.0 Besonderheiten der MCS-48 Familie

Die Mitglieder der MCS-48 Familie haben aufgrund ihrer Hardware-Architektur einige, teils sehr unangenehme Eigenheiten.

2.6.1 "SEL MBx" : Speichermanagement à la intel in 1976

Die 8048-, 8049-, 8748-, 8749-, 8035- und 8039-Mikrocontroller der intel MCS-48-Familie unterstützen einen bis zu 12 Bit breiten externen Adressbus (A0 bis A11), so dass maximal 4kByte adressiert werden können. Allerdings sind diese 4kByte in 2 Bänke à 2kByte aufgeteilt, und nur innerhalb dieser 2kByte großen Speicherbänke kann durch "JMP"- und "CALL"-Befehle linear, also "am Stück", adressiert werden.

Zum Wechsel zwischen diesen 2kB 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 Mikrocontroller 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), 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 (A11) des Programmzählers wird der Zustand des oben genannten Vorbereitungs-FlipFlops übernommen.

Nach Ausführen des folgenden Codes hat der Programmzähler ("PC") den Wert 0x800 (Bit11 = 1) :

000 F5 SEL MB1 ;MB-FlipFlop = 1
001 04 JMP 000 ;PC = 0x000 + 0x800
002 00

Wird danach Folgendes ausgeführt, wird der Programmzähler auf 0x000 (Bit11 = 0) gesetzt :

800 E5 SEL MB0 ;MB-FlipFlop = 0
801 04 JMP 000 ;PC = 0x800 - 0x800
802 00

Es kann 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 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 erst beim nächsten "JMP"- oder "CALL"-Befehl des Anwender-Programms wirksam wird.

Es muss also beim Beenden der Monitor-Software neben Bit0 bis Bit11 des Programmzählers (PC) unbedingt auch der Zustand des MB-FlipFlops im Moment des Aufrufs der Monitor-Software wiederhergestellt werden.

Internes MB-FlipFlop (A12)
Bild: Prinzipdarstellung der internen Logik zur Erzeugung des 12. Adress-Bits, PC.11

SEL MB1
Bild: Ausführen des "SEL MB1"-Befehls (0xF5) und Wirkung auf P2.3 nach "JMP 000" (0x04,0x00)

2.6.2 "SEL MBx" und 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.

2.6.3 "SEL MBx" und "CALL"

Wenn ein Bankwechsel im Zusammenhang mit einem Unterprogramm-Aufruf per "CALL"-Befehl stattfindet ist ebenfalls Vorsicht geboten. 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 :

000 F5 SEL MB1
001 14 CALL 000 ;Sprung zu 0x800 (Adresse 0x000 in Bank 1)
002 00
003 04 JMP 010  ;Sprung zu 0x010 (oder doch 0x810 ?)
004 10
800 83 RET      ;Rücksprung zur Adresse 0x003

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).

2.6.4 Der Programmzähler : Bitte ein Bit ...

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 natürlich wieder einen Sonderfall : wenn der Sprungbefehl in einer der höchsten Adressen 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.

2.6.5 Timer/Counter und Interrupt

Zum Timer-/Counter und dem zugehörigen 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 im Debugger) abhängig ist.