Dr Jefyll wrote:
Speaking of "a lot less wiring required," somewhere on the net I saw a bootup scheme for Z80 in which the host computer connected only to the Z80 clock and interrupt lines. (And reset, I guess, but still it was downright astonishing.) The gist of it was to stick the bytes in memory using the stack pointer as it responds to interrupts. You can control what byte-value gets pushed by controlling what address you're at before the interrupt hits -- and that, in turn, is controlled by clocking through piles of NOPs. (I know I'm missing a lot of details, because I make it sound pretty easy.) Anyway, it sure opened my eyes about what can be accomplished, even with absurdly restrained resources.
-- Jeff
This intrugues me. I have thought of a way to make similar system with a 6502.
There are two main difficulties that must be overcome. Firstly, the SP starts in an unknown state. Secondly, an interrupt also causes the status register to get pushed to the stack.
So, here's the plan:
The microcontroller (MCU) is connected to clock, NMI, reset on the 6502. It also controls the CE signal for the RAM.
The 6502 data pins are pulled up/down into the NOP instruction. Data pin 5 will also be connected to the MCU as an input (I'll explain why shortly).
That's a total of 5 MCU pins.
Boot process:
The RAM CE pin is unasserted.
The MCU resets the 6502. The PC is now 0xEAEA.
The MCU clocks in NOPs until the program counter is 0x0000.
At this point, the MCU enables the RAM, triggers an NMI, and then disables RAM again, pushing 0x0000 somewhere on the stack. It also pushes the status register, which always has bit 5 set.
The MCU clocks in NOPs until the program counter is 0xFFFF. At this point, it triggers another NMI in the same way.
This process of pushing 0xFFFF is repeated, until the stack is full. (After each NMI, the PC will be at 0xEAEA again, so more NOPs will be needed for each push.)
Now, the MCU clocks in NOPs until the PC is at the start of the stack.
During the instruction read cycle, the MCU temporarily enables the RAM, and reads the value of D5 - If it is low, then it must be the 0x00 that was pushed previously.
The RAM is then disabled again so that only NOP is actually executed.
It scans through the stack by executing NOPs until it finds the 0x0000 sequence. When we find it, we can now deduce the current value of the stack pointer. (Problem 1 solved!)
Then, the MCU triggers NMIs until the SP is 0xFF.
Using the NMI technique, the MCU pushes 0x68 onto the stack. We now have the PLA instruction at a known memory location.
When we want to run the PLA instruction, we NOP until the PC is in the right place, and then enable the RAM when the instruction is being read.
Because we can now run PLA after each stack push, we can write continuous data to the stack (The status register part of the stack can be overwritten).
At this point, we can write a second-stage bootloader onto the stack. This secondary stage bootloader can read in data, one bit at a time, using bit 5 of the data bus.
I hope all that made sense!
P.S. After some more thinking, any bit could be used, rather than bit 5 - The 0x0000 sequence will still be detectable even if the status register state is unknown.
Edit:
If D0 was chosen for the MCU input, it would simplify things. Rather than pushing 0x0000 and 0xFFFFF, we could simply push 0xEAEA and 0xEBEB (since only the LSB matters, and the PC will be 0xEAEA after each NMI)