; *************************************************************************** ; * ; HC908 Debug Monitor V1.0 * ; George Heron, N2APB * ; 12/2002 * ; * ; This program is a simple, low-level debug monitor developed to support * ; the projects based on the "HC908 Daughtercard" project described * ; in QRP Homebrewer magazine (published by the NJQRP Club), in QRP * ; Quarterly magazine (published by QRP ARCI), and on the website of the * ; New Jersey QRP Club (www.njqrp.org) * ; * ; The operator interfaces to the HC908 Debug Monitor by means of a dumb * ; terminal connected to the RS-232 serial port of the MPU daughtercard. * ; Through the Monitor's command/response structure, the operator may edit * ; memory amd MPU registers, set and reset breakpoints, "go" or single step * ; from any executable location in the loaded program, load S record files * ; sent by the terminal, program Flash memory from the downloaded S records, * ; and read input ports and set output ports. * ; * ; The HC908 Debug Monitor is programmed into all HC908 Daughtercards after * ; manufacture. In some instances, another software program may also be * ; programmed in the HC908 Daughtercard at time of manufacture, providing * ; the customer with one of a growing number of software applications for * ; this product (e.g., the Digital Breadboard, the Antenna Analyzer, HC908 * ; Commander, the HC908 Digital VFO and others). * ; * ; As mentioned, the HC908 Daughtercard and its debug monitor provides the * ; user with an ability to program the permament and nonvolatile "flash" * ; memory directly from downloaded "S records". An S record file is a common * ; format for the assembled or compiled 68HC908 MPU binary code, as * ; used in most Motorola-based processors and tools. Thus, when a user * ; wishes to load a program other than what arrived on his HC908 * ; Daughtercard, he may download any of the available S record files from the* ; project's Internet website and "burn" the program into the MPU's flash * ; memory, thus making the program permanent and available for his use. In * ; this way, the user is able to change the HC908 Daughtercard's * ; "personality" without any other tools than a terminal program connected * ; to the Daughtercard on its serial port. * ; * ; Most "dumb terminals" may be used to communicate with the HC908 Debug * ; Monitor. Examples of such programs include HyperTerminal, Red Ryder, * ; ProComm and PCPlus. However, a useful, public domain (freeware) terminal * ; program called "Tera Term" is also available to run on Microsoft Windows * ; platforms. Tera Term has a convenient scripting ability that can be * ; invoked to send an S record file (like a new software program) to your * ; HC908 Daughtercard for flash programming by the Monitor. The Tera Term * ; terminal program and its S record transfer script are provided on the * ; HC908 project website for users to download and use on their systems. * ; * ; There are many more features and details concerning the use of the HC908 * ; Debug Monitor on the HC908 Daughtercard-based projects. Please refer to * ; written documentation provided with the Monitor and Daughtercard for the * ; latest and authoritative information concerning capabilities and use. * ; * ; Questions may be addressed to me by email and I'll do my best to help out.* ; ; v1 Dec 2002 Initial release ; v2a May 5, 2003 Removed $803C hook into User Space to reduce ; complexity and chance for user to mess up by ; inadvertently overwriting the hook code ; v2b June 8, 2003 Corrected comment for PIT interrupt vector code (FFF6+FFF7) ; * ; George Heron, N2APB * ; email: n2apb@amsat.org * ; * ; *************************************************************************** ; GNU Public License * ; * ; This program is free software; you can redistribute it and/or modify * ; it under the terms of the GNU General Public License as published by * ; the Free Software Foundation; either version 2 of the License, or * ; (at your option) any later version. * ; * ; This program is distributed in the hope that it will be useful, * ; but WITHOUT ANY WARRANTY; without even the implied warranty of * ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * ; GNU General Public License for more details. * ; * ; You should have received a copy of the GNU General Public License * ; along with this program; if not, write to the Free Software * ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ; * ; See license.txt file for details * ; * ;**************************************************************************** ; Credits: * ; * ; Major portions of this program were adapted from the Pony 68HC908 Debug * ; Monitor V1.4 by Larry Bateman. Copyright (c) 2000, L3 Systems. * ; * ; Portions borrowed from Motorola's "MC68HC908GP32 User Bootloader", * ; Copyright (c) Motorola 2000. Written by DGJ Klotz Rev ES 1.0 26-Feb-00 * ; * ; *************************************************************************** $BASE 10T include "../ab_regs.asm" ; MC68HC908GP32 register defimitions include "../macros.asm" ; Macro instruction definition include "../local.asm" ; Local variables ; User Base RAM org $50 _count rmb 1 ; Byte Counter for s record download _temp_sp rmb 2 ; Temporary stack pointer ; User stack - Hex 3ff org $3FF _user_stack rmb 1 ; Position to Initialize user stack ; Monitor RAM - Hex 400-44F org $400 _hbufpos rmb 2 ; buffer position temp storage _tempx rmb 2 ; Temporary h:x register storage _stack_save rmb 2 ; Stack save _last_break rmb 2 ; Save last break, to reset break ; when resuming _h_save rmb 1 ; h-reg save _state rmb 1 ; State after break point _inbuf rmb RXBLEN ; Input Buffer ; Monitor stack, initialize at end of RAM Hex 23F org $44F _mon_stack rmb 1 ; Position of monitor stack org $EF00 _user_reset fdb $8040 ; pointer to start User Application ;************************************************************ ; Power-on Reset ;************************************************************ __start: _bootreset: ; Launch the bootloader from power-on reset. sei ; disable all interupts ldhx #_mon_stack+1 ; initialize txs ; the stack pointer jsr PLLset ; change bus speed ; Initialize the SCI. mov #init_scbr,scbr ; initialize baud rate mov #init_scc1,scc1 ; initialize SCI Control Register 1 mov #init_scc2,scc2 ; initialize SCI Control Register 2 mov #init_config1,config1 ; init Configuration Register 1 ; Test Port F7 for "Monitor Jumper" ; Entry to Monitor = jumper OFF ==> F7 = 1 ; Entry to User Pgm = jumper ON ==> F7 = 0 mov #$40,ddrf ;set portf bits 7,5,4,3,2,1,0 as inputs, bit 6 (LED) as output mov #$B8,prtfpu ;assign pullups to Port F bits 7,5,4,3 bclr 6,portf ;turn LED on continuously while in monitor brclr 7,portf,MonStart ;go start Monitor if "Monitor Jumper" is in place ldhx #_user_stack ;else init user SP jsr _save_sp ; in _user_stack area jsr $8040 ; and go start User application at $8040 MonStart: ldhx #ram_start clrRAM: clr ,x ;Clear RAM aix #1 cphx #ram_last+1 bne clrRAM jsr _init_ustack ;Initialize user stack nop nop nop ; Boot start _boot: sta copctl ;clear the COP counter lda #$FF jsr _delay ;delay just a bit ldhx #_PWR_MSG ;point to monitor sign-on message jsr _puts ;and display it _main: ldhx #_PROMPT ; Print prompt jsr _puts jsr _gets ;get user input command string bcs _main ;keep looking if ESC or ctl-C lda _inbuf ;check input buffer beq _main ;keep looking if empty (just CR entered) and #$DF ;turn to capital letter ldhx #_cmdtab ;point to command table jsr _get_atbl ;get menu selection bcc notfound ;valid menu item not selected jsr ,x ;found menu item, call corresponding routine bra _main ;get another command when processing done notfound: ldhx #_ERR_MSG ;pointer to error string jsr _puts ;print the string bra _main ;go get another command ;************************************************************ ; _init_ustack After power up or download, checks for ; valid user reset jump statement. If one exists, ; then initialize user stack to go there on an rti ;************************************************************ _init_ustack: brclr 7,PortF,no_rst_vec ; "Mon Jumper" in place, we're in Monitor ldhx #_user_stack-4 ; Read user stack address + rti frame jsr _save_sp ; Store address in stack_save lda _user_reset ; Get address of user program reset sta _user_stack-1 ; and store in address field of stack frame lda _user_reset+1 ; sta _user_stack no_rst_vec: rts ;************************************************************ ; _medit() Edit memory locations ;************************************************************ _medit: jsr _first_hex bcs end_medit mexlp: jsr _crlf jsr _pword lda ,x jsr _pbyte_sp jsr _space lda #2 pshhx jsr _gethex lda _inbuf bcs not_byte txa pulh pulx sta ,x aix #1 bra mexlp not_byte: pulhx aix #1 cmp #SPACE beq mexlp ; If nul entry (ENTER), go to next byte aix #-2 cmp #BS beq mexlp ; If Backspace, go to previous byte end_medit: rts ; Else return ;************************************************************ ; _dump() Dump Memory locations ;************************************************************ _dump: jsr _first_hex bcs end_dump txa ; Init even boundary and #$F0 tax prmem: pshhx ldhx #_HEADING jsr _puts pulhx prmlp: txa and #$0F bne nxmem jsr _crlf tha jsr _pbyte txa jsr _byte_sp nxmem: lda ,x jsr _byte_sp aix #1 txa tsta bne prmlp wt_end_dump: jsr _do_again beq prmem end_dump: rts ;************************************************************ ;************************************************************ ; ; D E B U G C O M M A N D S ; ;************************************************************ ;************************************************************ ;************************************************************ ; _fill() -- Fill Memory locations ;************************************************************ _fill: jsr _first_hex bcs end_fill pshhx jsr _next_hex bcc get_val pulhx bra end_fill get_val: tha sta _tempx stx _tempx+1 jsr _next_hex txa pulhx bcs end_fill fill_lp: sta ,x psha tha cmp _tempx pula bne nxt_fill cpx _tempx+1 beq end_fill nxt_fill: aix #1 bra fill_lp end_fill: rts ;************************************************************ ; _pr_reg, _out_reg -- Outputs registers from user stack ;************************************************************ _prreg: jsr _crlf _out_reg: ldhx #SP_MSG jsr _puts jsr _get_sp aix #-1 jsr _pword pshhx ldhx #CC_MSG reg_lp: jsr _puts aix #1 pshhx lda ,x cmp #':' bne not_h_reg lda _h_save jsr _pbyte bra nxt_reg not_h_reg: lda 3,sp tah ldx 4,sp aix #1 lda ,x jsr _pbyte tha sta 3,sp stx 4,sp nxt_reg: pulhx lda ,x cmp #'E' bne reg_lp pulhx rts ;************************************************************ ; _set_break -- Sets breakpoint ;************************************************************ _set_break: jsr _first_hex ; Gets breakpoint address bcs pr_brkpt tha ; store breakpoint so that it can be restored sta _last_break ; at next breakpoint when resuming stx _last_break+1 bsr _wt_break pr_brkpt: ldhx #_MSG_BREAK jsr _puts lda brkscr bpl end_set_bp lda brkh tah ldx brkl jsr _pword end_set_bp: rts ;************************************************************ ; _restore_bk -- Restores break address to last set value ;************************************************************ _restore_break: lda _last_break tah ldx _last_break+1 ; _wt_break writes a break point at h:x _wt_break: stx brkl ; stores breakpoint tha sta brkh lda #$80 sta brkscr ; enables breakpoint sta sbfcr ; Allows access to break status registers rts ;************************************************************ ; _clr_break -- Clears breakpoint ;************************************************************ _clr_break: clra ; disables breakpoint sta brkscr rts ;************************************************************ ; _break_pt -- Routine to process breakpoint ;************************************************************ _break_pt: sei lda #$80 sta sbfcr ; Allows access to break status registers sta brkscr tha sta _h_save ; Save h register tsx jsr _save_sp ; Save user stack pointer ldhx #_mon_stack+1 ; Transfer stack to monitor RAM txs bsr _restore_break ; restore breakpoint lda _state ; Check if this was a go from a breakpoint cmp #1 ; If so, we need to resume bne not_resume clra ; Clear resume state sta _state jmp _do_rti ; Resume from current breakpoint not_resume: ldhx #_MSG_BREAK ; Output breakpoint message jsr _puts jsr _out_reg ; Output registers jsr _get_pc ; Get current user program counter jsr _disasm_1x ; Disassemble where you are lda _state cmp #2 ; Is it in single step mode? bne not_sstep ; If not, go back to prompt jsr _do_again ; If so, look for space to step next beq _step_again ; If space, do next instruction clra ; If not, clear resume state sta _state ; and go back to prompt not_sstep: jmp _main ;************************************************************ ; _next -- Step one instruction ;************************************************************ _next: bsr _is_stack_ok ; Only step if Stack is initialized bcs no_step ; WARNING: this is not a bullet-proof test! _step_again: bsr _break_next ; Set breakpoint to stop at next instruction lda #2 ; Sets single step state sta _state jmp _go_stack ; ;************************************************************ ; _break_next -- Set to break on next instruction Based on following: ; - If current instruction is 2 or more bytes ; setting the break in the 2nd byte will cause ; the break to occur on the next instruction ; - If one byte instruction, only jsr ,x and ; jmp ,x will start at next byte ;************************************************************ _break_next: jsr _get_pc ; Get current user program counter lda ,x aix #1 ; Check if instruction is a jmp ,x or jsr ,x and #$FE cmp #$FC bne not_jx bsr _get_hx lda ,x ; If it is a jmp ,x or jsr ,x ldx 1,x ; Then set break at address pointed to by x-reg tah not_jx: jmp _wt_break ;************************************************************ ; _is_stack_ok returns carry clear if ok, set if not, ; ;************************************************************ _is_stack_ok: lda _stack_save ; Check that user SP is valid beq ck_ss_low cmp #1 bne stk_not_ok bra stk_ok ck_ss_low: lda _stack_save+1 beq stk_not_ok stk_ok: clc rts stk_not_ok: sec no_step: end_go: rts ;************************************************************ ; _get_pc Gets user PC off of user stack, returned in h:x reg ;************************************************************ _get_pc: bsr _get_sp lda 3,x ldx 4,x bra done_get ;************************************************************ ; _get_hx Gets user h:x reg, gets x-reg off of stack and ; h reg from _h_save. Returns in h:x reg ;************************************************************ _get_hx: bsr _get_sp ldx 2,x lda _h_save bra done_get ;************************************************************ ; _get_sp Gets user stack pointer from +stack_save ; Returns in h:x reg ;************************************************************ _get_sp: lda _stack_save ldx _stack_save+1 done_get: tah rts ;************************************************************ ; _save_sp Saves user stack pointer in stack_save ; Passed in h:x reg ;************************************************************ _save_sp: tha sta _stack_save ; Store address in stack_save stx _stack_save+1 rts ;************************************************************ ; go(*x-reg) Execute program at X-reg ;************************************************************ _go: jsr _first_hex bcs chk_stack_add tha stx _tempx ldhx #_user_stack+1 txs tah ldx _tempx cli jmp ,x ; Call user prog,x chk_stack_add: bsr _is_stack_ok bcs end_go _go_stack: lda brkscr bpl _do_rti jsr _get_pc ; Get current user program counter cpx brkl ; compares breakpoint address to current bne _do_rti tha cmp brkh bne _do_rti lda #1 ; If currently at breakpoint, set _state to 1 sta _state ; to indicate to continue from next break tha ; and store breakpoint to be restored sta _last_break ; at next breakpoint when resuming stx _last_break+1 jsr _break_next ; and set break at next instruction _do_rti: bsr _get_sp ; If user SP is valid, set SP to user SP and do RTI txs lda _h_save tah rti ;************************************************************ ; Prints Help message ;************************************************************ _help: ldhx #_PWR_MSG jsr _puts ldhx #_HELPLIST jsr _puts rts ;************************************************************ ; Copy Flash Mass Erase algorithm into RAM and execute. ;************************************************************ ; ram_exec equ $200-STACK_ALLOC-ProgramRamSize+1 ; executable RAM ram_exec equ $19A _do_mass_erase: ldhx #EraseRamSize ; initialize pointer BootErase1: lda MassErase-1,x ; get program from Flash sta ram_exec-1,x ; copy into RAM dbnzx BootErase1 ; decrement pointer and loop back until done jsr ram_exec ; execute Flash Mass Erase algorithm from RAM BootDone: jsr _init_ustack ; initialize user stack rts ;------------------------------------------------------------------- ; Check for Program Flash command. _do_dnload: ; Copy Program Flash algorithm into RAM and execute. ldhx #ProgramRamSize ; initialize pointer BootProg: lda _delay-1,x ; get program from Flash sta ram_exec-1,x ; copy into RAM dbnzx BootProg ; decrement pointer and loop back until done ldhx #_MSG_WAITING ; point to waiting message jsr _puts ; output it ; Get S-Record from host. BootProg1: sta copctl ; clear the COP counter tsx ; get the Stack Pointer sthx _temp_sp ; save it temporarily ais #-36T ; allocate stack space for data jsr GetSRec ; get an S-Record bne BootProg3 ; indicate error if S-Record is invalid pula ; get S-Record type cmp #'9' ; check for end record type beq BootProg2 ; indicate operation complete cmp #'1' ; check for data record type bne BootProg3 ; indicate error if S-Record is invalid ; Program Flash. jsr {ram_exec+ProgramRam} ; execute Program Flash alg from RAM ais #35T ; deallocate stack space bra BootProg1 ; loop bacl for next S-Record BootProg2: ais #35T ; deallocate stack space brclr SCRF,scs1,BootDone ; skip if SCI receiver is empty jsr _getchne ; else, clear last ASCII carriage ; return from the SCI brclr SCRF,scs1,BootDone ; skip if SCI receiver is empty jsr _getchne ; else, clear last LF from the SCI bra BootDone ; indicate operation complete BootProg3: ais #36T ; deallocate stack space ; Respond to error situations. ldhx #_MSG_ERROR ; point to error message Boot4: jsr _puts ; output it jmp _boot ; jump back to the top ;******************************************************************** ; CGM PLL Bus Frequency Change Subroutine ; ; This subroutine will program the CGM PLL to change the bus frequency ; from that of the 4.915 MHz xtal to about 8 MHz ;******************************************************************** PLLset: bclr BCS,pctl ; select external reference as base clock bclr PLLON,pctl ; turn off PLL mov #$77,PPG ; set up PLL Programming Register bset AUTO,pbwc ; enable automatic bandwidth control bset PLLON,pctl ; turn on PLL PLLwait: brclr LOCK,pbwc,PLLwait ; wait for PLL to lock bset BCS,pctl ; select VCO as base clock rts ; return ;******************************************************************** ; GetSRec Subroutine ; ; This subroutine will retrieve data in S19 record format via the SCI. ; ; Calling convention: ; ; ais #-buffer_length ; jsr GetSRec ; ; Returns: CCRZ= 1 if valid S-Record retrieved. Otherwise, CCRZ= 0. ; S-Record Type at SP+1 (1 byte) ; S-Record Size at SP+2 (1 byte) ; S-Record Address at SP+3 (2 bytes) ; S-Record Data at SP+5 (up to 32 bytes, typically) ; ; | | <-sp (after local space allocation) ; H:X-> | SRecCount | ; | SRecChkSum | <-sp (when called) ; | ReturnAddr msb | ; | ReturnAddr lsb | <-sp (upon return) ; | SRecType | ; | SRecSize | ; H:X-> | SRecAddr msb | ; | SRecAddr lsb | ; | SRecData 00 | ; | SRecData 01 | etc.. ; ; Changes: ACC, H:X ;******************************************************************** SRecCount equ 1 ; stack pointer offset for S-Record Counter (local) SRecChkSum equ 2 ; stack pointer offset for S-Record Check Sum (local) SRecType equ 5 ; stack pointer offset for S-Record Type SRecSize equ 6 ; stack pointer offset for S-Record Size SRecAddr equ 7 ; stack pointer offset for S-Record Address SRedData equ 8 ; stack pointer offset for S-Record Data GetSRec: ais #-2 ; allocate local variable space clr SRecSize,sp ; initialize S-Record size GetSRec1: jsr _getchne ; get a character from the SCI #if HYPERTERM #elseif jsr _putch ; echo it back #endif cmp #CR ; check for ASCII carriage return bne GetSRec1a ; just loop back if so lda #LF ; get ASCII line feed #if HYPERTERM #elseif jsr _putch ; echo it back #endif GetSRec1a: cmp #'S' ; check for start of record character bne GetSRec1 ; loop back if not jsr _getchne ; else, get next character from the SCI #if HYPERTERM #elseif jsr _putch ; echo it back #endif cmp #'0' ; check for header record type beq GetSRec1 ; loop back if so cmp #'9' ; else, check for end record type beq GetSRec2 ; continue if so cmp #'1' ; else, check for data record type bne GetSRec1 ; loop back if not GetSRec2: sta SRecType,sp ; save S-Record type jsr GetHexByte ; get the S-Record length bne GetSRec4 ; exit if not a valid hex byte sta SRecCount,sp ; initialize S-Record counter sta SRecChkSum,sp ; initialize S-Record check sum sub #3 ; adjust for address and checksum sta SRecSize,sp ; save S-Record size tsx ; use H:X as data stack frame pointer aix #(SRecAddr-1) ; adjust so pointer starts at S-Record Address GetSRec3: jsr GetHexByte ; get next S-Record hex byte bne GetSRec4 ; exit if not a valid hex byte sta ,x ; save data in stack frame add SRecChkSum,sp ; add data to check sum sta SRecChkSum,sp ; save new check sum aix #1 ; move data stack frame pointer dbnz SRecCount,sp,GetSRec3 ; loop back until all data received inc SRecChkSum,sp ; final calc zeros check sum if it's okay GetSRec4: ais #2 ; deallocate local variables rts ; return ;************************************************************************** ; Flash Mass Erase Subroutine ; This subroutine performs multiple Page Erase operations in order ; to completely erase the application space Flash memory. ; This subroutine is copied into and executed from RAM. ;******************************************************************** MassErase: ldhx #rom_start ; initialize pointer to start of Flash memory MassErase1: ; Set ERASE, read the Flash Block Protect Register and write any ; data into Flash page. lda #ERASE ; set ERASE control bit sta flcr ; in Flash Control Register lda flbpr ; read from Flash Block Protect Register sta ,x ; write any data to address within page ; Wait for >10us, then set HVEN. lda #1 ; wait bsr _delay ; for 11.7us lda #(ERASE|HVEN) ; set HVEN control bit sta flcr ; in Flash Control Register ; Wait for >1ms, then clear ERASE. lda #100T ; wait bsr _delay ; for 1.005ms lda #HVEN ; clear ERASE control bit sta flcr ; in Flash Control Register TestLabel: ; Wait for >5us, then clear HVEN. lda #1 ; wait bsr _delay ; for 11.7us clra ; clear HVEN control bit sta flcr ; in Flash Control Register ; Advance pointer and repeat until finished. aix #{flash_page/2} ; add half of Flash Erase Page size twice, aix #{flash_page/2} ; since it's 128 bytes for GP32 cphx #boot_start ; check if finished bne MassErase1 ; loop back if not rts ; return ;******************************************************************** ; delay Subroutine ; ; This subroutine performs a simple software delay loop based upon ; the value passed in ACC. ; The following timing calculation applies: ; ; delay = ((ACC * 74) + 12) (tcyc) ; If A=1 ; then delay = 11.7us at 114.545ns/cycle ; ;******************************************************************** _delay: psha ; [2] save delay parameter temporarily delay1: lda #102T ; [2] initialize 5us loop counter ; (repeat for timing) delay2: dbnza delay2 ; [3] decrement inner delay loop counter dbnz 1,sp,delay1 ; [6] decrement outer delay loop counter pula ; [2] deallocate local variable rts ; [4] return EraseRamSize equ (*-MassErase) ProgramRam equ (*-_delay) ;******************************************************************** ; Flash Program Subroutine ; ; This subroutine controls the Flash programming sequence. A stack ; frame data block is passed to it in the format shown below. ; This subroutine is copied into and executed from RAM. ; ; | | <-sp (when called) ; | ReturnAddr msb | ; | ReturnAddr lsb | <-sp (upon return) ; | SRecSize | ; | SRecAddr msb | ; | SRecAddr lsb | ; | SRecData 00 | ; | SRecData 01 | etc.. ;******************************************************************** FlashProgram: tsx ; get the Stack Pointer sthx _temp_sp ; save it temporarily ; Get S-Record size and use the Stack Pointer as the data source pointer. ais #2 ; SP points to SRecSize pula ; get SRecSize sta _count ; save it temporarily ; Establish H:X as the destination pointer. pulh ; get destination address msb pulx ; get destination address lsb ; Set PGM, read the Flash Block Protect Register and write anywhere ; in desired Flash row. lda #PGM ; set PGM control bit sta flcr ; in Flash Control Register lda flbpr ; read from Flash Block Protect Register sta ,x ; write any data to first Flash address ; Wait for >10us, then set HVEN. LDA #tnvs DBNZA * lda #(PGM|HVEN) ; set HVEN control bit sta flcr ; in Flash Control Register ; Wait for >5us. LDA #tpgs DBNZA * ; Write data to Flash and wait for 30 - 40us. FlashProgram1: pula ; get S-Record data sta ,x ; write data to Flash LDA #tprog DBNZA * ; Advance destination pointer and data counter. aix #1 ; advance destination pointer dbnz _count,FlashProgram1 ; decrement counter and loop back ; if not done. ; Clear PGM. lda #HVEN ; clear PGM sta flcr ; in Flash Control Register ; Wait for >5us, then clear HVEN. LDA #tnvh DBNZA * clra ; clear HVEN control bit sta flcr ; in Flash Control Register ldhx _temp_sp ; restore txs ; Stack Pointer rts ; return ProgramRamSize: equ (*-_delay) ;******************************************************************** ; Command lookup table ;******************************************************************** _cmdtab: fcb 'B' fdb _set_break fcb 'U' fdb _clr_break fcb 'E' fdb _medit fcb 'D' fdb _dump fcb 'G' fdb _go fcb 'N' fdb _next fcb 'F' fdb _fill fcb 'R' fdb _prreg fcb 'L' fdb _do_dnload fcb 'H' fdb _help fcb 'C' fdb _do_mass_erase fcb 'A' fdb _disasm fcb 'X' fdb $8040 fcb NUL ;************************************************************* ; Prompts and Messages ;************************************************************* _PROMPT: fcb CR,LF fcb "HCmon> " fcb NUL _HEADING: fcb CR,LF,LF fcb "ADDR 0 1 2 3 4 5 6 7 8 9 A B C D E F" fcb CR,LF fcb "---- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --" fcb NUL #if HYPERTERM _MSG_WAITING: fcb " -waiting..." fcb NUL #elseif _MSG_WAITING: fcb " -waiting..." fcb CR,LF,NUL #endif _MSG_ERROR: fcb " - error" fcb NUL _MSG_BREAK: fcb CR,LF fcb "Break: " fcb NUL _PWR_MSG: fcb CR,LF fcb "HC908 Monitor, rev 2a Dec 2002, G.Heron N2APB" fcb CR,LF,NUL _ERR_MSG: fcb "Huh?" fcb NUL _HELPLIST: fcb CR,LF,LF fcb "Monitor Commands:" fcb CR,LF,LF fcb "H Help" fcb CR,LF fcb "A ADDR Disassemble" fcb CR,LF fcb "B ADDR Set Break" fcb CR,LF fcb "U Undo Break" fcb CR,LF,LF fcb "D ADDR Dump" fcb CR,LF fcb "E ADDR Edit" fcb CR,LF fcb "F BEGIN END VALUE Fill" fcb CR,LF fcb "R Print Regs" fcb CR,LF,LF fcb "G ADDR Go" fcb CR,LF fcb "N Next" fcb CR,LF fcb "L Load Srec" fcb CR,LF fcb "C Clear Flash" fcb CR,LF fcb "X Goto User Application" fcb CR,LF fcb NUL ;************************************************************* ; Register prompts SP_MSG: fcb "SP=" fcb NUL CC_MSG: fcb " CC=" fcb NUL A_MSG: fcb " A=" fcb NUL H_MSG: fcb " H:X=" fcb NUL X_MSG: fcb ":" fcb NUL PC1_MSG: fcb " -- PC=" fcb NUL PC2_MSG: fcb NUL END_MSG: fcb "EE" ;************************************************************ #include "../utils.asm" #include "./disasm08.asm" ;************************************************************ ; Vectors ;************************************************************ org $ffd0 adc_vec: fdb $8000 ; ADC Conversion Complete vector to user jump table keyboard_vec: fdb $8003 ; Keyboard Vector to user jump table scitx_vec: fdb $8006 ; SCI Transmit Vector to user jump table scirx_vec: fdb $8009 ; SCI Receive Vector to user jump table scierr_vec: fdb $800C ; SCI Error Vector to user jump table rmb 4 ; RESERVED timbch3_vec: fdb $800F ; TIMB Channel 3 Vector to user jump table timbch2_vec: fdb $8012 ; TIMB Channel 2 Vector to user jump table spitx_vec: fdb $8015 ; SPI Transmit Vector to user jump table spirx_vec: fdb $8018 ; SPI Receive Vector to user jump table timb_of_vec: fdb $801B ; TIMB Overflow Vector to user jump table timb_ch1_vec: fdb $801E ; TIMB Channel 1 Vector to user jump table timb_ch0_vec: fdb $8021 ; TIMB Channel 0 Vector to user jump table tima_of_vec: fdb $8024 ; TIMA Overflow Vector to user jump table tima_ch3_vec: fdb $8027 ; TIMA Channel 3 Vector to user jump table tima_ch2_vec: fdb $802A ; TIMA Channel 2 Vector to user jump table tima_ch1_vec: fdb $802D ; TIMA Channel 1 Vector to user jump table tima_ch0_vec: fdb $8030 ; TIMA Channel 0 Vector to user jump table pit_vec: fdb $8033 ; PIT Vector to user jump table pll_vec: fdb $8036 ; PLL Vector to user jump table irq_veq: fdb $8039 ; ~IRQ1 Vector to user jump table break_vec: fdb _break_pt ; SWI break point vector reset_vec: fdb _bootreset ; Reset vector to start of Monitor