Wiederaufnahme

Nachdem ich meine Bachelorarbeit abgegeben habe, hatte ich endlich wieder Zeit mich mit meinem DIY 8-bit Computer auf Basis eines 65C02 Prozessors zu beschäftigen. Ich hatte bereits ein 4x16 Zeichen LCD Modul und ein 4x4 Keypad angeschlossen und konnte einfache Programme und Menüs auf dem Computer laufen lassen.

vim-ca65 highlights instructions, labels, literals, macros and assembler functions. An Arduino is conencted to one of the VIAs of the  6502 breadboard computer.

Umstieg auf ca65

Zusätzlich bin ich auf einen anderen Assembler, nämlich ca65, umgestiegen. Dieser ist für ambitionierte Projekte besser geeignet als Vasm, zum einen durch die Trennung in Assembler und Linker, zum anderen da er Features wie scopes, structs, enums und macros unterstützt.

Ich habe außerdem ein Vim Plugin für ca65 geschrieben. Dieses bietet Syntax Hervorhebung für den Code und die Assembler Funktionen sowie ein paar nützliche Vim-Funktionen und Vim-Hilfe für die Opcodes (erstellt aus dem Buch "Programming the 65816") hinzufügt. Sehr nützlich, wenn man beispielsweise mal nicht sicher ist welche Status-Flags der bit Befehl updatet, reicht ein :help ca65-bit um alle Infos zum Befehl zu bekommen.

Verbindung mit Desktop PC

Das wirkliche große Hindernis für eine schnelle Entwicklung des Computers ist der iterative Prozess des Debuggens: Funktioniert etwas nicht, muss man eine mögliche Fehlerquelle im Code suchen, den Code kompilieren, den EEPROM ausbauen und mit dem Code beschreiben und ihn dann wieder einbauen. Das dauert lange und strapaziert die Beine des EEPROMs. Schön wäre es also, Code direkt vom Desktop auf den 6502 zu schicken. Dafür bietet sich eine serielle Verbindung an, die mit den bereits 6522 Interface-Adaptern gut umsetzen lässt. Diese haben 8-Bit Schieberegister, die auch über eine externe Clock betrieben werden können.

Ich habe also einen Arduino Nano per USB mit meinem Desktop verbunden und 2 der digitalen GPIO Pins an CB1 und CB2 des 6522. Der Desktop kann nun den Binärcode an den Arduino senden und dieser sendet ihn dann über das Serial Peripheral Interface Protokoll (SPI) an den 6522. Nach einem gesendeten Byte löst der 6522 einen Interrupt aus und der Prozessor kopiert das Byte in einen Puffer im Arbeitsspeicher. Wurden alle Bytes übertragen, kann man mit dem jmp Befehl an den Beginn der geladenen Bytesequenz springen und führt somit den geladenen Code aus.

VIA Hardware Bug

Das Ganze hat an sich ziemlich gut funktioniert, allerdings wurde oft 1 Byte zu wenig übertragen. In diesem Fall ist der Prozessor meist "abgestürzt". Nach langer Fehlersuche habe ich schließlich herausgefunden, dass der 6522 Interface-Adapter (auch der 65C22) einen Hardware-Bug haben: Wechselt die Clock am Schieberegister in dem Moment in dem die Systemclock PHI2 von 1 auf 0 geht, wird der Übergang ignoriert. In diesem Fall wird ein Bit zu wenig registriert. Das führt dann zu sogenannten "framing" Fehlern, d.h. Bit 0 des nächsten Bytes wird zu Bit 7 des letzten und man liest nur noch Müll ein. Ich musste also dafür sorgen, dass die SPI Clock nie während umschaltet während PHI2 fällt. Dafür habe ich die SPI Clock an einen von PHI2 getakteten D Flip-Flop angeschlossen. Dadurch wechselt die SPI Clock immer nur dann, wenn PHI2 von 0 auf 1 übergeht.

SOB Pin

Ich habe später mein SPI Programm etwas abgeändert, sodass zuerst immer die Größe der Übertragung als 16 Bit Little Endian Zahl gesendet wird. Ein Status Byte wurde benutzt, um den derzeitigen Status im Interrupt Handler zu nutzen: Wird auf das erste Byte gewartet, ist Bit 7 (negativ) des Status Bytes gesetzt. Wird auf das zweite Byte gewartet, ist Bit 6 (overflow) gesetzt. Für alle nachfolgenden Bytes, also den eigentlichen Buffer, sind Bit 6 und 7 des Status-Bytes nicht gesetzt. Um also das übertragene Byte richtig zu verarbeiten, habe ich den bit Befehl auf das Status-Byte angewendet und bcs und bvs benutzt. Seltsamerweise wurde manchmal die gesamte Übertragung nach dem ersten Byte für das zweite Byte der Größe gehalten, obwohl das Status-Byte richtig gesetzt war. Nach langer Fehlersuche habe ich schließlich in der Beschreibung von bvs gesehen, dass das Overflow Bit auch durch den physischen Set-Overflow (SOB) Pin gesetzt werden kann. Die Existenz dieses Pins hatte ich nach über zwei Jahren total vergessen. Und siehe da, ich hatte den SOB Pin nicht angeschlossen, was wahrscheinlich dazu geführt hat dass er zufällig das Overflow Bit gesetzt hat. Also habe ich ihn an 5V gehängt und von da an war das Problem gelöst.