⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bootldr3.asm

📁 pic bootloader 用于PIC单片机的主程序下载
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;
;  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 + -