;=============================================================================

; Copyright 2000 S. Gupta

; Micro Control Journal

; PicBoot1.asm

;

; Revision: 1.00

; Date: October 6, 2000

;=============================================================================

 

      list p=16f876, st=OFF, x=OFF, n=0

      errorlevel -302

      #include <p16f876.inc>

 

      __CONFIG _BODEN_OFF & _CP_OFF & _PWRTE_ON & _WDT_OFF & _WRT_ENABLE_ON & _XT_OSC & _DEBUG_OFF & _CPD_OFF & _LVP_OFF

;-----------------------------------------------------------------------------

 

;     Constants

;     =========

DLY_COUNTT  EQU   10   

DLY_COUNTH  EQU   .125 

DLY_COUNTL  EQU   .250 

Num_Of_Tries      EQU   3      ; Number of tries before exiting to supposed user code

BAUD        EQU   0x19  ; 9600 baud at 4.00 MHz

;-----------------------------------------------------------------------------

 

;     Variables bank0

;     ===============

      CBLOCK      0x20

      AdrsH:            1      ; Location of High Byte of flash memory adrs

      AdrsL:            1      ; Location of High Byte of flash memory adrs

      Count:            1      ; Word Count in this line

      HexByte:    1     ; 2 Hex digits

      Low_Byte:   1    

      High_Byte:  1

      CountT:           1      ; Top byte of delay variable

      CountH:           1      ; High byte of delay variable

      CountL:           1      ; Low byte of delay variable         

      ENDC

;-----------------------------------------------------------------------------

 

;     Macros for register bank selection

;      ==================================

Bank0       MACRO             ;Bank 0

            bcf   STATUS,RP0

            bcf   STATUS,RP1

            ENDM

 

Bank1       MACRO             ;Bank 1

            bsf   STATUS,RP0

            bcf   STATUS,RP1

            ENDM

 

Bank2       MACRO             ;Bank 2

            bcf   STATUS,RP0

            bsf   STATUS,RP1

            ENDM

 

Bank3       MACRO             ;Bank 3

            bsf   STATUS,RP0

            bsf   STATUS,RP1

            ENDM

;=============================================================================

 

;     Normal Reset Vector

;     ===================

 

            ORG   0x0000

            movlw high Boot

            movwf PCLATH            ;set page bits for page3

            goto    Boot            ;go to boot loader

 

            ORG   0x1EF0            ; For Flash Module - PIC16F876

 

Start_Of_User_Code:

;           Place user code here  *****

 

; ============================================================================

;           Start of the Bootloader Code

; ============================================================================

            ORG   0x1f00            ; For Flash Module - PIC16F876

Boot:

            Bank0

            call      Init_Serial ; Initialize serial port

            movlw      Num_Of_Tries     

            movwf Count

Get_Cmd:

            btfss PIR1,RCIF      ; Check if Rx flag set

            call  Delay       ; If not kill time

            movf  RCREG,W            ; Char received. Read data into W

            decfsz      Count       ; If num of tries done then assume NO BootLoad

            goto  Get_Cmd

           

            goto  EXIT        ; Exit and jump to user code

 

            ; Get a line of hex file

Get_Colon:

            call  Get_Char_e      ; Get a char from serial port & echo

            xorlw ':'         ; Is it ':' ?

            btfss STATUS,Z

            goto  Get_Colon      ; If not, repeat till ':' received

 

            ; Get the number of data bytes & limit to 10H

            ; Echo each char as it is received.

            call      Get_2HexDigits_e

            andlw 0x1F       

            movwf Count

 

            ; Data will be received as Byte (2 hex digits)

            ; Divide the count by 2 to get number of Words

            ; Echo each char as it is received.

            bcf   STATUS,C

            rrf   Count      

 

            ; Get Program address

            ; Echo each char as it is received.

            call      Get_2HexDigits_e

                              ; Upper Byte of address

            movwf AdrsH

            call      Get_2HexDigits_e 

                              ; Lower Byte of address

            movwf AdrsL

 

            ; In PIC program address is indicate in Words and not in Bytes

            ; Divide the address by 2 to get word address

            bcf   STATUS,C

            rrf   AdrsH      

            rrf   AdrsL

 

Get_Data:

            ; Get data bytes

            ; Echo each char as it is received.

            call      Get_2HexDigits_e  ; Receive low data byte

            movwf Low_Byte     

            call      Get_2HexDigits_e  ; Receive high data byte

            movwf High_Byte     

 

Load_Adrs:

            ; Program flash memory

            ; Load address into flash program address register

            movf  AdrsH,W            ; Read high address

            Bank2            

            movwf EEADRH            ; Load high address

            Bank0            

            movf  AdrsL,W            ; Read low address

            Bank2            

            movwf EEADR       ; Load low address

 

Load_Data: 

            ; Load data into flash program data register

            Bank0

            movf  Low_Byte,W      ; Read low byte

            Bank2

            movwf EEDATA            ; Store low byte

            Bank0

            movf      High_Byte,W ; Read high byte

            Bank2

            movwf EEDATH            ; Store high byte

 

            call  Flash_WR      ; Program the data in Flash memory

 

            ; Increment 16 bit program memory address

            Bank0            

            incfsz      AdrsL      

            goto  Next_1           

            incf  AdrsH      

Next_1:          

            decfsz      Count       ; Check if done

            goto  Get_Data      ; Else get next data word & program

 

            ; This line of code is programmed

            ; Transmit prompt indicating that this line is done

            movlw '>'        

            call  Tx_Char           

            goto  Get_Colon      ; Get next line  

Wait_Here: 

            goto  Wait_Here      ; If reached here, then wait for reset

 

EXIT:      

            goto      Start_Of_User_Code                       

                              ; Jump to user code, which is assumed to start

                              ; at 0x1EF0

 

; -----------------------------------------------------------------------------

 

; *****************************************************************************

;                       Get_2HexDigits_e

; *****************************************************************************

; Receive two ascii digits and pack these into one hex byte

; Each character is echoed as it is received.

; This routine returns in bank0

; EXIT:

;     W contains the Byte

 

Get_2HexDigits_e:

            call  Get_Char_e      ;get new byte from serial port

           

 

            addlw 0xbf        ; Add -'A'

            btfss STATUS,C      ; If overflow then number >= 0A (10d)

            addlw 0x07        ; It is smaller add 17 ('0' to '9')

            addlw 0x0a        ; Add 10 and ignore overflow

            movwf HexByte            ; Store digit (B3-B0)

            swapf HexByte            ; Shift to MSNibble (B7-B4)

 

            call  Get_Char_e      ; Read another byte from serial port

            addlw 0xbf       

            btfss STATUS,C     

            addlw 0x07       

            addlw 0x0a       

            iorwf HexByte            ; Pack two digits

            movf  HexByte,W      ; Place result in W reg

            return

 

; End of Get_2HexDigits_e

;-----------------------------------------------------------------------------

 

; *****************************************************************************

;                       Init_Serial

; *****************************************************************************

 

; Initialize serial port

 

;Exit: In bank 0

 

Init_Serial:

            Bank1             ; Bank1

            movlw BAUD        ; 9600 Baud at 4Mhz Xtal

            movwf SPBRG

            bsf   TXSTA,BRGH      ; High speed option

            bsf   TXSTA,TXEN      ; Enable transmitter

 

            Bank0             ; Bank1

            bsf   RCSTA,CREN      ; Enable receiver

            bsf   RCSTA,SPEN      ; Enable serial port

            return

; End of Init_Serial

;-----------------------------------------------------------------------------

 

; *****************************************************************************

;                       Get_Char

; *****************************************************************************

 

; Wait for a character

; EXIT:

;     W: Char Received

;     Bank 0

 

SerialReceive:   

Get_Char:

            Bank0             ; Bank 0

Get_Char1:

            btfss PIR1,RCIF      ; Check if Rx flag set

            goto  Get_Char1      ;If not check again

            movf  RCREG,W      ;Char received. Read data into W

            return

 

; End of Get_Char

;-----------------------------------------------------------------------------

 

; *****************************************************************************

;                       Get_Char_e

; *****************************************************************************

 

; Wait for a character

; EXIT:

;     W: Char Received

;     Bank 0

 

 

Get_Char_e:

            Bank0             ; Bank 0

Get_Char_e1:

            btfss PIR1,RCIF      ; Check if Rx flag set

            goto      Get_Char_e1 ;If not check again

            movf  RCREG,W      ;Char received. Read data into W

 

            ; The next four lines of code are not needed as the code will automatically

            ; run into the following Tx_Char routine. These are reproduced here

            ; for clarity.

Tx_Char_e1:

            btfss PIR1,TXIF      ; Wait till Tx buffer is empty

            goto  Tx_Char_e1

            movwf TXREG       ; Tx char

            return

;-----------------------------------------------------------------------------

 

; *****************************************************************************

;                       Tx_Char

; *****************************************************************************

 

; Transmit a character

; ENTRY:

;     W: Char to be transmitted

; EXIT:

;     Bank 0

 

SerialTransmit:  

Tx_Char:         

            Bank0             ; Bank 0

Tx_Char1:

            btfss PIR1,TXIF      ; Wait till Tx buffer is empty

            goto  Tx_Char1

            movwf TXREG       ; Tx char

            return

 

; End of Tx_Char

;-----------------------------------------------------------------------------

 

 

; *****************************************************************************

;                       Flash_WR

; *****************************************************************************

 

; Program the flash program memory

; ENTRY:

;     EEADRH and EEADR:      Program address

;     EEDATH and EEDATA:      Data to be programmed

; EXIT:

;     Bank3

 

Flash_WR:  

            Bank3            

            bsf      EECON1,EEPGD      ; Enable flash programming

            bsf      EECON1,WREN ; Enable write to flash memory

 

            movlw 0x55       

            movwf EECON2

            movlw 0xAA

            movwf EECON2

            bsf   EECON1,WR      ; Start program operation

 

            nop              

            nop

            bcf      EECON1,WREN ; Disable write to flash

            return

 

; End of Flash_WR

;-----------------------------------------------------------------------------

 

; *****************************************************************************

;                       Delay

; *****************************************************************************

 

; EXIT:

;     Bank0

 

Delay:     

            movlw DLY_COUNTT

            movwf CountT

Delay_1:

            movlw DLY_COUNTH

            movwf CountH           

Delay_2:

            movlw DLY_COUNTL

            movwf CountL           

Delay_3:

            decfsz      CountL

            goto  Delay_3

           

            decfsz      CountH

            goto  Delay_2

           

            decfsz      CountT

            goto  Delay_1

 

            nop              

            return

 

; End of Delay

;-----------------------------------------------------------------------------

;      **********************************************************************

;      **********************************************************************

            END

;      **********************************************************************

;      **********************************************************************