[comp.dsp] Building a DSP board, Part Seven: Serial Loader Bootstrap

todd@ivucsb.sba.ca.us (Todd Day) (10/09/89)

Building a DSP board, Part Seven: Serial Loader Bootstrap
---------------------------------------------------------

This is the seventh in a series on how I went about building
a dual Motorola DSP56000 sampling board.

Okay, first off, how did I make this board two channel in,
four channel out?  Well, I told you how to make a single DSP
board (two in, two out).  All you have to do is hook the
second DSP to same input section you made for the first one,
and make another completely new output section for the second
one.

Now we have to make the board boot.  Since I'm using two DSPs,
I'll have to burn two EPROMs.  First, let's find out how the
built-in bootstrap ROM on the 56000 works.

When the 56000 boots, it loads its original operating mode from
some external pins.  There are four different modes.  We want
to set the chip up for a mode 1 initialization.  Mode 1 loads
an external program into internal program RAM (PRAM) and then
switches to mode 2 and starts executing from internal PRAM.
Mode 2 is the standard operating mode.  Mode 1 is a fairly
whacked out operating mode.  The 56000 executes from internal
PROM, reads from external PROM, and then writes to internal PRAM.

The first thing the 56000 does is decide whether to load from
an external byte-wide PROM or load from the byte-wide host
port.  It does this by checking the MSBit of P:$C000 (the P:
prefix means a reference to the program memory, as opposed to
the X: and Y: memories).  We set this bit high (we want it to
boot from EPROM) by tying D23 to +5V through a 10k resistor.
The 56000 then selects 15 wait states (more than enough for our
slow 250ns EPROM) and begins loading the PRAM from the EPROM.

Now, how does the 56000 map 8 bit-wide bytes into 24 bit-wide
words?  Let's have a look:

EPROM		PRAM
$C000		$0000 low byte
$C001		$0000 middle byte
$C002		$0000 high byte
  .		  .
$C5FD		$01FF low byte
$C5FE		$01FF middle byte
$C5FF		$01FF high byte

Note that the PRAM loading is the Intel bassackwards method of
LSB MSB instead of the awesome Motorola method of MSB LSB.  Go
figure...

Now, I didn't feel like dealing with the $C000 decoding, so I
just hooked up the lower address bits to the EPROM (I used a
2716) plus the P address bank selector.

So, after the 56000 is done loading from the EPROM, it switches
to operating mode 2 (maps PRAM to program fetching as well as
P: writing) and boots the program it just loaded from P:$0000.

Here is the program that I blasted into my EPROM.  I think it
is documented fairly okay, so I won't say anything else.

Next time: initializing all of your hardware

----------------------------------------------------------------------
; sloader.asm
; Wed Aug  2 23:56:14 PDT 1989
; This file originally came from Motorola's Dr. BuB DSP board.
; Slightly modified by Todd Day (todd@ivucsb.sba.ca.us)
;	to echo characters received.

;       Serial Loader for the DSP56000.
;       This loader initializes the serial communications interface (SCI)
;       on the DSP56001 for 9600 baud and then loads OMF records (output
;       by the DSP56000 assembler) into internal memory.  The loader takes
;       the upper 128 bytes of P memory allowing the lower memory from
;       $0000-(LDRMEM-1) to be used by the user.  The following records are
;       interpreted:
;           _DATA X ADDR
;           _DATA Y ADDR
;           _DATA P ADDR
;           _END ADDR
;       After the END record is encountered, the loader jumps to the address
;       in the END record.  Note that an address MUST be present in the
;       END record (the program must contain at least one P segment).
;
;       To generate a EPROM of this loader (8Kx8), perform the following:
;       $ asm56000 -b -l -a sloader
;       $ srec sloader
;
;       The EPROM is in file SLOADER.P.  To program the EPROM, set the
;       programmer to MOTOROLA S record format, download the file with
;       a zero address offset and program the part.
;
;	BTW, S record format is LSB MidSB MSB (what! Intel format? :-)
;	Took me a few hours to figure this one out!
;
;	If you don't have the program srec (where can I get this?),
;	you have to do some gnarly contortions on the .LOD file.
;
;	So, if your .LOD file resulting from compiling this program
;	looks like this:
;
;	_START SLOADER 0000 0000
;
;	_DATA P 0020
;	010203 040506 070809
;	_END 0020
;
;	then, program your PROM with this sequence:
;	$0020	0302  0106  0504  0908  07..... etc. (Fun, eh? :)
;
;
;       The loader loads the following memory spaces:
;           X - 0 to FF
;           Y - 0 to FF
;           P - 0 to LDRMEM-1
;
        PAGE    68,66,1,1

SCR     EQU     $FFF0           ;SCI CONTROL REGISTER
SCCR    EQU     $FFF2           ;SCI CLOCK CONTROL REGISTER
PCC     EQU     $FFE1           ;PORT C CONTROL REGISTER
RDRF    EQU     $2              ;RECEIVE DATA REGISTER FULL FLAG
SSR     EQU     $FFF1           ;SCI STATUS REGISTER
SRXH    EQU     $FFF6           ;SCI RECEIVE IN HIGH BYTE
LDRMEM  EQU     $19D            ;START OF LOADER IN P MEMORY

        ORG     P:$0000         ;RESET VECTOR FOR BOOTING
RVEC
        JMP     LOAD            ;GO EXECUTE LOADER

        ORG     P:LDRMEM,P:3*LDRMEM
LOAD
        MOVEP   #$0302,X:SCR    ;ENABLE TX,RX: 8 BIT 1 START, 1 STOP

				; *** You will probably have to
				; *** change the line below!
        MOVEP   #$0020,X:SCCR   ;CD=32 (/33), INT CLK @ 9600 BAUD
        MOVEP   #$0007,X:PCC    ;ENABLE SCI
WTUS
        JSR     GETCH           ;INPUT CHARACTER
        MOVE    #'_',X0         ;GET UNDERSCORE CHARACTER
        CMP     X0,A            ;SEE IF "_" YET
        JNE     WTUS            ;NO
GOTUS
        JSR     GETCH           ;GET A CHARACTER
        MOVE    #'D',X0         ;GET A D FOR DATA
        CMP     X0,A    #'E',X0 ;COMPARE TO D, GET E
        JEQ     DATAREC         ;IF "D", THEN DATA RECORD
        CMP     X0,A            ;SEE IF END RECORD
        JNE     WTUS            ;NO, GO WAIT FOR ANOTHER UNDERSCORE
_WTSPC
        JSR     GETCH           ;GET CHARACTER
        MOVE    #$20,X0         ;GET SPACE
        CMP     X0,A            ;WAIT FOR SPACE AFTER "END"
        JNE     _WTSPC          ;WAIT FOR SPACE
        JSR     IN4             ;GET TRANSFER ADDRESS
        MOVE    B1,R0           ;MOVE TRANSFER ADDRESS
        NOP                     ;CLEAR ADDRESS PIPE
        JMP     (R0)            ;GO EXECUTE USER CODE
DATAREC
        JSR     GETCH           ;GET CHARACTER
        MOVE    #$20,X0         ;GET SPACE
        CMP     X0,A            ;SEE IF SPACE
        JNE     DATAREC         ;NO
        JSR     GETCH           ;GET [P,X,Y]
        MOVE    A1,Y0           ;SAVE CHARACTER
        JSR     IN4             ;GET ADDRESS OF DATA RECORD
        MOVE    B1,R0           ;SAVE ADDRESS
        MOVE            #'X',A  ;GET X
        CMP     Y0,A    #'Y',A  ;SEE IF X, GET Y
        JEQ     _LDX            ;LOAD DATA INTO X MEMORY
        CMP     Y0,A            ;SEE IF Y
        JEQ     _LDY            ;LOAD DATA INTO Y MEMORY
_LDP
        JSR     IN6             ;GET DATA
        MOVE    B1,P:(R0)+      ;LOAD P MEMORY
        JMP     _LDP
_LDX
        JSR     IN4             ;GET DATA
        MOVE    B1,X:(R0)+      ;LOAD X MEMORY
        JMP     _LDX
_LDY
        JSR     IN4             ;GET DATA
        MOVE    B1,Y:(R0)+      ;LOAD Y MEMORY
        JMP     _LDY

GETCH
        JCLR    #RDRF,X:SSR,*   ;WAIT FOR DATA IN SCI
        MOVEP   X:SRXH,A        ;GET SCI DATA IN HIGH BYTE
        LSL     A               ;SHIFT OUT PARITY
        LSR     A               ;PUT 0 IN PARITY BIT
        MOVE    A1,A            ;SIGN EXTEND AND ZERO
	MOVEP	A,X:SRXH	;put sci data in high byte
        RTS

IN4
        CLR     B       #>4,X0  ;CLEAR VALUE, GET 4
        JMP     READHEX         ;READ 4 HEX CHARACTERS
IN6
        CLR     B       #>6,X0  ;CLEAR VALUE, GET 6
READHEX
        DO      X0,_READHEX     ;READ ASCII HEX AND CONVERT TO BINARY
_GET
        JSR     GETCH           ;GET A CHARACTER
        MOVE    #'_',X0         ;GET UNDERSCORE
        CMP     X0,A    #'F',X0 ;SEE IF UNDERSCORE
        JNE     _NOTUS          ;NO
        ENDDO                   ;EXIT LOOP
        MOVE    SSH,X0          ;POP RETURN ADDRESS
        JMP     GOTUS           ;GO PROCESS NEW INPUT RECORD
_NOTUS
        CMP     X0,A    #'0',X0 ;SEE IF GREATER THAN F
        JGT     _GET            ;YES, IGNORE
        CMP     X0,A            ;SEE IF LESS THAN 0
        JLT     _GET            ;YES, IGNORE
        SUB     X0,A    #10,X0  ;ADJUST FOR ASCII TO BINARY
        CMP     X0,A    #7,X0   ;SEE IF A-F
        JLT     _NOTALPHA       ;NO
        SUB     X0,A            ;ADJUST FOR 1-F
_NOTALPHA
        REP     #4              ;SHIFT OLD VALUE LEFT 1 NIBBLE
        LSL     B
        REP     #16             ;SHIFT NEW NIBBLE DOWN TO LSB
        LSR     A
        ADD     A,B             ;ADD NEW NIBBLE IN
_READHEX
        RTS

        END

-- 

Todd Day  |  todd@ivucsb.sba.ca.us  |  ivucsb!todd@anise.acc.com
"Time to eat all your words, swallow your pride, open your eyes."
					-- Tears for Fears