Bankswitching beim C64 und C128
der heutige Aufsatz kommt von Hans. Damit ihr ihn in aller Ausführlichkeit genießen könnt gibt es erst am Montag einen neuen Blog von mir.
Aufbauend auf den Artikel von Bernd hier ein paar Details zu den grossen Konkurenten der CPC-Serie. Als erstes wären da die CPUs zu nennen, das sind nämlich keine reinen 6502-CPUs, sondern Abwandlungen davon. Sie sind allerdings Befehlssatzkompatibel. Beim C64 ist das eine 6510 CPU, beim 128er eine 8502 CPU. Beiden gemeinsam ist, das sie über einen 6 Pin Port verfügen, über den das Speichermanagement gesteuert wird. Genutzt werden davon allerdings nur 3 Bits, die anderen drei werden zur Steuerung der Datasette, also des Kassettenrecorders zum Datenspeichern benutzt. Die 8502 CPU im 128er kann ausserdem noch mit der doppelten Taktfrequenz von 2MHz arbeiten. Und beim 128er kommt noch eine programmierbare MMU (Memory Management Unit) dazu, aber dazu später.
Die Speicherchips sind fast identisch; beim C64 sind acht, beim 128er sechzehn 4164 RAM-Chips verbaut. Dazu kommen beim 64er zwei ROMs vom Typ 2364A, eines vom Typ 2332A sowie ein spezielles Color-RAM, Typ 2114L-3. Der C128 hat vier ROMs vom Typ 23128, wovon zwei auch vom Typ 23256 sein können, und einen Steckplatz, d.h. IC-Sockel für ein fünftes 23256 ROM. Ausserdem hat er noch zwei 4416 RAMs für den 80-Zeichen Controller.
Im Gegensatz zum Z80 oder 8086 und anderen Prozessoren kennen 6502 und kompatible CPUs keine separaten I/O-Operationen, d.h. sie haben keine Portbefehle wie IN oder OUT. Der Datentranfer mit I/O-Bausteinen läuft bei ihnen über die normalen Lade- und Speicherbefehle, mit denen auch der RAM-Speicher angesprochen wird. Dem entsprechend benötigen sie einen speziellen Adressbereich, in dem die Register der Peripheriebausteine ansprechbar sind. Das ist der sogenannte I/O-Bereich, der bei den hier behandelten Rechnern zwischen den Adressen $D000 bis $DFFF liegt. Ist dieser I/O Bereich aktiv, dann korrespondiert jede Adresse mit einem Register eines I/O-Chips. Der Grafikcontroller des C64/128 belegt beispielsweise den Adressraum von $D000 bis $D3FF. Schreibt der Prozessor also etwas an die Adresse $D000, so wird dieser Wert in das Register 0 des Grafikchips geschrieben.
Da es in diesem Bereich aber auch RAM-Speicher gibt, muss das Bankswitching dies auch berücksichtigen, indem der I/O-Bereich ein oder ausgeschaltet werden kann. Denn nur wenn der I/O-Bereich deaktiviert ist, kann auf das darunter liegende RAM zugegriffen werden. Daher ist besondere Umsicht geboten, wenn man in diesem Bereich Programmcode ablegt, der auch auf die Peripheriebausteine zugreifen soll; – man hat es in der Regel vermieden. Bliebe noch anzumerken, das man beim C64 aber nie von Bankswitching gesprochen hat, sondern immer nur von Speicherverwaltung, oder -management.
Um die 6 Portpins der CPU programmieren zu können, hat sie spezielle Portregister in den Speicheradressen 0 und 1. In Adresse 0 wird dabei definiert, ob die Portpinne zur Eingabe oder Ausgabe dienen sollen (Datenrichtungsregister). Je nach dem, was man ins Portregister bei Adresse 1 schreibt, werden bestimmte RAM- oder ROM-Bereiche bzw. der I/O-Bereich ein oder aus geschaltet. Da der Prozessor sich den RAM Speicher jedoch auch mit dem Videocontroller teilen muss, der auch regelmässig darauf zugreift, führen die Pinne vom Prozessorport auf einen komplizierteren Spezialbaustein, der den Speicherzugriff zwischen CPU und Videocontroller koordiniert. Dabei handelt es sich um den von Bernd erwähnten ULA. In diesem Fall ein FPLA, also ein Field Programmable Logic Array mit 28 Pinnen. (FPLAs sind eine Untergruppe der ASICs, also der Anwendungsspezifischen ICs; die Programmierung erfolgt dabei durch den Hersteller.) Der von Bernd ebenfalls erwähnte 74LS620 kann das also nicht sein, denn der hat 40 Anschlusspinne.
Der C64 verfügt über 64KB RAM und 20 KB ROM. Die genaue Aufteilung zeigt die Grafik.
Wie man der Zeichnung entnehmen kann überlappt sich der I/O-Bereich ausser mit dem RAM noch mit dem Character ROM. Darin sind für den Videocontroller die Informationen abgelegt sind, wie die im Textmodus darzustellenden Zeichen aussehen sollen. Dann gilt es noch zu berücksichtigen, das der VIC-Chip, d.h. der Grafikchip des C64/128 kein eigenes Video RAM kennt. Er benutzt dafür sowohl im Text- als auch im Grafikmodus den RAM-Speicher des Prozessors. (Beim PC hat man dieses Prinzip bei AGP-Karten verwendet.) Dadurch entfallen im Textmodus 2KB auf den Bildschirminhalt und im Grafikmodus 9KB.
Der PLA-Baustein des C128 ist ein 48-Pin Chip, zu dem sich noch eine frei programmierbare Memory Management Unit (MMU) gesellt. Denn der 128er verfügt nicht nur über doppelt so viel RAM wie der C64, sondern auch über wesentlich mehr ROM, wie man der Abbildung 2 entnehmen kann. Das System ist in der Grundkonfiguration auf 256KB RAM aufrüstbar, und man kann auch noch eine (interne) ROM Erweiterung einbauen. Dafür gibt es einen IC-Sockel auf der Systemplatine. Das RAM ist in Bänke zu je 64KB aufgeteilt; – auf welche Bank der Prozessor zugreift, wird durch die MMU gesteuert. (Hier wurde dann auch erst der Begriff Bankswitching eingeführt.) Dazu arbeitet im 128er auch ein Z80 Prozessor, sofern man ihn lässt. Das ist allerdings nur kurz beim einschalten der Fall, oder wenn man CP/M bootet um damit zu arbeiten. Ein kurzes Testprogramm überprüft nach dem Einschalten, ob eine CP/M Diskette im Laufwerk liegt. Wenn ja, wird davon gebootet, wenn nein, gibt der Z80 die Kontrolle an den 8502 ab, was durch setzen eines Bits in einem MMU-Register erfolgt.
Der Basicinterpreter des C128 meldet beim einschalten, dass 122365 Bytes, also knapp 120 KB frei sind. Die restlichen 8KB werden von Systemvariablen und der Common Area belegt. Basic arbeitet nun so, das der Quelltext in Bank 0 abgelegt wird, und Variablen des Basicprogramms in Bank 1. Gemäss der Initalisierungsroutine vom Basicinterpreter stehen 56½ KB für Quelltext und knapp 63KB für Variablen zur Verfügung. Problematisch wird das nur, wenn ein ca. 50+x KB grosses Basicprogramm mit Grafik arbeiten soll, weil dann 9KB vom Speicher für Quelltext abgezogen werden müssen, in denen dann der Bildschirmspeicher des Videocontrollers liegt. Danach bleiben aber immer noch 47 KB für Quelltext übrig. Ich hab allerdings noch kein C128-BasicProgramm gesehen, das so lang war. Nebenbei ist es mit dem Basic 7.0 recht einfach, Sound und Grafik zu programmieren, da die entsprechende Hardware voll unterstützt wird. Eine Ausnahme bildet da nur der 80-Zeichen Controller, den es im 128er gibt. Der wird vom Basicinterpreter nur begrenzt d.h. nur im Textmodus unterstützt. Der Controller besitzt seinen eigenen Bildschirmspeicher von 16KB, der genauso wie seine vielen Steuerregister nur über zwei Bytes im I/O-Bereich angesprochen werden kann. Dieser Chip kann zwar auch Grafik darstellen, die muss man aber vollständig selbst programmieren. (Das wurde meines Wissens nach aber nur wenig gemacht, weshalb es nicht viele Grafikprogramme gab, die den Chip nutzten.)
Die Common Area ist ein Speicherbereich, der in allen RAM-Bänken identisch ist. In ihr liegen u.a. auch spezielle Routinen des Betriebssystems, die es ermöglichen, das ein Programm, (u.a. der Basicinterpreter) auf RAM Speicher zugreifen kann, der an der gleichen physikalischen Adresse, aber in einer anderen RAM-Bank liegt. Der Basicinterpreter nutzt diese Routinen um einerseits den Quelltext in Bank 0 auswerten (interpretieren) zu können, und andererseits um auf die Variablen in Bank 1 zuzugreifen.
Die Grösse und die Lage dieser Common Area kann durch die MMU programmiert werden. Zur Auswahl stehen 1, 4, 8 und 16KB Grösse, wahlweise am oberen oder unteren Ende der 64KB, die der Prozessor ansprechen kann, bzw. zu gleichen Teilen an beiden Enden. Man kann die Commonarea aber auch ganz abschalten, wenn man es für nötig hält. Diese Möglichkeit zum Verschieben der Common Area ist u.a auch für den Betrieb von CP/M nötig, weil dann Teile des ROM in andere Adressbereiche gemappt werden müssen. Denn CP/M benuzt ja eine andere Aufteilung des Speichers, was in der anderen Prozessorarchitektur begründet liegt. Ebenfalls nutzt das CP/M des 128ers die im ROM vorhandenen I/O-Routinen für den 8502 als BIOS, wobei der Z80 die Kontrolle für I/O Operationen an den 8502 abgibt. Welcher der beiden Prozessoren arbeitet, wird dabei auch durch die MMU gesteuert. Es kann immer nur einer arbeiten, ein Parallelbetrieb funktioniert nicht.
Soweit mal eine Erläuterung zum Bankswitching in den Commodore Rechnern. – Ich hoffe, ich hab nichts vergessen… 😉
Verwendete Literatur:
Larry Greenly u.a.; Das C128 Buch, Sybex, 1. Auflage 1986, ISBN 3-88745618-1
Schieb u.a.; Commodore 128 Intern, Data Becker, 1. Auflage 1986, ISBN 3-89011-098-3
Brückmann u.a.; 64 Intern, Data Becker, 7. Auflage 1988, ISBN 3-89011-000-2
Guter Artikel, nur ist die obere Grafik falsch, die zeigt ebenfalls den Adressraum des C128.
@Arne: in wie fern ist das der Adressraum des 128ers? Und wo genau soll da der Fehler stecken?
Das hat Bernd offenbar schon korrigiert, als der Eintrag online ging, waren beide Grafiken identisch.
@Arne: ach so. Das hab ich nicht mitbekommen. Als ich nachgesehen habe, waren sie so, wie sie sein sollten.