; ; Typical 68332 startup file, based on original provided by ; Software Development Systems in their SDS Startup Kit. ; ; ; Use the Motorola equate file to declare the 68332 I/O registers. ; #include equ332.asm ; ; Declare some important externals and publics. ; XDEF START,__brkp,__brksz,__exit XREF STKTOP,DATA,_main ; ; I removed the C++ initializers. See the original start.s file ; for their declaration. ; ; ; Define variables to track memory allocations for mbrk(). ; SECTION ram __brkp DS.L 1 ; point to available memory __brksz DS.L 1 ; number of available bytes ; ; The reset vector will point to this code (START). ; By the time we get here, A7 will have been initialized. ; ; I've added the following snippet of startup code originally at $0800 ; in the New Micros ROM. It checks for the presence of R9 on the ; PCB. If R9 is present, the CPU will continue with the startup ; procedure. If R9 is missing, the CPU will jump immediately to ; CPU32BUG. ; ; Note that per disassembly of the NMIX-0332 V1.00 ROMs, the entry ; point to CPU32BUG is $4a38, NOT $49b0 as called out in the ; memory.doc file shipped with the NMIX-0332 board. ; SECTION code .STK "none" ; terminate call chain for -OG START ; MOVE.W CSPAR1,D0 ; get CSPAR1 ; AND.W #$0002,D0 ; check DB3 ; BEQ start1 ; 0 = R9 installed, run my program ; JMP $4a38 ; no, start up CPU32BUG start1 MOVE.L #STKTOP,A7 ; set the stack pointer MOVE.L #0,A6 ; terminate call chain for -Og ; move.w #$c000,TRAMBAR ; move 2k RAM block to $c00000 ; move.l #$c007f0,a7 ; set stack pointer in 2k RAM ; ; Perform low-level configuration of system hardware. Configuration ; relies on the table at label config below. ; move.w #$2700,SR ; setup the status register move.l #config,a0 ; point to start of config tbl tbl1: move.w (a0)+,d0 ; get size word move.l (a0)+,a1 ; get destination addr move.l (a0)+,d1 ; get data to move cmp.w #0,d0 ; write a byte? bne tbl2 ; branch if not move.b d1,(a1) ; write byte to addr bra tbl1 ; do next tbl2: cmp.w #1,d0 ; write a word? bne tbl3 ; branch if not move.w d1,(a1) ; write word to addr bra tbl1 ; do next tbl3: cmp.w #2,d0 ; write a long? bne tblx ; if not, all done move.l d1,(a1) ; write long to addr bra tbl1 ; do next tblx: ; move.w #$7f00,SYNCR ; 16.667 MHz ; move.b #$4,SYPCR ; no watchdog ; move.w #$0038,SCCR0 ; baud = 9600 ; move.w #$000c,SCCR1 ; enable rcv and xmt ; move.w #$0004,CSBARBT ; boot ROM, 128K at $0000-$1ffff ; move.w #$7b70,CSORBT ; u/l bytes, r+w, 13 wait states move.w #'A',d0 l1: btst.b #0,SCSR beq.b l1 move.b d0,SCDR+1 bra l1 ; do forever ; ; Zero out uninitialized RAM. ; ; MOVE.L #`BASE(ram),A1 ; A1 = base of region ram ; MOVE.L #`SIZE(ram),D0 ; D0 = size of region ram ; LSR.L #2,D0 ; compute size in longs ; BRA ZDBF ; enter a fast loop ZLP: ; CLR.L (A1)+ ; clear four bytes at a time ZDBF: ; DBF D0,ZLP ; up to 256K in inner loop ; SUB.L #$10000,D0 ; rest in outer loop ; BHS ZLP ; ; Initialize other RAM from ROM. ; ; MOVE.L #DATA,A0 ; A0 = ROM base of region data ; MOVE.L #`BASE(data),A1 ; A1 = RAM base of region data ; MOVE.L #`SIZE(data),D0 ; D0 = size of region data ; LSR.L #2,D0 ; compute size in longs ; BRA IDBF ; enter a fast loop ILP: ; MOVE.L (A0)+,(A1)+ ; move four bytes at a time IDBF: ; DBF D0,ILP ; up to 256K in inner loop ; SUB.L #$10000,D0 ; rest in outer loop ; BHS ILP ; ; Initialize memory allocator. ; ; MOVE.L #`BASE(malloc),D0 ; address of malloc region ; MOVE.L #`SIZE(malloc),D1 ; size of malloc region ; .IF "ptrd"?"2" ; SWAP D0 ; handle 2-byte C "pointers" ; .ENDIF ; .IF "long"?"2" ; SWAP D1 ; handle 2-byte C "longs" ; .ENDIF ; MOVE.L D0,__brkp ; vars referenced by mbrk() ; MOVE.L D1,__brksz ; ; Invoke main() with no arguments. ; JSR _main ; "int" return value in D0 ; ; Control reaches this point if control leaves main(). ; __exit DONE BRA DONE ; loop if main ever returns ; ; If your program needs standard character I/O routines, this makes ; a good place to stash them. The following routines assume that ; CPU32 is available, and rely on the monitor's TRAP mechanism. ; ; ; outch output char in D0 to active port ; XDEF _outch ; .FDEF _outch,4 _outch move.w SCSR,d1 ; get SCI status and.w #$0100,d1 ; leave only TDRE bit beq _outch ; loop until ready and.w #$00ff,d0 ; force upper bits to 0 move.w d0,SCDR ; send the char rts ; move.b d0,-(a7) ; save char on stack ; trap #15 ; use CPU32 ; dc.w $0020 ; output a char ; rts ; and leave ; ; inch get char from active port, return in D0 ; XDEF _inch _inch subq.l #2,a7 ; make room on stack trap #15 ; use CPU32 dc.w $0000 ; input a char move.b (a7)+,d0 ; put char in D0 rts ; and leave ; ; Define the system configuration table. ; ; The following table works for the New Micros 68332 board. Change ; this table as needed for your hardware. ; ; Each entry in the configuration table specifies the ; size of a value to write to memory, the address affected, and ; the data to write to it. The config implementation is based ; on the TINIT routine used by New Micros in their MAXForth/332 ; firmware. I liked their idea so much I had to use it in my ; system. ; ; Each entry in the table consists of a word and two longs, in the ; following order: ; ; dc.w 0, 1, or 2 ; 0=byte, 1=word, 2=long ; dc.l addr ; address to change ; dc.l data ; value to write to addr ; ; For example, to write the word $0038 to address SCCR0 (sets ; baud rate to 9600 baud), you would use the following table entry: ; ; dc.w 1 ; SCCR0 (word) ; dc.l SCCR0 ; set baud rate ; dc.l $0038 ; to 9600 ; ; Mark the end of the table with a size field other than 0, 1, or 2. ; ; Note that the configuration values are written to the hardware ; registers in the order of appearance. ; config: dc.w 1 ;16.667MHz dc.l SYNCR dc.l $7F00 dc.w 0 ;BME, NO WATCHDOG TIMER dc.l SYPCR dc.l 4 ; dc.w 1 ;boot ROM, 128K at $00000-1ffff ; dc.l CSBARBT ; dc.l $0004 ; dc.w 1 ;select for u/l bytes, read + write, ; dc.l CSORBT ;3 wait states, U/S space ; dc.l $78F0 ; dc.l $7B70 ; dc.w 1 ;CS0 = 2nd half of ROM space, ; dc.l CSBAR0 ;128k at $20000-3ffff ; dc.l $0204 ; dc.w 1 ;CS1 = 1st half of RAM, ; dc.l CSBAR1 ;64K at $40000-5ffff ; dc.l $0404 ; dc.w 1 ;CS2 = ram, ; dc.l CSBAR2 ;128k at $60000-7ffff ; dc.l $0604 ; dc.w 1 ;CS3 = io space, ; dc.l CSBAR3 ;64k at $f00000-f0ffff ; dc.l $F003 ; dc.w 1 ;wait states for CS0 = 3 ; dc.l CSOR0 ; dc.l $78F0 ; dc.w 1 ;wait states for CS1 = 3 ; dc.l CSOR1 ; dc.l $78F0 ; dc.w 1 ;wait states for CS2 = 3 ; dc.l CSOR2 ; dc.l $78F0 ; dc.w 1 ;wait states for CS3 = 13 ; dc.l CSOR3 ; dc.l $7B70 dc.w 1 ;sci=9600 baud dc.l SCCR0 dc.l $0038 dc.w 1 ;enable rcv and xmt dc.l SCCR1 dc.l $000C ; dc.w 1 ;setup internal ram ; dc.l TRAMBAR ; dc.l $FFE8 dc.w $ffff ; marks end of table ; ; Declare the reset vector, stored in supervisor space at address 0. ; Address 0 holds the 32-bit address to write to A7, the stack pointer. ; Address 4 holds the 32-bit address to write to PC. ; SECTION reset DC.L STKTOP ; initial stack pointer DC.L START ; initial execution address ; ; OTHER EXCEPTION VECTORS: to supervisor data space at address 8, ; or 8 bytes beyond where the vector base register will point. ; This table is commented out because no actual interrupt rou- ; tines are provided. ;********************************************************************** ; SECTION vects ; DC.L BUSERROR,ADRERROR ; 0x08 ; DC.L ILLEGAL,ZERODIV,CHK,TRAPV ; 0x10 ; DC.L PRIVILEGE,TRACE,EMULA,EMULF ; 0x20 ; DC.L RESVD,PROTO,FORMAT,UNINIT ; 0x30 ; DCB.L 8,RESVD ; 0x40 ; DC.L SPURIOUS,AUTO1,AUTO2,AUTO3 ; 0x60 ; DC.L AUTO4,AUTO5,AUTO6,AUTO7 ; 0x70 ; DC.L TRAP0,TRAP1,TRAP2,TRAP3 ; 0x80 ; DC.L TRAP4,TRAP5,TRAP6,TRAP7 ; 0x90 ; DC.L TRAP8,TRAP9,TRAPA,TRAPB ; 0xa0 ; DC.L TRAPC,TRAPD,TRAPE,TRAPF ; 0xb0 ; DC.L FUNORD,FNEXACT,FZERODIV,FUNFLOW ; 0xc0 ; DC.L FOPND,FOVFLOW,FSNAN,RESVD ; 0xd0 ; DCB.L 8,RESVD ; 0xe0 ; DCB.L 192,USER ; 0x100