Close

More simplification

A project log for Bootstrapping a ROMless Z80 using RS-232

Is it possible to bootstrap a simple ROMless Z80 system using only two wires - e.g. from an RS232 interface? This project explores this.

willstevenswill.stevens 01/16/2024 at 21:420 Comments

Here is a simpler scheme. Rather than connecting RS-232 TxD to /NMI, it is connected to /RESET, and this is used to reset the CPU whenever HALT is reached. This scheme assumes that all registers except PC (and I and R) are preserved on RESET.

The following instruction sequence is used for programming memory:

23 00100011 INC HL
E5 11100101 PUSH HL
76 01110110 HALT
F6 11110110 OR A,n

This can be obtained using the following assignments:

D7 = A0
D6 = A0 or A1
D5 = 1
D4 = A1
D3 = RTS and /A1
D2 = A0 or A1
D1 = A1 or /A0
D0 = /A1

To initialise HL, set D1 = A1 (with a manual SPST switch). This makes the first instruction LD HL,nn followed by OR A,n (which causes LD HL,nn to be skipped on the second time through the sequence), then PUSH HL, then HALT.  So HL gets set to the value 76E5h.

The sequence can be used to push any desired sequence of bytes onto the stack by selectively omitting the PUSH while counting to the required value of HL. This is done by setting RTS high, so that the sequence becomes DEC HL, EX DE,HL, HALT. Because of the EX DE,HL instruction this must be executed twice to decrement HL once. So HL can be set to any required value and then pushed onto the stack by setting RTS low again. 


Because we don’t know the value of SP when we power on, the first thing we do is use the above scheme to fill RAM with the LD SP,HL instruction. Then we execute this so that SP has a known value.


We then run the programming scheme again starting with the stack at a known location, so that we can fill RAM with whatever we like.


Filling RAM with a constant value can be quick (2 bytes every third time /RESET is set low) - 1Kb in about a 0.15 seconds at 115200 baud. (Assuming each dummy byte sent to TxD causes one reset).


Filling RAM with a program
 would be slower, since on average we must decrement HL by about 32768 before every PUSH HL. That is about 15 million decrements per 1Kb RAM. That is 30 million resets and would take about 3000 seconds at 115200 baud.

The speed can be improved by doing more than one reset per TxD dummy byte - up to 5 can probably be done by transmitting “start bit + 01010101” so 600 seconds to program 1Kb of RAM.

But if we only need to load a short program to do the next stage of bootstrapping, this might only be 100 bytes long, and would only take a minute.
 

Discussions