;//.processor m68hc11 ; ; File: memcheck.s ; Startup Runtime Code for project TEST, ; cmpe121 Spring 2001, basic test code for initial board verification. ; ; This assembly code is the first to be executed following a reset or ; power-on boot. Generally, this is the place to do any reset (boot) initializations that ; must be done during the first 64 clock cycles. xdef __stext xref _main, __memory, __idesc__ ; The following lines define where code and data objects are to be located in the ; 68HC11 memory map. You must insure that it agrees with your hardware design. ; These "segment" or "section" boundaries are defined in the TEST.CMD file, which should ; be edited by you to make things go where they should (see discussion in this file). switch .bss __sbss: ;label to base of bss segment (static, uninit. data) ; From crtsi.s svx: dc.w 0 sve: dc.w 0 ; end paste switch .bss __sdata: ;label base of data segment (init. data) ;Executable code must begin at the base of the text segment. switch .text __stext: ;label to base of text segment (code in rom) REGB1: equ $9016 REGB1L: equ $9017 REGB2: equ $9018 REGB2L: equ $9019 REGB3: equ $901A REGB3L: equ $901B REGB4: equ $901C REGB4L: equ $901D ERAM_B: equ $0000 ; Start external ram ERAM_L: equ $7FFF ; Length external ram IRAM_B: equ $8000 ; Start internal ram IRAM_L: equ $1FF ; Length internal ram ldab #$89 ; RAM = $8000, REGS = $9000 stab $103D clra ; a = 0 clrb ; b = 0 ;setup the stack frame at the top of zpage inside the hc11 ldx #$81FF ; X is decremented when xferred to SP txs cli ldaa $9000 anda #$02 beq 19200$ ldaa #$30 ; BAUD=9600 staa $902B bra cont 19200$: ldaa #$20 ; BAUD=19200 staa $902B cont: ldaa #$0C ; Turn on TE and RE in SCCR2 staa $902D ldaa $9000 anda #$01 beq init jmp memstart clra clrb ldy #0 ldx #0 jmp init ; jmp memstart ; Had to copy from crtsi.s from the Cosmic headers to make it ; initialize global variables properly at declaration time. ; paste from crtsi.s init: ldx #__idesc__ ; descriptor address ldy 0,x ; start address of prom data inx ; skip address inx ibcl: ldaa 0,x ; test flag byte beq zbss ; no more segment bpl nobk ; skip bank inx ; info inx ; if any nobk: stx svx ; save pointer ldd 3,x ; end address std sve ; in memory ldx 1,x ; destination address dbcl: ldab 0,y ; copy from prom stab 0,x ; to ram inx ; next byte iny cpy sve ; last one ? bne dbcl ; no, loop again ldx svx ; reload pointer to desc ldab #5 ; size of one entry abx ; point to next entry bra ibcl ; and loop zbss: ldx #__sbss ; start of bss bra loop ; start loop zbcl: staa 0,x ; clear byte inx ; next byte loop: cpx #__memory ; up to the end bne zbcl ; and loop lds #$81FF ; initialize stack pointer jsr _main ; execute main _exit: bra _exit ; and stay here ; end paste memstart: ldy #mem_start lds #memcheck jmp prints memcheck: ; Memory check! ; Y gets loaded with LENGTH of space, ; X gets loaded with base address. ldx #IRAM_B ; Check internal SRAM first ldy #IRAM_L ; 512 bytes long lds #1$ ; Retarget to next space sts REGB3 ; Store SP in REGB3 as convention, to protect it ldaa #$00 bra 10$ 1$: ldx #ERAM_B ; Check sram now ldy #ERAM_L ; 32768 bytes long lds #linecheck ; After this, jump to end! sts REGB3 ldaa #$00 bra 10$ 10$: ;c ldaa #$00 ;c staa 0, x ;c com 0, x ; This doesn't work because it seems ;c com 0, x ; that reads from bad ram read the addr? ;c bne 20$ ldaa #$00 ; Writing 0x00 staa 0, x ldab 0, x cba bne 20$ ; Error ldaa #$FF staa 0, x ldab 0, x cba bne 20$ ; Error ;Print if good stx REGB1 ; Save X sty REGB2 ; Save Y, prints(mem_good) ldy #mem_good lds #11$ jmp prints 11$: lds #15$ jmp printaddr 15$: ;ldaa '=' ; Debug print memory values ;lds #69$ ;jmp printc 69$: ;ldaa #$00 ; Printing out good value in low byte ;ldx REGB1 ;ldab 0, x ;xgdx ;lds #70$ ;jmp printaddr 70$: ldx REGB1 ldy REGB2 12$: ; See if we are at the end of the space cpy #$0000 ; if Y = 0, then we must have run through the space beq retarget ;beq done inx dey bra 10$ 20$: stx REGB1 sty REGB2 ; Save X in REGB1, prints(mem_error) ldy #mem_error lds #13$ jmp prints 13$: ldy REGB2 ; Copy X to REGB1, save Y in REGB2, printaddr(X) ;stx REGB1 lds #14$ jmp printaddr 14$: ;ldaa '=' ; Debug print memory values ;lds #71$ ;jmp printc 71$: ;ldab #$00 ;ldx REGB1 ;ldaa $008C ;xgdx ;lds #72$ ;jmp printaddr 72$: ldy #mem_bsod lds #16$ jmp prints 16$: ldx REGB1 ; Restore X and Y, return to memcheck loop ldy REGB2 bra 12$ ; Convert mem address in X to text and print ; Div by 4096 -- 16^3 place ; Div by 256 -- 16^2 place ; Div by 16 -- 16^1 place ; Left over -- 16^0 place ; This function will tamper with X, Y, D, S, and REGB4 ; Put Address in X and return address in S. printaddr: ldd #$1000 sts REGB4 divloop: ; Entering loop, xgdx ; X should have the portion of address left to conv, txs ; D should have the digit place I'm trying to convert idiv ; Swapped them for idiv, stored X to S which lets me ; remember the last place I converted. ;code here to print digit from quotient which is in X xgdx 1$: ldaa #$80 anda $902E beq 1$ cmpb #$A bge 2$ addb #48 ; ASCII offset for numbers bra 3$ 2$: addb #55 ; ASCII offset for capital letters 3$: stab $902F xgdx xgdy ; Save remainder in Y tsx ; Pull last place from S into X, xgdx ; switch X into D, ldx #$0010 ; Load 16 into X so I can do D/X = last-place/16 idiv cpx #0 ; If X is zero now, then I've processed the One's place beq 4$ xgdx ; Swap the remainder into X and quotient into D ; X should be zero, and D should have my digit place. tys ; Copy the previously saved remainder from Y into tsx ; S, and then copy that into X. This positions the ; remaining portion of my address into X for next iteration. bra divloop 4$: ldx REGB4 jmp 0, x retarget: ; Jump back to the code for retargeting memory checker ldx REGB3 jmp 0,x linecheck: ; Finally done! ; Make memory checker jump to main when it is done? ; Need to check for stuck lines first. ldy #mem_done lds #1$ jmp prints 1$: ldy #addr_start lds #2$ jmp prints ; First write should be a sentinel value, to the base address ; After that, a mask should be OR'd with the base address and ; that is what is used to construct addresses for tests. This ; mask keeps getting left shifted until the AND'd address is ; greater than the top address. See bound notebook. 2$: realline: ldd ERAM_B ; ERAM_B = SRAM base, REGB1 = SRAM top address addd ERAM_L std REGB1 ldd #$0001 10$: cpd ERAM_B bge 11$ ; Found my shift mask lsld ldaa 'S' lds #10$ ;jmp printc bra 10$ 11$: ;ldaa 'F' ;lds #21$ ;jmp printc std REGB2 71$: ldx REGB1 ; Start address debug lds #72$ jmp printaddr 72$: lds #73$ ldaa '-' jmp printc 73$: ldx ERAM_B lds #74$ jmp printaddr 74$: ldaa '-' lds #75$ jmp printc 75$: ldx ERAM_L lds #76$ jmp printaddr 76$: ldaa 13 lds #77$ jmp printc 77$: ldaa 10 lds #71$ jmp printc ; End address debug 21$: ;std REGB2 ; REGB2 = Shift mask ldaa #$55 ; Initial write to base address ldx ERAM_B staa 0, x 12$: ldd ERAM_B ; Load base address oraa REGB2 ; AND with mask (have to do it in halves) orab REGB2L xgdx ; Move it to X stx REGB3 lds #69$ ;jmp printaddr 69$: ldx REGB3 ldaa 0, x ; Read that pointer into A cmpa #$55 beq 13$ ; We read a previously written value ldd REGB2 ; Shift mask, loop if it is still smaller lsld ; than top address cpd REGB1 ble 12$ bra 7$ ; Must be foldback 13$: ldy #addr_error lds #5$ ;jmp prints 5$: lds #6$ ;jmp printaddr 6$: bra 6$ 7$: ldy #addr_done lds #init ;jmp prints ;loopstart: ; ldaa #76 ;loop: ; lds #loop ; inca ;; jmp printc ; bra loop ;; end char test ; jmp _main ;char to print goes into A printc: 10$: ldab #$80 andb $902E beq 10$ staa $902F tsx dex jmp 0,x ;string to print goes into Y prints: ldaa 0,y 10$: ldab #$80 andb $902E beq 10$ staa $902F iny ldaa 0,y cmpa #0 bne 10$ tsy dey jmp 0,y mem_start: dc.b 13 ; CR dc.b 10 ; LF dc.b 27 ; ESC dc.b '['; Disp attribs dc.b '3'; FG = Black dc.b '0' dc.b ';' dc.b '4'; BG = White dc.b '7' dc.b 'm'; End disp attribs dc.b "Running memory block checker." dc.b 13 ; CR dc.b 10 ; LF dc.b $00 mem_error: dc.b 13 ; CR dc.b 10 ; LF dc.b 27 ; ESC dc.b '['; Disp attribs dc.b '3'; FG = White dc.b '7' dc.b ';' dc.b '4'; BG = Blue dc.b '4' dc.b 'm'; End disp attribs dc.b "FAIL 0x" dc.b $00 mem_good: dc.b 13 ; CR dc.b 10 ; LF dc.b 27 ; ESC dc.b '['; Disp attribs dc.b '3'; FG = Black dc.b '0' dc.b ';' dc.b '4'; BG = White dc.b '7' dc.b 'm'; End disp attribs dc.b "Pass 0x" dc.b $00 mem_bsod: dcb.b 69,' ' dc.b $00 mem_done: dc.b 13 ; CR dc.b 10 ; LF dc.b 27 ; ESC dc.b '['; Disp attribs dc.b '3'; FG = Black dc.b '0' dc.b ';' dc.b '4'; BG = White dc.b '7' dc.b 'm'; End disp attribs dc.b "Memory block check finished." dc.b $00 addr_start: dc.b 13 ; CR dc.b 10 ; LF dc.b 27 ; ESC dc.b '['; Disp attribs dc.b '3'; FG = Black dc.b '0' dc.b ';' dc.b '4'; BG = White dc.b '7' dc.b 'm'; End disp attribs dc.b "Running memory address checker." dc.b 13 ; CR dc.b 10 ; LF dc.b $00 addr_error: dc.b 27 ; ESC dc.b '['; Disp attribs dc.b '3'; FG = White dc.b '7' dc.b ';' dc.b '4'; BG = Blue dc.b '4' dc.b 'm' dc.b "Bad address line: " dc.b $00 addr_done: dc.b "Memory address lines are good." dc.b 13 ; CR dc.b 10 ; LF dc.b $00 stop end