?? bootldr3.asm
字號:
;
; bootldr3.asm Flash-resident bootloader for the PIC 16f873
;
; Derived from the original Microchip program, boot877.asm
;
;
; This bootloader uses the state of PB1 to determine action. If PB1 is
; low on reset, the bootloader prepares to download a user file into
; memory. If PB1 is high on reset, the bootloader tests the value in
; a reserved flash cell, CodeStatus, to see if memory contains a valid
; code image. If CodeStatus is zero, the code image is assumed valid
; and control jumps to StartUserCode to run the downloaded image.
;
list p=16f873, st=OFF, x=OFF, n=0
errorlevel -302
#include <p16f873.inc>
#include "bank.mac"
__CONFIG _BODEN_OFF & _CP_OFF & _PWRTE_ON & _WDT_OFF & _WRT_ENABLE_ON & _XT_OSC & _DEBUG_OFF & _CPD_OFF & _LVP_OFF
;-----------------------------------------------------------------------------
;Constants
;
;
; Define the version as a byte literal. This will be displayed as part
; of the user prompt, as two hex characters.
;
VERSION equ 01
;
; I changed the download selector input to PB1 from the original of
; PB0. I didn't want to tie up the valuable INT* pin for this selection.
;
TEST_INPUT EQU 1 ;Port B Pin 1 input indicates download
;
; The following baud rate constants assume a 4.0 MHz crystal.
;
BAUD_9600 equ 0x19
BAUD_19200 equ 0x0c
BAUD_DEFAULT equ BAUD_9600
;-----------------------------------------------------------------------------
;Variables in bank0
CBLOCK 0x20
AddressH: 1 ;flash program memory address high byte
AddressL: 1 ;flash program memory address low byte
NumWords: 1 ;number of words in line of hex file
Checksum: 1 ;byte to hold checksum of incoming data
Counter: 1 ;to count words being saved or programmed
TestByte: 1 ;byte to show reset vector code received
HexByte: 1 ;byte from 2 incoming ascii characters
Temp: 1 ;temp byte for general use
DataPointer: 1 ;pointer to data in buffer
DataArray: 0x40 ;buffer for storing incoming data
ENDC
;=============================================================================
;Reset vector code
ORG 0x0000
ResetVector:
movlw high Main
movwf PCLATH ;set page bits for page3
goto Main ;go to boot loader
;=============================================================================
;Start of boot code in upper memory traps accidental entry into boot code area
; ORG 0x1e00 ;Use last part of page3 for PIC16F876/7
; ORG 0x0e00 ;Use last part of page1 for PIC16F873/4
; ORG 0x0600 ;Use last part of page0 for PIC16F870/1
ORG 0xe00 ;leave lots of room for loader
StartOfBoot:
movlw high TrapError ;trap if execution runs into boot code
movwf PCLATH ;set correct page
TrapError:
goto TrapError ;trap error and wait for reset
;-----------------------------------------------------------------------------
;Relocated user reset code to jump to start of user code
;Must be in bank0 before jumping to this routine
StartUserCode:
clrf PCLATH ;set correct page for reset condition
nop ;relocated user code replaces this nop
nop ;relocated user code replaces this nop
nop ;relocated user code replaces this nop
nop ;relocated user code replaces this nop
movlw high TrapError1 ;trap if no goto in user reset code
movwf PCLATH ;set correct page
TrapError1:
goto TrapError1 ;trap error and wait for reset
;-----------------------------------------------------------------------------
;Program memory location to show whether valid code has been programmed
CodeStatus:
DA 0x3fff ;0 for valid code, 0x3fff for no code
;-----------------------------------------------------------------------------
;Main boot code routine
;Tests to see if a load should occur and if valid user code exists
Main:
Bank0 ;change to bank0 in case of soft reset
btfss PORTB,TEST_INPUT ;check pin for boot load
goto Loader ;if low then do bootload
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
btfss STATUS,Z ;test Z flag
TrapError2:
goto TrapError2 ;if not zero then is no valid code
goto StartUserCode ;if zero then run user code
;-----------------------------------------------------------------------------
;Start of routine to load and program new code
Loader:
Bank0 ; entry from vector at end of ROM
clrf TestByte ; indicate no reset vector code yet
call LoadStatusAddr ; load address of CodeStatus word
movlw 0x3f ; load data to indicate no program
movwf EEDATH
movlw 0xff ; load data to indicate no program
movwf EEDATA
call FlashWrite ; write new CodeStatus word
call SerialSetup ; set up serial port
goto GetCmd ; skip initial prompt
;-----------------------------------------------------------------------------
;Get new line of hex file starting with ':'
;Get first 8 bytes after ':' and extract address and number of bytes
GetNewLine:
call SendCRLF ; make it pretty
movlw VERSION ; get version number
call SendByte ; send as two hex digits
movlw '>' ; issue prompt
call SerialTransmit
GetCmd:
call SerialReceive ; get new byte from serial port
xorlw 0x0a ; linefeed?
btfsc STATUS,Z
goto GetCmd ; yes, just skip silently
xorlw 0x0a ; restore char
call SerialTransmit ; echo char
xorlw ':' ; check if ':' received
btfsc STATUS,Z
goto GetRec ; got :, start processing record
xorlw ':' ; restore the char
xorlw 0dh ; not :, is it CR?
btfsc STATUS,Z
goto GetNewLine ; got CR, just start over
xorlw 0dh ; restore the char
xorlw 'G' ; was it GO command?
btfsc STATUS,Z
goto DoGoCmd ; do the GO
;
; Control reaches this point if the user sent an unknown command.
; Receive and echo all characters until CR.
;
EatLine:
call SerialReceive ; get char from serial port
xorlw 0ah ; line-feed?
btfsc STATUS,Z
goto EatLine ; yes, ignore it
xorlw 0ah ; recover char
xorlw 0dh ; CR?
btfsc STATUS,Z
goto GetNewLine ; yes, done with this line
xorlw 0dh ; recover char
call SerialTransmit ; echo the char
goto EatLine ; loop until hit CR
;
; Control reaches this point after user enters a semicolon, marking
; the start of a HEX record. Note that the leading semi has already
; been echoed.
;
GetRec:
clrf Checksum ; start with checksum zero
call GetHexByte ; get number of program data bytes in line
andlw 0x1F ; limit number in case of error in file
movwf NumWords
bcf STATUS,C
rrf NumWords,F ; divide by 2 to get number of words
call GetHexByte ; get upper half of program start address
movwf AddressH
call GetHexByte ; get lower half of program start address
movwf AddressL
bcf STATUS,C
rrf AddressH,F ;divide address by 2 to get word address
rrf AddressL,F
call GetHexByte ;get record type
xorlw 0x01
btfsc STATUS,Z ;check if end of file record (0x01)
goto FileDone ;if end of file then all done
movf HexByte,W
xorlw 0x00
btfss STATUS,Z ;check if regular line record (0x00)
goto LineDone ;if not then ignore line and send '.'
movlw 0xe0
addwf AddressH,W ;check if address >= 0x2000 (was <)
btfsc STATUS,C ;which is ID locations and config bits
goto LineDone ;if so then ignore line and send '.'
;-----------------------------------------------------------------------------
;Get data bytes and checksum from line of hex file
movlw DataArray
movwf FSR ;set pointer to start of array
movf NumWords,W
movwf Counter ;set counter to number of words
GetData:
call GetHexByte ;get low data byte
movwf INDF ;save in array
incf FSR,F ;point to high byte
call GetHexByte ;get high data byte
movwf INDF ;save in array
incf FSR,F ;point to next low byte
decfsz Counter,F
goto GetData
call GetHexByte ;get checksum
movf Checksum,W ;check if checksum correct
btfss STATUS,Z
goto ErrorMessage
;
; Get saved data one word at a time to program into flash
;
movlw DataArray
movwf FSR ;point to start of array
movf NumWords,W
movwf Counter ;set counter to half number of bytes
;
; Check if address is in reset code area
;
CheckAddress:
movf AddressH,W ;checking for boot location code
btfss STATUS,Z ;test if AddressH is zero
goto CheckAddress1 ;if not go check if reset code received
movlw 0xfc
addwf AddressL,W ;add 0xfc (-4) to address
btfsc STATUS,C ;no carry means address < 4
goto CheckAddress1 ;if not go check if reset code received
bsf TestByte,0 ;show that reset vector code received
movf AddressL,W ;relocate addresses 0-3 to new location
addlw low (StartUserCode + 1) ;add low address to new location
Bank2 ;change from bank0 to bank2
movwf EEADR ;load new low address
movlw high (StartUserCode + 1) ;get new location high address
movwf EEADRH ;load high address
goto LoadData ;go get data byte and program into flash
;-----------------------------------------------------------------------------
;Check if reset code has been received
;Check if address is too high and conflicts with boot loader
CheckAddress1:
btfss TestByte,0 ;check if reset vector code received first
goto ErrorMessage ;if not then error
movlw high StartOfBoot ;get high byte of address
subwf AddressH,W
btfss STATUS,C ;test if less than boot code address
goto LoadAddress ;yes so continue with write
btfss STATUS,Z ;test if equal to boot code address
goto ErrorMessage ;no so error in high byte of address
movlw low StartOfBoot ;get low byte of address
subwf AddressL,W
btfsc STATUS,C ;test if less than boot code address
goto ErrorMessage ;no so error in address
;-----------------------------------------------------------------------------
;Load address and data and write data into flash
LoadAddress:
movf AddressH,W ;get high address
Bank2 ;change from bank0 to bank2
movwf EEADRH ;load high address
Bank0 ;change from bank2 to bank0
movf AddressL,W ;get low address
Bank2 ;change from bank0 to bank2
movwf EEADR ;load low address
LoadData:
movf INDF,W ;get low byte from array
movwf EEDATA ;load low byte
incf FSR,F ;point to high data byte
movf INDF,W ;get high byte from array
movwf EEDATH ;load high byte
incf FSR,F ;point to next low data byte
call FlashWrite ;write data to program memory
Bank0 ;change from bank3 to bank0
incfsz AddressL,F ;increment low address byte
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -