6502 Microcomputer Projekt

Der You-Tube Kanal von Ben Eater befasst sich mit Grundlagen der Digital- und Computertechnik. Insbesondere der Beitrag „Hello, world” from scratch on a 6502 hat mich inspiriert, in dieser Richtung meine eigenen Experimente zu machen.

Clock-Baustein

Normalerweise arbeitet der Mikroprozessor mit Taktfrequenzen im MHz Bereich. Um aber etwas genauer verfolgen zu können, wie der Prozessor arbeitet, ist es sinnvoll eine geringere Taktzeit vorzusehen. Dazu werden auf Basis des NE555 Timer IC ein Stabiler und ein Monostabiler Multivibrator gebaut. Mit dem Monoflop Modul lassen sich dann einzelne Schritte ausführen, während der astabile Bruder für eine kontinuierliche Impulsfolge zwischen 1 und 5 Hz (je nach Auslegung des RC Glieds) sorgt.

Die Schaltung ist in folgender Graphik dargestellt:

EEPROM Programmierung

Wenn man mit einem Microcomputer aus der Frühzeit der Computertechnik arbeitet, bietet es sich an, anstelle der EPROMS heute verfügbare EEPROMS zu verwenden. Diese lassen sich bequem mit Hilfe eines entsprechenden Programmiergerätes flexibel Programmieren.

Ich verwende dazu ein USB Programmiergerät der Firma BATRONIX. Meine Version ist schon 20 Jahre alt, verrichtet seinen Dienst aber nach wie vor tadellos und ist auch mit der neusten Version der Programmierumgebung „ProExpress“ einsetzbar. Der USB Chip Programmer (und seine erhältlichen Nachfolger) ist ein besonders flexibler und einfach zu handhabender Eprom Programmer mit umfangreicher Unterstützung für Eproms, EEproms, Flash und weitere Speicherchips. Die besondere Flexibilität wird durch eine komplette Versorgung über den USB Port erreicht. Ein Netzteil oder Batterien werden nicht benötigt, alle Programmierspannungen zwischen 3 und 25 Volt werden intern aus der USB Spannung über Ladungspumpen generiert.

Generierung der EEPROM Programmier-Informationen

Natürlich kann man versuchen die EEPROMS auch von Hand zu programmieren, aber weit sinnvoller ist es, dies natürlich mit Hilfe eines Programms zu machen, das die entsprechenden Daten in eine Datei schreibt, die dann von der Programmiersoftware eingelesen und auf den Chip geschrieben wird.

Als erstes soll ein Python Programm vorgestellt werden, die diese Aufgabe übernimmt. Der Aufbau ist ziemlich übersichtlich. Zuerst wird ein Array definiert, das der Größe des EEPROM entspricht und dann mit Daten gefüllt. Einzelne Stellen können dann noch manuell eingetragen werden. Anschliessend wird das Ganze dann als Datei mit dem Namen „rom.bin“ ausgegeben.

rom = bytearray ([0xEA]*32768)
rom[0x7FFC] = 0x00
rom[0x7FFC] = 0x80
with open ("rom.bin","wb") as out_file:out_file.write(rom)

Natürlich kann auch jede andere Programmiersprache verwendet werden. Ich verwende üblicherweise mein Mathematica bzw. die Wolfram Language für derartige Programmieraufgaben. In Mathematica würde das Problem wie folgt lösen:

Nach dem das File dann über die Programmer-Software auf den EEPROM übertragen wurde, sieht das im Tool dann etwa so aus:

Arduino als Adress- und Daten-Monitor

Der Arduino Mega mit seinen 54 Pins biete sich an, um damit ein Monitor-Programm für den Adress- und Datenbus und andere relevante Datenleitungen des Mikroprozessors zu verwenden. Das folgende Programm bildet die Basis. Mit Hilfe einer Interrupt Routine werden bei jedem Takt-Impuls die 16-Adress- und 8-Daten-Bits ausgelesen und dargestellt.

// *******************************************
// Monitor Programm um Daten und Adress Bits
// mit Arduino Mega auszulesen
// nach Ben Eater modifiziert von
// ProfHof Sept 2022
// Version 1.0
// *******************************************

const char ADDR[] = {22, 24, 26, 28, 30, 32, 34, 36, 40, 42, 44, 46, 47, 49, 51, 53};
const char DATA[] = {14, 15, 16, 17, 18, 19, 20, 21};
#define CLOCK 2
#define READ_WRITE 3

void setup() {
  for (int n = 0; n < 16; n += 1) {
    pinMode(ADDR[n], INPUT);
  }
  for (int n = 0; n < 8; n += 1) {
    pinMode(DATA[n], INPUT);
  }
  pinMode(CLOCK, INPUT);
  pinMode(READ_WRITE, INPUT);
// sobald clock impulse am Eingang 2 dann wird
// Interrupt routinbe "Clock" aufgerufen
  attachInterrupt(digitalPinToInterrupt(CLOCK), onClock, RISING);
  
  Serial.begin(57600);
}

void onClock() {
  char output[15];

  unsigned int address = 0;
  for (int n = 0; n < 16; n += 1) {
    int bit = digitalRead(ADDR[n]) ? 1 : 0;
    Serial.print(bit);
    // Umwandlung in ein Integerwert
    address = (address << 1) + bit;
  }
  
  Serial.print("   ");
  
  unsigned int data = 0;
  for (int n = 0; n < 8; n += 1) {
    int bit = digitalRead(DATA[n]) ? 1 : 0;
    Serial.print(bit);
    // Umwandlung in ein Integerwert
    data = (data << 1) + bit;
  }
// Ausgabe hat das Format: 
// 16bit Adresse __ 8Bit Data ___ HexAdr __ R/W __ HexData

  sprintf(output, "   %04x  %c %02x", address, digitalRead(READ_WRITE) ? 'r' : 'W', data);
  Serial.println(output);  
}

void loop() {
 
}

Die Ausgabe sieht dann beispielsweise wie folgt aus:

6502 Assembler

Natürlich kann man kleinere Programme „von Hand“ wie oben gezeigt schreiben. Aber ein Assembler erleichtert die Arbeit schon deutlich. Im Beitrag von Ben Eater wird der Assembler „VASM“ von Volker Bartelmann und Frank Wille eingesetzt. http://sun.hasenbraten.de/vasm/

Das Besondere an diesem Assembler ist, dass man ihn für nicht kommerzielle Zwecke frei nutzen darf und es bereits lauffähige Binaries für den Mac gibt. Natürlich stehen auch Versionen für Windows und Linux Betriebssysteme zur Verfügung.

Die Benutzung erfolgt rein über die Kommandozeile und bedarf daher etwas Übung. Es gibt verschiedene Möglichkeiten den Assembler zu konfigurieren. Im folgenden wird beschrieben, wie man den „VASM“ nutzt, um aus einer Datei in der ein 6502-Assembler Programm steht, den Maschinencode für den Eprom-Programmer zu erzeugen.

Beispiel für blinkende LEDs als 6502 Assembler Programm :

 .org $8000
reset:
  lda #$ff
  sta $6002
  lda #$50
  sta $6000

loop:
  ror
  sta $6000
  jmp loop

  .org $fffc
  .word reset
  .word $0000

Diese Datei (mit dem Namen blink.s) wird nun dem Assembler übergeben, und diesem mitgeteilt, dass man Binärcode (option -Fbin) erwartet und mnemonic Anweisungen (wie .org, etc.) berücksichtigt haben will (-dotdir). Der Assembler generiert daraus dann das File a.out, das man mit den Befehlen „cut“ und „hexdump“ anschauen kann. In der Kommandozeile sieht das dann etwa so aus:

MBP-II-2018:mac phof$ ./vasm6502_oldstyle -Fbin -dotdir blink.s
vasm 1.8f (c) in 2002-2019 Volker Barthelmann
vasm 6502 cpu backend 0.8 (c) 2002,2006,2008-2012,2014-2018 Frank Wille
vasm oldstyle syntax module 0.13f (c) 2002-2018 Frank Wille
vasm binary output module 1.8a (c) 2002-2009,2013,2015,2017 Volker Barthelmann

seg8000(acrwx1):	          17 bytes
segfffc(acrwx1):	           4 bytes
MBP-II-2018:mac phof$ cat a.out
???`?P?`j?`L
??MBP-II-2018:mac phof$ hexdump -C a.out
00000000  a9 ff 8d 02 60 a9 50 8d  00 60 6a 8d 00 60 4c 0a  |....`.P..`j..`L.|
00000010  80 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00007ff0  00 00 00 00 00 00 00 00  00 00 00 00 00 80 00 00  |................|
00008000
MBP-II-2018:mac phof$ 

Der Inhalt dieser Datei lässt sich dann – wie oben beschrieben – in einen EEPROM programmieren und zur Steuerung des Mikroprozessors verwenden. Schematisch lässt sich das wie im nachfolgenden Schaubild darstellen:

Schreibe einen Kommentar