MMU-16
Inhaltsverzeichnis
MMU - Memory Management Unit
Eine MMU verwaltet den Verfügbaren Arbeitsspeicher eines Computer System. Im Falle einer 8 Bit CPU, die einen sehr eingeschränkten Adressraum hat, wird durch den Einsatz einer MMU der Adressraum stark erweitert. Der Adressraum einer Motorola 6809 CPU ist auf 64K beschränkt, man spricht vom logischen Adressraum. Die MMU hingegen hat einen viel größeren Adressraum von mehreren MB, das bezeichnet man als physischen Adressraum.
Die Idee hinter der MMU ist es, den logischen Adressraum der CPU in kleine Blöcke zu teilen. Jeder Block kann dann irgendwo im physischen Adressraum verschoben werden. Damit steht der gesamte physikalische Adressraum im Zugriff der CPU, natürlich nur stückweise.
Je kleiner die Größe eines Blocks gewählt wird, desto flexibler kann die Sicht auf den physikalische Adressraum gestaltet werden. Allerdings vergrößert sich der Verwaltungsaufwand, je kleiner die Blockgröße gewählt wird.
Jeder Speicherzugriff der CPU ist immer ein Zugriff in den logischen Adressraum (64K).
Die MMU rechnet jeden Speicherzugriff um, von der logischen Adresse zur physikalischen Adresse.
Die Umsetzung von logischer auf physikalischer Adresse erfolgt durch ein sehr schnelles RAM, das 'Mapping RAM' (MRAM).
Das ist insbesondere bei einer 3MHz CPU eine ziemliche Herausforderung.
Die MMU-16
Für die Motorola 6809 gibt es einen perfekt passenden Speicher Manager, die Motorola MMU 6829. Leider ist die MMU 6829 heutzutage sehr schwer zu bekommen. Aus diesem Grund habe ich die MMU-16 entwickelt. Die MMU-16 besteht aus diskreten Bauteilen.
Die MMU-16 ist weitgehend kompatibel zur Motorola 6829.
Allerdings hat die MMU-16 ein deutlich größeres Mapping RAM (2x 8KB).
Damit unterstützt eine einzelne MMU-16 bis zu 256 Tasks.
Zudem hat das MRAM gleich 16 Bit, anstatt nur 10 Bit bei der 6829. Von den 16 Bit werden 13 Bit für die Bildung der physikalische Adresse verwendet. Damit kann die MMU-16 einen größeren physikalischen Adressraum verwalten (bis zu 16MB).
Die restlichen 3 Bit steuern den Speicher Zugriff (lesen, schreiben, ausführen). Damit kann man zum Beispiel eine RAM Seite auf lesenden Zugriff beschränken, sodass es für die CPU wie ROM aussieht.
Die MMU-16 Hardware
Die Umsetzung von logischer zu physikalischer Adresse erfolgt also über ein schnelles SRAM. Das SRAM sollte bei einer 3MHz CPU mindestens 12nS Zugriffszeit haben. Besser sind 10nS um auf der sicheren Seite zu sein.
Übliche SRAM mit 10nS Zugriff haben eine Datenbreite von 8 Bit. Also benötigen wir zwei dieser SRAM Bausteine. Die übrigen 6 Bit kann man sinnvoll nutzen, um den physikalischen Adressraum noch weiter zu vergrößern und/oder andere Dinge zu machen (Access Flags).
Der SRAM übernimmt im Betrieb die Umsetzung von logischer zu physikalischer Adresse. Aber der SRAM muss ja irgendwie einen sinnvollen Inhalt bekommen. Die CPU muss daher den vollen Zugriff auf dieses Mapping SRAM haben. Da kommt der CPLD ins Spiel. Er übernimmt die Aufgabe, alle Funktionen der MMU zu steuern (Register etc.).
- Die MMU-16 braucht folgende Bauteile zur Funktion
- SRAM zur Umsetzung von logischer auf physikalische Adresse (2x 8KB)
- CPLD 1: Adressen MUX für M-RAM, Takterzeugung für CPU, Adressen Selektor
- CPLD 2: MMU Register und MMU Steuerung
Die Platine enthält die CPU 6809EP, eine MMU-16 und den IO Decoder (3 zu 8 Demultiplexer). Die Stiftleiste links geht zum Byte Machine Mainboard. Die Stiftleiste rechts ist für den Anschluss eines IO Boards.
Das SRAM
Die Umsetzung von logischer auf physikalischer Adresse benötigt in der MMU 6829 exakt 10 Bit. Übliche SRAM Bausteine haben eine Datenbreite von 8 Bit. Also benötigen wir zwei dieser SRAM Bausteine. Die übrigen 6 Bit kann man sinnvoll nutzen, um den physikalischen Adressraum noch weiter zu vergrößern und andere Dinge zu ermöglichen (Access Flags).
Einen Arbeitsspeicher von 2MB ist ausreichend für einen 8 Bit Computer. Andererseits ist Speicher heutzutage sehr preisgünstig zu haben, und man muss den möglichen Adressraum ja nicht vollständig nutzen. Daher werden 3 der übrigen Daten Bits benutzt, um den Adressraum von 2MB auf maximal 16MB zu erweitern.
Die übrigen drei Bits sind Flags, die besondere Dinge beim Zugriff auf den Arbeitsspeicher steuern. Sie steuern die Rechte auf den Speicherblock: lesen, schreiben, ausführen. Manchmal ist es sinnvoll, den Zugriff auf das RAM zu beschränken auf nur lesenden Zugriff (Ram als ROM verwenden). Genauso kann man auch den lesenden Zugriff beschränken. Die Ausführung von Code sollte vom OS beschränkt werden auf eigene Segmente, die nicht beschrieben werden können.
Motorola 6829 | MMU-16 | |
---|---|---|
Blockgröße | 2K | 2K |
Adressraum | 2MB | 16MB |
Access Flags | 0 | 3 |
Anzahl Tasks | 4 | 256 |
Unsere MMU hat nun 32 Blöcke zu 2K im logischen Adressraum der CPU. Jeder Block kann im gesamten physischen Adressraum von 16MB bewegt werden (in 2K Schritte). Jeder Block hat drei Bit für die Zugriffsrechte.
Der physische Adressraum ist unterteilt in 8192 Seiten (2K * 8192 --> 16MB). Jeder der 32 Blöcke hat also eine Seiten Nummer (Page#). Die Seiten Nummer plus 3 Zugriffsbit benötigen insgesamt 16 Bit (2 mal 8 Bit --> 2 SRAM Bausteine je 8 Bit).
Die SRAM Bausteine haben 8K, 16K oder 32K. Alle drei Arten verwenden dasselbe Pinout und haben dieselbe PIN Belegung. Verwendet werden immer nur 8KB, deshalb kann man die RAM Art frei wählen, auch gemischt.
Die CPU sieht zu jedem Zeitpunkt immer nur 64KB (logischer Adressraum), also 32 Blöcke. Jeder Block liegt auf einer bestimmten Seite im physischen Adressraum. Diese 'Sicht' auf den physischen Speicher nennt man 'MAP' (Memorty MAP). Jede MAP wird beschrieben durch 32 Worte zu 16 Bit. In jedem der beiden SRAM Bausteine belegt eine Memory MAP exakt 32 Byte. Aus Sicht der CPU sind das 64 Bytes.
Ein SRAM mit 8KB kann 256 Memory MAPs speichern (32 * 256). Die Auswahl der MAP erfolgt über die Task# Nummer. Die Task# Nummer geht von 0 bis 255. Die Task# Nummern 0 und 1 haben besondere Bedeutung: Task#0 ist der System Task mit besonderer Zugriffs Berechtigung. Der Task#1 ist reserviert für DMA Zugriffe. Task# 2 bis 255 sind Benutzer Tasks. Die aktive Task# Nummer entspricht den Adressleitungen RA5 bis RA12 der SRAM Bausteine.
Warum braucht man mehrere Memory MAPs? Das braucht man dann, wenn man mehrere Programme gleichzeitig ausführen möchte, oder wenn man OS (System Task) und das Benutzer Programm trennen möchte. Hätte die MMU nur eine MAP, so müsste man bei jedem Task Wechsel alle 64 Byte umschreiben. So genügt ein Schreib Zugriff, die Task# Nummer.
Ein gutes OS trennt die Memory MAP der Benutzer Programme gegeneinander und von der eigenen Memory MAP. Dadurch bleibt das System stabil, auch wenn ein Programm 'abstürzt'. Jedes Benutzerprogramm ist in seiner eigenen 64K Welt gefangen und kommt nicht heraus. Böswilliger Schadcode kann den Speicher nicht verwüsten, er kann nur in der eigenen Memory MAP Änderungen vornehmen. Der Zugriff auf Ressourcen kann vom OS verwaltet werden oder einem bestimmten Task zugeordnet werden. Dadurch ist alles gesteuert und geordnet, es entsteht kein Chaos durch Zugriff gleichzeitig von mehreren Tasks.
Der CPLD
Die Umsetzung von logischer Adresse (16 Bit) zu physikalischer Adresse (24 Bit) wird vom Mapping RAM übernommen. Der CPLD ist daran nicht beteiligt.
Der CPLD hat folgende Aufgaben:
- Bereitstellung von Register zur Steuerung der MMU
- Schreibzugriff auf den Inhalt des Mapping RAM
- Adressdekodierung für MMU Fenster
- Adressdekodierung für externe Speicher und IO
- Task# Verwaltung
MMU-16 - Funktion
MMU Speicherfenster
Die MMU ist sichtbar für die CPU in einem MMU Speicherfenster . Das MMU Fenster hat eine Größe von 128 Byte. Normalerweise liegt das Fenster an der logischen Adresse $FF00 bis $FF7F. Aber es kann prinzipiell auch an eine andere Adresse verschoben werden. Das MMU Fenster ermöglicht den Zugriff auf das Mapping RAM sowie auf die MMU Register.
Die ersten 64 Byte des MMU Fenster ($FF00 bis $FF3F) sind reserviert für den Zugriff auf das Mapping RAM. Die restlichen 64 Byte ($FF40 bis $FF7F) sind für MMU Register reserviert. Wobei nur einige wenige Speicherzellen wirklich verwendet werden.
Das MMU Fenster ist nur sichtbar für den Task# 0 (Systemtask). Alle anderen Tasks sehen die MMU nicht, es kann auch nicht Mapping eingeblendet werden. Daher haben alle Benutzer Tasks und auch das DMA Zugriff auf die gesamten 64KB logischen Adressraum. Es geht kein Byte verloren durch MMU oder IO.
Der System Task sieht das MMU Fenster IMMER an seiner logischen Adresse, diese 128 Byte können nicht ausgeblendet werden.
Die Funktionen der MMU werden über die MMU Register gesteuert. Die Register sind weitgehend kompatibel zur Motorola MMU 6829, sodass ein Umstieg sehr einfach durchgeführt werden kann:
- --- MMU Register -----
- KV MMU0 to KV MMU7 ($40 - $47)
- Diese 8 Register sind für dier MMU-16 irrelevant.
- (Damit kann man bis zu 8 Stück MC6829 kaskadieren um von 4 auf maximal 32 Tasks zu erweitern)
- S - System/User Flag Bit ($48)
- Dieses Bit kann nur gelesen werden.
- FUSE - MAP switch Fuse ($49)
- Ein drei Bit Countdown Zähler der die MAP Umschaltung verzögert aktiviert.
- Access Key ($4A)
- Die Task# für den Zugriff des Mapping RAM.
- Das Register steuert, welche MAP im Zugriff steht an den Adressen $00 bis $3F.
- Operate Key ($4B)
- Die Task# für den aktiven Task.
- Das Register steuert, welche MAP für den operativen Betrieb verwendet wird (Task# Nummer).
- Der Wechsel zur eingestellten MAP erfolgt aber erst durch einen Schreibzugriff auf das FUSE Register.
Mapping RAM
Das Mapping RAM setzt direkt die logische Adresse um in eine physikalische Adresse. Dazu sind die CPU Adressleitungen LA11 bis LA15 an den Adresspins des Mapping RAM angeschlossen (A0 bis A4). Der CPLD ergänzt die Adresse des Mapping RAM mit der Tasknummer (A5 bis A12). Das im Mapping RAM gespeichert Byte dient als physikalische Adresse (PA11 bis PA23).
Das Mapping RAM gibt 16 Bit aus, 3 Bit sind Access Flags und 13 Bit für die physikalische Adresse. Es werden also beide RAM Bausteine gleichzeitig angesprochen an derselben Adresse, da jeder RAM 8 Datenleitungen hat. Das Mapping RAM 0 ist für die Adressleitungen PA11 bis PA18 zuständig. Das Mapping RAM 1 ist für die Adressleitungen PA19 bis PA23 zuständig sowie für die drei Access Bits.
Für die Konfiguration einer Memory MAP muss man das Mapping RAM beschreiben. Eine MAP besteht aus zwei mal 32 Byte. Aus Sicht der CPU sind das 64 Speicherzellen. Diese 64 Byte sieht die CPU im MMU Fenster an der Offset Adresse 0 (Byte 0 bis 63 im Fenster). Das MMU Fenster liegt normalerweise an der logischen Adresse $FF00 und ist nur für den Systemtask (Task# 0) sichtbar. Das Memory MAP liegt also an der Adresse $FF00 bis $FF3F.
Es wird dabei immer nur EIN Speicher Baustein zugegriffen. Das Mapping RAM 0 liegt an geraden Adressen und der Mapping RAM 1 liegt an ungeraden Adressen. Die physikalische Adresse für den Block 0 ist an der Adresse $FF00 (PA11 bis PA18) und $FF01 (PA19 bis PA23) gespeichert. Der Block 1 ist im Adresspaar $FF02/$FF03 und so weiter. Der oberste Block (Block 31) ist im Adresspaar $FF3E/$FF3F gespeichert. Ab $FF40 beginnen die MMU Register.
Der CPLD sorgt dafür, dass die CPU den Mapping RAM zugreifen kann. Wenn der Systemtask aktiv ist und die logische Adresse im Bereich von $FF00 bis $FF3F liegt, dann selektiert der CPLD das Mapping RAM. Zusätzlich arbeitet der CPLD als MUX, die logische Adresse wird unterschiedlich auf den Adressbus des Mapping RAM gelegt. Normalerweise werden die logischen Adressleitungen LA11 bis LA15 verwendet, im MMU Fenster werden jedoch die Adressleitungen LA1 bis LA5 verwendet sowie die LA0 für die Selektion von RAM-0 und RAM-1. Weiters wird das /WE Signal der beiden Mapping RAM Bausteine gebildet, wenn das Mapping RAM selektiert ist.
Adressdekoder
Der CPLD erzeugt auch die Signale für das BM Mainboard: /RD, /WRT, ROM
Wenn die MMU adressiert wird, dann sind /RD und /WT auf high, das BM Mainboard ist inaktiv. Ansonsten wird R/W umgesetzt auf die Signale /RD und /WRT für das BM Mainboard.
Im Falle einer Zugriffsverletzung wird der externe Speicher nicht zugegriffen. Es erfolgt keine Selektion des externen Speicher über /RD und /WRT. Erfolgt die Zugriffsverletzung beim Fetch (Execute Access), dann wird ein NMI ausgelöst. Das OS muss diese Zugriffsverletzung dann entsprechend behandeln.
Task# Verwaltung
Spezielle MMU Bits
Es gibt spezielle Bits in der MMU, auf die man keinen direkten Einfluss hat:
- Reset Bit
- Das System Bit (Task# 0)
Das Reset Bit wird gesetzt, wenn die Reset Leitung auf Low gezogen wird. Die MMU läuft nun in einem speziellen Reset Modus:
- Physikalische Adressen A11 bis A23 sind immer high
- Das System Bit ist automatisch aktiviert
Die physikalische Adressbits der MMU sind alle high. Das bedeutet der Adressraum ist auf 2KB beschränkt, und zwar auf die oberste Page (Page# 8191). Also auf die höchste physikalische Adresse die es gibt. Dort MUSS ein ROM sein, denn die CPU führt als erstes ein Fetch aus auf den Reset Vektor. Der Reset Code muss ebenfalls in den obersten 2KB liegen, denn es sind ja nur die obersten 2KB sichtbar für die CPU.
Das MMU Fenster ist sichtbar, denn die MMU ist im System Modus (Task# 0). Daher darf der Reset Code nicht in dem Adressen Bereich liegen, wo das MMU Fenster liegt.
Achtung: Da die oberste Page ein ROM sein muss, hat die CPU nach dem Reset kein RAM zur Verfügung! Daher dürfen keine CPU Befehle ausgeführt werden, die RAM benötigen!
Bei der Motorola 6829 wird der Reset Modus beendet, sobald die CPU das KV (Key Value) Register beschreibt. Das KV Register dient dazu, dass die Anzahl der Tasks durch Einsatz weiterer MMU Bausteine skaliert werden kann. Nun die MMU-16 hat von Haus aus 256 Tasks und benötigt daher das KV Register nicht. Um kompatibel zu sein, wird auch bei der MMU-16 die Adresse des KV-0 Register ($FF40) verwendet, um den Reset Modus zurück zu setzen.
Bevor der Reset Mode beendet wird, muss unbedingt die Memory MAP für Task# 0 konfiguriert werden! Sobald der Reset Modus beendet wird, werden die physischen Adressleitungen PA11 bis PA23 nicht mehr vom CPLD kontrolliert. Das Adressen Mapping wird aktiviert, die Signale PA11 bis PA23 werden nun vom Mapping RAM kontrolliert. Deswegen muss das Mapping RAM zu diesem Zeitpunkt konfiguriert sein!
Das System Bit wird gesetzt, wenn ein Interrupt ausgelöst wird (IRQ, FIRQ, NMI, SWIx). Die MMU läuft nun im System Modus (Task# 0):
- Der operative Task wird auf 0 gestellt (System Task), unabhängig davon, was im OPKEY Register steht
- Das System Bit wird automatisch aktiviert
Die Memory MAP des System Task ist aktiv, wodurch automatisch die Interrupt Vektoren aus der System MAP gelesen werden. Die CPU führt den entsprechenden Code in der System MAP aus. Die Umschaltung zur System MAP erfolgt NACHDEM die CPU die Rücksprungadresse und die Register auf den Stack gelegt hat. Diese Daten befinden sich also auf dem Stack in der MAP des Benutzer Task.
Der System Modus wird beendet, indem man das FUSE Register beschreibt. Das FUSE Register ist ein 3 Bit Register, das als Zähler (Countdown) implementiert ist. Es zählt System Takte. Wenn der Countdown Zähler null erreicht, dann schaltet die MMU auf den eingestellten operativen Task# (im Register OKKEY).
Verwendung der MMU-16 im NitrOS9-Board
Die MMU-16 läuft in einem SBC (Single Board Computer), dem NitrOS9-Board.
Memory MAP
Inbetriebnahme
Das Betriebssystem
Das einzige Betriebssystem, das eine MMU unterstützt, ist OS9 ab Level 2. Daher habe ich NitrOS9 Level 2 angepasst für mein NitrOS9 Board mit MMU-16. Die Basis dafür ist der Quellcode des NitrOS9 für den großartigen Positron 9000 Computer.
Reset Modus
Durch einen Hardware Reset wird in der MMU das Reset Bit gesetzt. Die MMU ist dann in einem speziellen Modus: Reset Modus
Das Reset Bit ist notwendig, weil das Mapping RAM nach dem einschalten einen nicht definierten Inhalt hat. Dadurch wäre das ganze System in einem undefinierten Zustand und könnte nicht richtig gestartet werden.
Zusammenfassung Reset Bit:
- das Reset Signal setzt das Reset Bit, die MMU ist im Reset Modus
- im Reset Modus ist das Mapping RAM inaktiv, alle physikalischen Adressleitungen sind high
- im Reset Modus kann das Mapping RAM beschrieben werden, wie im SU Modus
- das Reset Bit wird zurück gesetzt, sobald man da OP-Key Register beschreibt
System Modus
Durch einen Interrupt (Hardware oder Software Interrupt) wird in der MMU das System Bit gesetzt. Die MMU wechselt dadurch automatisch in den System Modus (oder auch Super User Modus). Solange das System Bit gesetzt ist, ist die MMU immer Task# 0 (System Task). Die Memory Map ist die System Map und die MMU Register sind im Zugriff. Normalerweise wird nun Betriebssystem Code ausgeführt. Das System Bit wird zurückgesetzt, indem man einen Task Wechsel zu einem Benutzer Task durchführt.
Zusammenfassung System Bit:
- ein Interrupt setzt das System Bit, die MMU wechselt in den System Modus
- im System Modus ist immer der Task# 0 (System Task) aktiv
- im System Modus ist die System Memory Map aktiv
- im System Modus ist hat man Zugriff auf die MMU Register und das Mapping RAM
- das System Bit wird zurück gesetzt, sobald man das FUSE Register beschreibt und der FUSE Counter null erreicht
Benutzer Modus
Der Benutzermodus ist quasi der 'Normalbetrieb'. Die CPU führt einen Benutzer Task aus und ist auf die eingestellte Memory MAP beschränkt. Die MMU Register und das Mapping RAM sind nicht im Zugriff, ja sogar vollkommen unsichtbar. Der MMU Speicherbereich ist komplett nutzbar durch die eingestellte Page.
Im Benutzermodus kann das OS aufgerufen werden durch einen Software Interrupt (SWI Befehl).
Hardware Interrupts werden durch das OS bedient. Es funktioniert im Prinzip genau wie ein Taskwechsel.
DMA Zugriffe funktionieren auch ohne Hilfe des OS. Während eines DMA Zugriff wechselt die MMU automatisch in den Task# 1. Die externe Hardware 'sieht' die Memory MAP der Task# 1 die durch das OS konfiguriert wurde.
Start Sequenz
Nach einem Reset fetched die CPU den RESET Vektor von der logischen Adresse $FFFE und führt den Code aus. Die MMU ist nach einem System RESET im Reset Modus. Die Adressleitungen PA11 bis PA23 sind high, daher wird der Reset Vektor gelesen von der physischen Adresse $FFFFFE in der obersten Page (Page 8191). Es läuft privilegierter Code, die MMU Konfig Register sind sichtbar an der Adresse $FF00 bis $FF7F.
Das erste was die CPU nun zu tun hat, ist die Konfiguration der MMU. Sonst hat man keinen Zugriff außerhalb der Page 8191. Die MMU bekommt nun die Konfiguration unter der NitrOS9 laufen kann. Dann wird der Kern Code gestartet. Je nach Art des NitrOS9 ist entweder das gesamte OS im ROM (20K) oder nur der Kern (4K).
Konfiguration der MMU nach einem Reset:
- der Access Key ($FF4A) wird auf Task# 0 gestellt
- das Mapping RAM für Task# 0 wird beschrieben ($FF00 bis $FF3F)
- das Key Value Register KV-0 ($FF40) wird beschrieben, das beende den Reset Modus und aktiviert das Mapping
- nun kann die Kontrolle dem OS übergeben werden
NitrOS9 Level 2
Eine MMU bietet mehr als nur ein raffiniertes Memory Banking. Geschützte bzw. getrennte Speicherbereiche und priviligierter Code (System Code) machen MMU Systeme perfekt für Multitasking und Multi User Systeme wie das Positron 9000. Allerdings braucht man hierfür neben der MMU Hardware auch ein passendes Betriebssystem, um alle Möglichkeiten der MMU voll nützen zu können. Und hier kommt OS-9 ins Spiel, bzw. der Open Source Pendant NitrOS9.
OS9 ist ein Betriebssystem, das speziell für 6809 System entwickelt wurde. OS9 Level 1 ist für einfache Systeme mit wenig RAM und einfachem Banking. OS9 Level 2 hingegen spielt in einer ganz anderen Liga, es ist für großen Speicher ausgelegt und unterstützt MMU Systeme mit Speicherschutz.
Post Byte Problem
N
News
- 09.06.2022 --
Downloads