;=============================================================================
;
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
; **********************************************************************
; **********************************************************************