rosco-m68k / rosco_m68k

Design, documentation and software for the Really Old School Computer (M68K)
https://rosco-m68k.com
Other
158 stars 35 forks source link

Keep flash mapped to low addresses until manually disabled #428

Closed 0xTJ closed 5 months ago

0xTJ commented 5 months ago

This PR is a small set of changes to GAL and firmware code (no hardware changes) that keeps the flash mapped to the bottom of the memory map until the firmware takes an action to disable it.

It's bothered me a bit that an NMI could arrive before the CPU finishes copying vectors from ROM to RAM, and cause the CPU to end up jumping to whatever the RAM happens to contain. With this change, the ROM remains mapped in the lower 256 KB, but only for reads, even after the initial PC and SP have been fetched. This allows the firmware to copy data from the ROM into the (shadowed) RAM, while always keeping a valid exception vector table mapped at address 0.
Instead of ending after 4 bus cycles, boot mode is exited by the CPU making any Supervisor Data access to any address in the ranges $X40000-$XBFFFF, where X can be any of the 1 MB "banks" (so the middle 512 KB of any 1 MB "bank"). I chose this range as the trigger because it uses only address lines already connected to the glue PLD, and keeps clear of the lower RAM, where the vectors are being copied, the upper onboard RAM, where the stack is, and the (lower 256 KB of the) flash.

Right after copying the vectors from flash to RAM, the firmware makes an access in that range (choosing $040000 here), which then disables boot mode, and the system operates as usual.

With the changes in the address decoder PLD, the ROM only replaces RAM in boot mode for reads to the lower 256 KB of memory. In the glue PLD, instead of a counter to end boot mode, it will end on the first rising edge of /AS at the end of a Supervisor Data cycle to the middle 512 KB of any aligned 1 MB region (a more elegant solution is possible, but this will work with the existing hardware). The boot mode is also entered with /RESET signal assertion, instead of requiring /RESET and /HALT. This was done because /RESET signals a system reset, just not necessarily a CPU reset. This boot mapping behaves effectively like an I/O device, which would normally be reset upon the assertion of /RESET.

I believe that an approach like this is taken on some retro m68k computers. (I may have heard a mention in some YouTube video that this was done with a CPU-controlled I/O device output pin inside some Macs or Amigas, but I'm not sure about that.)

The firmware change is backwards compatible with boards using older PLD code, since it's just a write to onboard RAM. The PLD change will require firmware that includes this write, but this seems reasonable since you'd normally install the latest firmware on a new board.

This has been tested with an MC68010 on a rev. 2.1 board with bodge wires to hook up more address lines to IC5, as are present on later revisions.

I'm not overly attached to this PR (I spent more time writing this text up than actually making and testing the changes :sweat_smile:), so I'm looking for thoughts on this approach.

roscopeco commented 5 months ago

I'm happy to go with this scheme if you think it's a good change 👍

0xTJ commented 5 months ago

I'm happy to go with this scheme if you think it's a good change 👍

Thanks for having a look! On further reflection, I realized that the system going back into boot mode on the RESET instruction, instead of just on a hard reset, could cause problems for software.

The updateflash program uses the RESET instruction, but it looks like it wasn't failing when I was testing because the JMP is a single word, and might already have been before the system is forced back to boot mode. Adding some NOPs there caused a system crash.

I've pushed up a new commit that keeps all of the changes, except for the boot mode being entered on /RESET alone, which now also needs /HALT.

roscopeco commented 5 months ago

I'm happy to go with this scheme if you think it's a good change 👍

Thanks for having a look! On further reflection, I realized that the system going back into boot mode on the RESET instruction, instead of just on a hard reset, could cause problems for software.

The updateflash program uses the RESET instruction, but it looks like it wasn't failing when I was testing because the JMP is a single word, and might already have been before the system is forced back to boot mode. Adding some NOPs there caused a system crash.

I've pushed up a new commit that keeps all of the changes, except for the boot mode being entered on /RESET alone, which now also needs /HALT.

Ah, cool. I'd wondered about that a bit but thought probably fine. Good catch! 👍