Skip to content

6502 - Einführung

Vorstellung der Demo-Platine

alt: "Foto der Demo-Platine", w:50

alt: "Schematischer Aufbau der Demo-Platine", w:60

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

alt: "Pinout des Mikroprozessors (W65C02)", w:25, src: "W65C02 Datenblatt, S. 13"

alt: "Blockdiagramm des Mikroprozessors", w:50, src: "W65C02 Datenblatt, S. 7"

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

rom = [0xEA] * 0x8000

with open("all_EA.bin", "wb") as outfile:
    outfile.write(bytearray(rom))

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)

alt: "6502 Opcode Matrix", w:66,  src: "W65C02 Datenblatt, S. 22", label:"fig:6502_opcode_matrix"

alt: "6502 Instruction Set", w:66, src: "W65C02 Datenblatt, S. 21"

alt: "6502 Addressing Modes", w:66,  src: "W65C02 Datenblatt, S. 20", label:"fig:6502_address_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.

alt: "Pinout des VIA (W65C22)", w:25, src: "W65C22 Datenblatt, S. 28"

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

alt: "Register des VIA (W65C22)", w:66, src: "W65C22 Datenblatt, S. 8"

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