6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 12:15 pm

All times are UTC




Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Bootstrapping an SBC
PostPosted: Sun Feb 07, 2010 12:23 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
It's often seen as a stumbling block that EPROM programmers are expensive, and yet an SBC needs somehow to have some software to get started.

One approach is to use a single-stepping circuit and toggle the bootstrap into RAM. This is historically authentic but error-prone and tedious!

If the SBC uses an EEPROM, it could be made to be programmable in-place(*), once you've got a way to get your code into the SBC.

Or, combining the two approaches, it would be possible to toggle the bootstrap into EEPROM, so you only need to get it right once.

But in any case the bootstrap should be short. I found myself wondering how short, and this is what I came up with - 27 bytes of utterly untested machine code!

Code:
        ;; sketch of a minimal bootstrap
        ;; suitable to be toggled into an eeprom
        ;; loads up to 256 bytes, to be placed in zero page
        ;; this is minimal! no error checking!
        ;;
        ;; this bootstrap will load a bigger second-stage bootstrap from serial port
        ;; a typical second stage might load a monitor in srecord format
        ;;

        .ORG $FFE5 ; (manually) place the bootstrap up against the reset vector (Edit: Nope! 2 bytes out!)

        ;; for info on 6850 see http://www.electronics.dit.ie/staff/tscarff/6800/6850acia/6850.htm
        .DEFINE         SERIAL_STATUS_REG  $FE08
        .DEFINE         SERIAL_DATA_REG    $FE09

        .DEFINE         EOF                $EA   ; NOP opcode to indicate end of program
                                                 ; (must avoid this value even as a data byte)

bootstrap:
        ; master-reset the UART
        LDA #$03
        STA SERIAL_STATUS_REG

        LDX #0
readbyte:
        LDA SERIAL_STATUS_REG   ; bit 0 tells us if there is a byte to read
        ROR
        BCC readbyte
        LDA SERIAL_DATA_REG
        CMP #EOF    ; check for end of second stage
        BEQ 65536   ; jump to second stage at bottom of zero page
        STA 0,X
        INX
        BNE readbyte

        .word bootstrap  ; the 6502 reset vector

In hex, that's
Code:
FFE5   A9 03
FFE7   8D 08 FE
FFEA   A2 00
FFEC   AD 08 FE
FFEF   6A
FFF0   90 FA
FFF2   AD 09 FE
FFF5   C9 EA
FFF7   F0 07
FFF9   95 00
FFFB   E8
FFFC   D0 EE
FFFE   E5 FF


Any comments or ideas on bootstrapping?

(*) Edit: I think some EEPROMs are particularly easy to program, but I might be mistaken.


Last edited by BigEd on Tue Feb 09, 2010 7:07 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Feb 07, 2010 4:34 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1748
Location: Sacramento, CA
27 bytes would not be too hard to do by hand. My COSMAC ELF used a hex keypad to bootstrap a program into ram. I used to write 25-80 bytes using that method.

For my first sbc, I built an eeprom programmer on a breadboard using 4 74LS373 connected to a PC parallel port. One held the data byte, two held the address, and one held the control bits (cs,rd,wr). The cost was under $15 as I used a scrap printer cable.

I had some trouble with the parallel port strobe line not strobing the latches right. I think I ended up using another handshake line for the strobe. I wrote the PC programmer code in QuickBASIC, using the Zicor 28C256 datasheet.

The process was no too complicated, as I recall. However, I had scrounged some 28C256's from a scrapped telecom key system, and I discovered that they had been write protected using a software lock. It took me a while to discover that and to write the unlock code, but I ended up getting it to work. New devices ship unlocked, so that should not even be a factor.

After my SBC-2 was up and running, I scrapped the PC programmer and created a programmer using a 6522 and two 74LS373's. The info on that is on my website under IO Devices.

An even easier solution is right here as well. I am willing to help anyone with programming an EEPROM. For the cost of return postage, I will program anything I'm able. I'm sure there are others here that would also be willing to assist. Just email or PM me with your device to be sure its one I can program.

Once an EEPROM is in a system, it could be reprogrammed in-system if designed to allow it. I have done that also with my SBC-2 system.

Daryl


Last edited by 8BIT on Tue Feb 09, 2010 1:09 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 2:33 am 
Offline
User avatar

Joined: Thu Mar 11, 2004 7:42 am
Posts: 362
The reset vector is at $FFFC, not $FFFE, so your code would have to start at $FFE3.

22 (untested) bytes is what I came up with. 253 bytes are always sent, which are stored on the stack (!) The order the bytes are stored in memory is the reverse of the order they were sent (!!) The RTS uses the last two bytes sent/pushed to jump to the appropriate place in the routine stored on the stack. RTI could be used instead, if you wanted to set up the flags before jumping.

Code:
FFE8 A2 03    LDX #3
     8E xx xx STX status
     9A       TXS
FFEE AD xx xx LDA status
     4A       LSR
     90 FA    BCC $FFEE
     AD xx xx LDA data
     48       PHA
     E8       INX
     D0 F3    BNE $FFEE
     60       RTS
FFFC E8 FF    DW  $FFE8 ;reset vector


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 8:29 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Nice! I had a go with using the stack, but I didn't think of the RTS trick.

(Big oops on the reset vector!)

Cheers
Ed


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 4:22 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
You can get rid of that TXS instruction, since I believe S defaults to $FF upon CPU start up. At the very least, the WDC chips do.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:03 pm 
Offline

Joined: Wed Oct 22, 2003 4:07 am
Posts: 51
Location: Norway
Couldn't you also get rid of the INX if you used 0 as an EOF byte?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:08 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
You can't use a 0-terminator, because 0 is a valid 6502 instruction, and it appears quite often in operands. It's better to transfer a fixed length chunk of binary data which, hopefully, contains valid code. :)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:12 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
But you could almost certainly avoid 0 in the second-stage boot - which only has to load the next stage.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:22 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
It's entirely possible to avoid 0. The problem is, to do so, you need extra code. To load zero into the accumulator, you need to do something like:
Code:
STA $01
EOR $01

and so on. You'll end up consuming more space and running into more bugs than that one little INX instruction is worth.

It also means you cannot (conveniently) access absolute addresses with a zero offset byte (e.g., $0100, $0200, $0300, etc). Again, you would have to work around this by loading X with $01, and using $02FF as your base address. More code. More opportunities for bugs.

If you can somehow get your code down below 14 bytes, you could use a 74154 to decode A0-A3 and construct a diode matrix ROM. Maybe with two chips, you can use 32 bytes of diode ROM.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:27 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
All true, but again, we save a byte in the bootstrap and possibly add a few bytes to the second stage. Any significant program is loaded by the second stage (presumably using a format which supports checksums) and has no such restriction.

Admittedly, saving a byte when we're already down near the 20 byte mark is hardly worth any extra inconvenience, but at this point I think it's a game of assembly golf.

(I think it must have been a typo, but I think Daryl's original response had the appearance of throwing down a challenge to reach 16 bytes.)

Cheers
Ed


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:29 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
Right -- I specified 14 bytes to give enough room for the reset vector. :)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:40 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
kc5tja wrote:
If you can somehow get your code down below 14 bytes, you could use a 74154 to decode A0-A3 and construct a diode matrix ROM. Maybe with two chips, you can use 32 bytes of diode ROM.


I had a thought a bit like that: I think the Apollo Guidance Computer had ROMs implemented as hard wired arrays(*) It's a suitable technology for a retro bootstrap.

In my own case, if the bootstrap is small enough, I'd like to synthesise it into the CPLD.

(*) Quick check tells me that it was hard-wired ROM but using ferrite cores. I had an idea that somewhere in the past was a ROM design using wire alone, although I can't see quite how that would be done.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 7:41 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
Back when I was toying with the Kestrel-1 design, one ROM concept I had was an optical matrix, where matrix rows were illuminated by LEDs, and columns were detected by photo-diodes.

Turned out to be more expensive than I would have liked though. :(


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 9:44 pm 
Offline

Joined: Tue Sep 24, 2002 4:56 pm
Posts: 50
Location: Essex, UK
Hmm... :idea:

It's occurred to me that there's another way of achieving the same effect, and quite easily, too - especially for those of us with (almost any) 8-bit Acorn kit (and some 32-bit kit, too) :D

What I'm thinking of is the "User Port" - for those not in the know, essentially port "B" of a 6522 VIA, wired up to an IDC header under the front edge of the Beeb; a VIA expansion card was also available for most early ARM-based machines, too.

And, of course, if the SBC's VIA's "B" port is hooked up back-to-back the the "User Port", that still leaves VIA's "A" port, and its timers, available to the SBC...

--Martin

_________________
Martin Penny

.sig in beta - full release to follow.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 09, 2010 9:48 pm 
Offline

Joined: Wed Oct 22, 2003 4:07 am
Posts: 51
Location: Norway
I was looking at the docs (because I wondered if it was possible to do LSR status) and noticed that it appears that the code selects 7bit word length, if I read it right. It would be a bit dificult to write a second stage bootloader that couldn't even use load or store opcodes :)



edit: if we dont do neither TXS nor INX, and if LSR status had been possible, and if the 6850 had been in zeropage, then it would have been just 16 bytes total :P


Last edited by Thowllly on Tue Feb 09, 2010 9:56 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: