6502 - Einführung
Vorstellung der Demo-Platine
- Github-Repository: https://github.com/RobFro96/Arduino-Mega-6502
- Simulator: https://www.tejotron.com/
- Schaltplan: https://raw.githubusercontent.com/RobFro96/Arduino-Mega-6502/master/eagle-6502/base/base.pdf
- Datenblätter:
- W65C02: https://www.westerndesigncenter.com/wdc/documentation/w65c02s.pdf
- AT28C256: http://ww1.microchip.com/downloads/en/DeviceDoc/doc0006.pdf
- AS6C62256: https://www.alliancememory.com/wp-content/uploads/pdf/AS6C62256.pdf
- W65C22: https://www.westerndesigncenter.com/wdc/documentation/w65c22.pdf
- LCD: https://www.sparkfun.com/datasheets/LCD/HD44780.pdf
- 74HC00: https://www.mouser.com/catalog/specsheets/nxp_74hc_hct00.pdf
- 74HC138: https://assets.nexperia.com/documents/data-sheet/74HC_HCT138.pdf
Aufbau des Mikroprozessors (W65C02)
- 8-Bit-Mikroprozessor von MOS Technology, Inc. von 1975
- Einsatz in vielen Heimcomputern und Videokonsolen: Atari VCS/2600 (6507), Commodore PET, Atari 800, Apple I, II
- Taktfrequenz: 20 kHz bis 4 MHz
- NMOS-Logik
- Strombedarf: 70-160 mA
- Daten des modernen W65C02:
- Neuauflage 1983 von Western Design Center
- Auch Stand 2021 noch in Produktion (z. B. Mouser)
- Taktfrequenz: 0 bis 14 MHz
- CMOS-Logik
- Strombedarf: < 1.5 mA/MHz
NOP-Generator
- „Hello World! eines Mikroprozessors“
- Ziel: Überprüfung der korrekten Funktionsweise des Mikroprozessors.
- Der Datenbus wird auf eine speziellen Code festgesetzt, sodass der Mikroprozessor immer die selben Daten einliest.
- NOP-Befehl des 6502: 0xEA (siehe Opcode-Matrix)
- hier: Der EEPROM wird komplett auf den Wert 0xEA gesetzt.
- Wenn der Mikroprozessor im Datenbereich von 0x8000 - 0xFFFF liest, gibt der EEPROM 0xEA aus.
Python-Code zum Erstellen der NOP-Binary-Datei
Bus-Verlauf des NOP-Programms
> AB = 0x800C R DB = 0xEA RESB
> AB = 0x800C R DB = 0xEA
> AB = 0xFFFF R DB = 0xEA nop
> AB = 0x800D R DB = 0xEA
> AB = 0x01F6 R DB = 0xFF
> AB = 0x01F5 R DB = 0xFF
> AB = 0x01F4 R DB = 0xFF
> AB = 0xFFFC R DB = 0xEA
> AB = 0xFFFD R DB = 0xEA
> AB = 0xEAEA R DB = 0xEA nop
> AB = 0xEAEB R DB = 0xEA
> AB = 0xEAEB R DB = 0xEA nop
> AB = 0xEAEC R DB = 0xEA
> AB = 0xEAEC R DB = 0xEA nop
> AB = 0xEAED R DB = 0xEA
> AB = 0xEAED R DB = 0xEA nop
> AB = 0xEAEE R DB = 0xEA
> AB = 0xEAEE R DB = 0xEA nop
> AB = 0xEAEF R DB = 0xEA
- RESB-Pin wird auf L-Pegel gezogen → Reset
- Der Mikroprozessor benötigt 6 weitere Takte für die Initialisierung.
- Einlesen des Reset-Vectors: 0xFFFC, 0xFFFD
- Ausführen des Programmes von der Adresse 0xEAEA aus.
- NOP-Befehl benötigt 2 Systemtakte zum Ausführen (siehe 6502 Addressing Modes)
Programmierung eines Mikroprozessors
- Ziel: LEDs blinken lassen, die am VIA angeschlossen sind.
- Der 6502 muss verschiedene Geräte ansprechen → es wird ein Adressdekoder benötigt.
- Dieser soll später untersucht werden. Es sei folgendes bekannt:
- Der W65C22S wird im Adressbereich 0x7F00-0x7F0F aktiviert.
- Der EEPROM wird im Adressbereich 0x8000-0xFFFF aktiviert.
- Zwei frei programmierbare Ports (PA0...PA7, PB0...PB7).
- Chip Select (CS1, CS2B)
- Anschluss an einen Teil des Adressbusses (RS0...RS3 → A0...A3)
- Anschluss an den Datenbus (D0...D7)
- Anschluss an Steuerbus (PHI2, RWB, IRQB)
Python-Code zum Erstellen des EEPROM-Abbildes der Blinken-Programms
rom = [0] * 0x8000
# lda #0xFF
rom[0] = 0xA9
rom[1] = 0xFF
# sta 0x7F02
rom[2] = 0x8D
rom[3] = 0x02
rom[4] = 0x7F
# lda #0xA5
rom[5] = 0xA9
rom[6] = 0xA5
# sta 0x7F00
rom[7] = 0x8D
rom[8] = 0x00
rom[9] = 0x7F
# lda #0x5A
rom[10] = 0xA9
rom[11] = 0x5A
# sta 0x7F00
rom[12] = 0x8D
rom[13] = 0x00
rom[14] = 0x7F
# jmp 0x8005
rom[15] = 0x4C
rom[16] = 0x05
rom[17] = 0x80
# reset vector = 0x8000
rom[0x7FFC] = 0x00
rom[0x7FFD] = 0x80
with open("blinky_opcode.bin", "wb") as outfile:
outfile.write(bytearray(rom))
Bus-Verlauf des Blinken-Programms
> AB = 0x800C R DB = 0x8D RESB
> AB = 0x800C R DB = 0x8D
> AB = 0xFFFF R DB = 0x00 brk
> AB = 0x800D R DB = 0x00
> AB = 0x01DB R DB = 0x8B
> AB = 0x01DA R DB = 0xB9
> AB = 0x01D9 R DB = 0x85
> AB = 0xFFFC R DB = 0x00
> AB = 0xFFFD R DB = 0x80
> AB = 0x8000 R DB = 0xA9 lda #$ff
> AB = 0x8001 R DB = 0xFF
> AB = 0x8002 R DB = 0x8D sta $7f02
> AB = 0x8003 R DB = 0x02
> AB = 0x8004 R DB = 0x7F
> AB = 0x7F02 w DB = 0xFF
> AB = 0x8005 R DB = 0xA9 lda #$a5
> AB = 0x8006 R DB = 0xA5
> AB = 0x8007 R DB = 0x8D sta $7f00
> AB = 0x8008 R DB = 0x00
> AB = 0x8009 R DB = 0x7F
> AB = 0x7F00 w DB = 0xA5
> AB = 0x800A R DB = 0xA9 lda #$5a
> AB = 0x800B R DB = 0x5A
> AB = 0x800C R DB = 0x8D sta $7f00
> AB = 0x800D R DB = 0x00
> AB = 0x800E R DB = 0x7F
> AB = 0x7F00 w DB = 0x5A
> AB = 0x800F R DB = 0x4C jmp $8005
> AB = 0x8010 R DB = 0x05
> AB = 0x8011 R DB = 0x80
> AB = 0x8005 R DB = 0xA9 lda #$a5
...