Understanding and Using the MMU
|Looking for CoCo help? If you are trying to do something with your old Color Computer, read this quick reference. Want to contribute to this wiki? Be sure to read this first. This CoCo wiki project was started on October 29, 2004. --OS-9 Al|
This page was last updated on 04/23/2020. Total Pages: 716. Total Files: 984.
Understanding and Using the MMU
A “Hopefully Helpful” Text file by
Allen C. Huffman
The 6809 CPU can only access 64K at a time. In order for an 8-bit CPU to access memory beyond that range, some sort of Memory Management Unit must be used. The CoCo 3’s MMU does the job nicely by breaking all of the memory into 8K chunks. The CoCo 3 is set up to handle up to 512K of memory which is addressed from &H0000 to &H7FFFF (0 – 524287). The 6809 will recognize the last 64K in this map (&H70000 to &H7FFFF) as “normal” memory for it. (In Basic, when you do a POKE 1024,42 it is actually putting a 42 in physical memory &H70000 + 1024. (If you do an LPOKE 1024,42 you will actually be putting the 42 in physical memory location 1024.) This may seem strange at this time, but hopefully it will soon be clear.
In a 128K Color Computer, the RAM is located from &H60000 to &H7FFFF. (All memory from &H00000 to &H5FFFF is unusable unless you have 512K in which case your extra memory resides there.) The 128K is broken into two parts. One is the normal 64K workspace that the CoCo uses. The other 64K is used for Hi-Res graphics, screens, etc. (For more detail on where everything is, refer to your CoCo 3 owners manual Memory Map on Page 311.)
Meanwhile, back to the MMU, all of the CoCo’s memory is handled internally as 8K blocks. Thus, a 64K workspace is actually 8 MMU blocks. (8 x 8K is 64K, right?) The MMU can access any of these 8K blocks by using the corresponding block number. The blocks are numbered as follows:
## Memory Range ## Memory Range ## Memory Range 00 00000 - 01FFF 10 20000 - 21FFF 20 40000 - 41FFF 01 02000 - 03FFF 11 22000 - 23FFF 21 42000 - 43FFF 02 04000 - 05FFF 12 24000 - 25FFF 22 44000 - 45FFF 03 06000 - 07FFF 13 26000 - 27FFF 23 46000 - 47FFF 04 08000 - 09FFF 14 28000 - 29FFF 24 48000 - 49FFF 05 0A000 - 0BFFF 15 2A000 - 2BFFF 25 4A000 - 4BFFF 06 0C000 - 0DFFF 16 2C000 - 2DFFF 26 4C000 - 4DFFF 07 0E000 - 0FFFF 17 2E000 - 2FFFF 27 4E000 - 4FFFF 08 10000 - 11FFF 18 30000 - 31FFF 28 50000 - 51FFF 09 12000 - 13FFF 19 32000 - 33FFF 29 52000 - 53FFF 0A 14000 - 15FFF 1A 34000 - 35FFF 2A 54000 - 55FFF 0B 16000 - 17FFF 1B 36000 - 37FFF 2B 56000 - 57FFF 0C 18000 - 19FFF 1C 38000 - 39FFF 2C 58000 - 59FFF 0D 1A000 - 1BFFF 1D 3A000 - 3BFFF 2D 5A000 - 5BFFF 0E 1C000 - 1DFFF 1E 3C000 - 3DFFF 2E 5C000 - 5DFFF 0F 1E000 - 1FFFF 1F 3E000 - 3FFFF 2F 5E000 - 5FFFF
That covers the 512K area. On a 128K CoCo, you can’t even use blocks 00 to 2F, so let’s look at what you can use:
30 60000 - 61FFF 31 62000 - 63FFF The first 4 blocks (32K) is where Basic puts the 32 64000 - 65FFF HSCREEN graphics. 33 66000 - 67FFF 34 68000 - 69FFF This is where the HGET/HPUT buffer is. (8K) 35 6A000 - 6BFFF This is the secondary stack area. (8K) 36 6C000 - 6DFFF This is where the 40/80 column screen goes. (8K)
37 6E000 - 6FFFF And this one is unused by Basic. (8K)
That takes care of the 64K you don’t have direct access to on startup. Here is the 64K you do have access to:
38 70000 - 71FFF The first 32K is normal system RAM. (System use, 39 72000 - 73FFF 32 column text screen. PMODE graphics, Basic program 3A 74000 - 75FFF and variable storage) 3B 76000 - 77FFF 3C 78000 - 79FFF The last 32K is where system ROM goes. (Note that 3D 7A000 - 7BFFF on the CoCo 3, all ROM is copied into RAM so these 3E 7C000 - 7DFFF locations are indeed RAM.) 3F 7E000 - 7FFFF
(Notice that all you have to do to convert physical locations to normal 8 bit locations on the older CoCo’s is to remove the 7.)
So now you should have some idea of how memory is looked at, but how do you actually use it? Eight memory locations control what physical block of memory goes where. Let’s have another chart…
FFA0 0000 - 1FFF Remember those block numbers given earlier? FFA1 2000 - 3FFF On startup, FFA0 - FFA7 contain: FFA2 4000 - 5FFF FFA3 6000 - 7FFF 78, 79, 7A, 7B, 7C, 7D, 7E, & 7F. FFA4 8000 - 9FFF FFA5 A000 - BFFF WHY? Shouldn't they be 38, 39, 3A, etc, as the FFA6 C000 - DFFF block numbers would indicate? Read on... FFA7 E000 - FFFF
The MMU locations have bit 6 set high which adds &H20 (64) to their actual value. Therefore, to the MMU 38 is the same as 78, 3E is the same as 7E, etc. The CoCo 3 Service Manual indicates that programmers may use any blocks in the range of 00-3F so we will go by that. Please try not to let this confuse you! Just accept it.
In order to use the MMU from Basic, you simply use the POKE command to tell the MMU what “block” goes where. For instance, location &HFFA2 contains 7A on startup. Anytime you peek memory between 4000-5FFF it is actually PEEKing from block 3A which is physical locations 74000-75FFF. You can change this by POKEing to it. If you POKE &HFFA2,&H30 then anytime you PEEK or use memory in the range of 4000-5FFF it will actually be coming from physical memory 60000-61FFF. Whatever was in block 3A is still there, but when you try to use that memory, the MMU points the CPU to somewhere else. The CPU never knows the difference! To get it back as before, POKE &HFFA2,&H3A.
You may now have a slight understanding of how those Basic HSCREEN save/load routines work. Take a look:
10 INPUT "Save picture as";N$ 20 FOR A = &H30 TO &H33 30 POKE &HFFA2,A 40 SAVEM N$+"/HR"+CHR$(A-&H2F),&H4000,&H5FFF,0 50 NEXT A 60 POKE &HFFA2,&H3A
Line 10 simply asks for what to save the picture as. Line 20 does a loop. If you notice 30-33 is the physical location of the hi-res HSCREENs. The poke in line 30 switches the physical location pointed to by “A” into CPU location 4000-5FFF. (The first time through, block 30 is there, then 31, then 32, etc.) After this, line 30 does a SAVEM of whatever is now at that location. (It tags the extension of HR at the end followed by a number 1-4). Line 50 continues the loop and line 60 restores the memory like it was before this routine.
Programmers out there might think this is strange seeing a program save the same contents of memory (4000-5FFF) four times, but that is where the magic of the MMU comes in. Thanks to the POKE, each time the program gets to that line the MMU points to a different area. To load a file back in, a similar routine must be used that flips the MMU to that area then, after loading, flips it back where it goes. It might look something like this:
10 INPUT "Load picture";N$ 20 INPUT "HSCREEN #";H 30 HSCREEN H 40 FOR A = &H30 TO &H33 50 POKE &HFFA2,A 60 LOADM N$+"/HR"+CHR$(A-&H2F) 70 NEXT A 80 POKE &HFFA2,&H3A
If you can understand why this program works, you are in good shape. By theory, someone could save the entire memory of the Color Computer to disk in 8K chunks using the above method. (Why? I don’t know, but they could…)
Now if you still don’t see how this works, try this experiment. Enter the following line which will fill up physical block &H37 (6E000-6FFFF) with the value of 42.
FOR A=&H6E000 TO &H6FFFF:LPOKE A,42:NEXT A
Okay. So all the memory from 6E000 to 6FFFF should have 42s in it, right? Right. (To verify, you could do FOR A=&H6E000 TO &H6FFFF:PRINT LPEEK(A):NEXT A and you would get 42s back.)
Somewhere in memory we have a block of 42s. We can make that block appear to be somewhere else. Try a POKE &HFF2A,&H30. You have just set it so whenever the CPU looks at locations 4000-5FFF it will really be looking at 60000-61FFF. Confirm this and try:
FOR A=&H4000 TO &H5FFF:PRINT PEEK(A);:NEXT A
You will see a bunch of 42s. Magic, right? No, just amazing. Still not convinced? Type POKE&HFF2A,&H3A and try that previous line again. What happened to the 42s? They are still where they were originally but, the CPU is being directed back to where it was supposed to be.
This is just the start of what the MMU can do. There is another bank of MMU registers from FFA8 to FFAF. These are being used by the CoCo itself while in basic, but any machine language programmer could define each set of MMU registers and then by toggling a single bit (bit 0 of FF91) he could select between which MMU map would be used.
If you still haven’t got it, leave a message for me and I will do my best to answer questions or to create another file that further explains the MMU.