?? bootldr3.asm
字號(hào):
goto CheckLineDone ;check for rollover
incf AddressH,F ;if so then increment high address byte
CheckLineDone:
decfsz Counter,F ;check if all words have been programmed
goto CheckAddress ;if not then go program next word
;-----------------------------------------------------------------------------
;Done programming line of file
LineDone:
movlw '.' ; line has been programmed so
call SerialTransmit ; transmit progress indicator back
call SerialReceive ; eat the trailing CR (hopefully!)
goto GetNewLine ; go get next line hex file
;
; Control reaches this point after loading a file. Change the
; status indicator to show that a legal file has been loaded,
; then issue the success indicator and return to the top for
; the next command.
;
FileDone:
File1:
call SerialReceive ; need to eat checksum for file record
xorlw 0x0d ; hit the CR yet?
btfsc STATUS,Z
goto File2 ; got the CR, finish the report
xorlw 0x0d ; need to echo, restore the char
call SerialTransmit ; do the echo
goto File1 ; loop until CR
File2:
call LoadStatusAddr ;load address of CodeStatus word
clrf EEDATH ;load data to indicate program exists
clrf EEDATA ;load data to indicate program exists
call FlashWrite
call SendCRLF
movlw 'O' ; show success
call SerialTransmit
movlw 'K'
call SerialTransmit
goto GetNewLine
;
; An error occurred in the file download. Send an error
; indicator, then return to the top for another command.
;
ErrorMessage:
call SendCRLF
movlw '!' ; show failure
call SerialTransmit
call SerialTransmit
goto GetNewLine
;
; Control reaches this point to process the GO command. Check for
; a valid file (CodeStatus). If OK, jump to user program, otherwise,
; send an error code. Note that this code is copied from the code at
; Main that runs on power-up in user mode.
;
; There are two forms of this command:
;
; G <CR> code status must be good before jump to user code.
; G! <CR> jumps to user code WITHOUT checking code status
;
; Note that the G! form forces the CodeStatus word to 0 before jumping
; to the user code. This means subsequent resets with the bootloader
; select line high will also jump to user code. There had better be
; something there!
;
DoGoCmd:
call SerialReceive ; get next char
xorlw 0x0d ; check it
btfss STATUS,Z
goto GoCmd1 ; no CR, might be !
call SendCRLF ; echo CR and LF
call LoadStatusAddr ; load address of CodeStatus word
call FlashRead ; read data at CodeStatus location
Bank2 ; change from bank3 to bank2
movf EEDATA,F ; set Z flag if data is zero
Bank0 ; change from bank2 to bank0
btfsc STATUS,Z ; skip if code status is bad
goto StartUserCode ; run the user program
call SendCRLF ; make it pretty
movlw 'N' ; get the failure marker
call SerialTransmit ; send it
movlw 'O' ; get rest of marker
call SerialTransmit ; send it
goto GetNewLine ; back to the top
GoCmd1:
xorlw 0x0d ; restore char
xorlw '!' ; force char?
btfss STATUS,Z
goto EatLine ; not !, must be trash...
movlw '!' ; need to echo
call SerialTransmit ;
call SerialReceive ; get next char
xorlw 0x0d ; better be CR
btfss STATUS,Z
goto EatLine ; no CR, ignore it
call SendCRLF ; echo CR and LF
call LoadStatusAddr ;load address of CodeStatus word
clrf EEDATH ;load data to indicate program exists
clrf EEDATA ;load data to indicate program exists
call FlashWrite
goto StartUserCode ; run the user program (hopefully)
;
; SendCRLF send a CR/LF sequence
;
SendCRLF:
movlw 0x0d ; CR
call SerialTransmit
movlw 0x0a ; LF
call SerialTransmit
return
;
; SendByte send a byte as two hex characters
;
SendByte:
movwf Temp ; save a copy
swapf Temp,w ; move top nybble to w
call outnyb ; send it
movf Temp,w ; move low nybble to w
call outnyb ; send and return
return
;
; outnyb send low nybble of w as hex to serial port
;
outnyb:
andlw 0x0f ; leave only low 4 bits
addlw -.10 ; test against 9
btfsc STATUS,C ; skip if value was <= 9
addlw 7 ; 10 or more, adjust to hex
addlw .10 ; restore value
addlw '0' ; make it ascii
call SerialTransmit ; and send it
return
;
; LoadStatusAddr load address of CodeStatus word to flash addr regs
;
; This routine returns in bank2.
;
LoadStatusAddr:
Bank2 ;change from bank0 to bank2
movlw high CodeStatus ;load high addr of CodeStatus location
movwf EEADRH
movlw low CodeStatus ;load low addr of CodeStatus location
movwf EEADR
return
;
; GetHexByte get two ASCII digits, convert to a byte
;
; This routine reads and echoes two characters from the USART
; and converts them to a single byte, returned in W. No check
; is made for legality. The byte is added to the checksum.
; This routine returns in bank0.
GetHexByte:
call SerialReceive ;get new byte from serial port
call SerialTransmit ;echo the character
addlw 0xbf ;add -'A' to Ascii high byte
btfss STATUS,C ;check if positive
addlw 0x07 ;if not, add 17 ('0' to '9')
addlw 0x0a ;else add 10 ('A' to 'F')
movwf HexByte ;save nibble
swapf HexByte,F ;move nibble to high position
call SerialReceive ;get new byte from serial port
call SerialTransmit ;echo the character
addlw 0xbf ;add -'A' to Ascii low byte
btfss STATUS,C ;check if positive
addlw 0x07 ;if not, add 17 ('0' to '9')
addlw 0x0a ;else add 10 ('A' to 'F')
iorwf HexByte,F ;add low nibble to high nibble
movf HexByte,W ;put result in W reg
addwf Checksum,F ;add to cumulative checksum
return
;
; SerialSetup initialize the USART
;
; Configure the USART for transmit and receive at the default
; baud rate.
;
; Note that this routine returns with the banking registers set
; for bank0.
;
SerialSetup:
Bank1
movlw BAUD_DEFAULT ;set baud rate
movwf SPBRG
bsf TXSTA,BRGH ;baud rate high speed option
bsf TXSTA,TXEN ;enable transmission
Bank0 ;change from bank1 to bank0
bsf RCSTA,CREN ;enable reception
bsf RCSTA,SPEN ;enable serial port
return
;
; SerialReceive read a byte from USART, return it in W
;
; Note that this routine returns with the banking registers set
; for bank0.
;
SerialReceive:
Bank0 ;change from unknown bank to bank0
btfss PIR1,RCIF ;check if data received
goto $-1 ;wait until new data
movf RCREG,W ;get received data into W
return
;
; SerialTransmit transmit byte in W register from USART
;
; Note that this routine returns with the banking registers set
; for bank0.
;
SerialTransmit:
Bank0 ;change from unknown bank to bank0
btfss PIR1,TXIF ;check that buffer is empty
goto $-1
movwf TXREG ;transmit byte
return
;
; FlashWrite write to a location in the flash program memory.
;
; The calling routine should write the address of interest in EEADRH
; and EEADR, and the data in EEDATH and EEDATA.
;
; Note that this routine returns with the banking registers set
; for bank3.
;
FlashWrite:
Bank3 ;change from bank2 to bank3
movlw 0x84 ;enable writes to program flash
movwf EECON1
movlw 0x55 ;do timed access writes
movwf EECON2
movlw 0xaa
movwf EECON2
bsf EECON1,WR ;begin writing to flash
nop ;processor halts here while writing
nop
return
;-----------------------------------------------------------------------------
;
; FlashRead read from a location in the flash program memory
;
; Address is in EEADRH and EEADR, data returned in EEDATH and EEDATA
; This routine returns in bank3.
;
FlashRead:
Bank2 ; get it right
movlw 0x1f ; keep address within range
andwf EEADRH,F
Bank3 ; change from bank2 to bank3
movlw 0x80 ; enable reads from program flash
movwf EECON1
bsf EECON1,RD ; read from flash
nop ; processor waits while reading
nop
return
;
; The following instructions act as vectors to permit other programs
; access to routines within the monitor. Programs should execute
; a CALL to one of these addresses, rather than a CALL directly to
; the target routine, as the target routine might move in future
; versions of this program!
;
; Pay close attention to the banking when these routines exit, as
; they often change the current register bank.
;
; Note that entry to the Loader at $xxff should be via a GOTO, not
; a CALL.
;
org StartOfBoot+0x1f8
return ; $1ff8
return ; $1ff9
return ; $1ffa
return ; $1ffb
goto SerialSetup ; $1ffc
goto FlashRead ; $1ffd
goto FlashWrite ; $1ffe
goto Loader ; $1fff
;-----------------------------------------------------------------------------
END
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -