Search This Blog

Sunday, November 21, 2010

BootLoader - Pic Code

Here is the Pic code for the bootloader.  Hope it copies ok.

;******************************************************************************
;                                                                            
;       Filename:   bootloader.asm                                                                          
;       Date:   2010.11.21                                                
;   File Version:   1.0.0                                                      
;                                                                            
;       Author:   Tom Hunt                                                  
;                                                                            
;******************************************************************************
;  NOTES: A bootloader for 16f88.  Runs at 9600 baud at 4 MHz currently.
;  Relies on Python code icsp.py to run.  Reserves the last 224 bytes
;         For the bootloader.
;
;         PC_flash: 0xC1  nr  AddrH  AddrL  ...(DataLo DataHi)...  crc
;  PIC: 0xC1   k k                                                        
;******************************************************************************
;  CHANGE LOG:                                                      
;                                                                    
;                                                                    
;******************************************************************************

list      R=DEC, p=16f88           ; list directive to define processor

#include "p16f88.inc"

__CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
__CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

;******************************************************************************
;  CONSTANT DEFINITIONS                                                      
;******************************************************************************

#define maxFlash 0x1000
#define bootLoader (maxFlash - 224) ;
#define userFirstFour (maxFlash - 32)
#define oneBefore (userFirstFour - 1 )
#define rewriteAddrH 0x00F
#define rewriteAddrL 0x0E0
#define startSignal 0xc1
;errorlevel 1, -302

;******************************************************************************
;  VARIABLE DEFINITIONS                                                      
;******************************************************************************

cblock 0x20
buffer:80
endc

cblock 0x70
crc
counter
i
cnt1
cnt2
cnt3
flag
endc

;******************************************************************************
;  MACRO DEFINITIONS                                                      
;******************************************************************************

bank0_no_status MACRO
clrf STATUS
ENDM

bank0 MACRO
bcf STATUS, RP1
bcf STATUS, RP0
ENDM

bank1 MACRO
bcf STATUS, RP1
bsf STATUS, RP0
ENDM

bank2 MACRO
bsf STATUS, RP1
bcf STATUS, RP0
ENDM

bank3 MACRO
bsf STATUS, RP1
bsf STATUS, RP0
ENDM

;******************************************************************************
;  PROGRAM RESET                                                      
;******************************************************************************

ORG     0x0000
PAGESEL TomBootloader
GOTO    TomBootloader

;******************************************************************************
;  BOOTLOADER CODE                                                    
;******************************************************************************

ORG bootLoader

Initb
bank2
movwf counter ; # of loops
clrf flag
movlw 0x000
movwf EEADR^0x100 ; prepare flash adress
movwf EEADRH^0x100
movlw buffer ; prepare FSR at index 0
movwf FSR
return

writeloop ; write 2 bytes = 1 instruction
movf INDF,W
movwf EEDATA^0x100
incf FSR,F
movf INDF,W
movwf EEDATH^0x100
incf FSR,F
bank3
bsf EECON1^0x180,EEPGD ; FOR NOW, NO DATA. ALWAYS PROGRAM SPACE
bsf EECON1^0x180,WREN
clrf INTCON ; shouldn't need to, but disable all interrupts
movlw 0x55
movwf EECON2^0x180
movlw 0xaa
movwf EECON2^0x180
bsf EECON1^0x180,WR
nop
nop
waitwre
btfsc EECON1^0x180,WR ;for eeprom writes (wait to finish write)
goto waitwre
bcf EECON1^0x180,WREN
bank2
incf EEADR^0x100,F ;does not cross zones
btfsc STATUS,Z ; if we overflow, increment addr high
incf EEADRH^0x100,F
decfsz counter,F
goto writeloop
return

;******************************************************************************
;  USART ROUTINES                                                      
;******************************************************************************

sendByte
movwf TXREG
bank1
btfss TXSTA^0x080,TRMT ; when TRMT is set, transmission is completed
goto $ - 1
bank0_no_status
return

; This is the same as my usual delay code. cnt gets loaded with 3 for 4MHz ~1.5 sec delay
Receive
bank0   ;_no_status ; puts us in bank0
movlw 0x03
movwf cnt1
rpt2
clrf cnt2
rpt3
clrf cnt3
rptc
btfss PIR1,RCIF ;test RX
goto $ + 8 ; endless wait for byte
btfss RCSTA,OERR
goto $ + 2
bcf RCSTA,CREN
bsf RCSTA,CREN
movf RCREG,W ;return in W
addwf crc,f ;compute crc
return

decfsz cnt3,F
goto rptc
decfsz cnt2,F
goto rpt3
decfsz cnt1,F
goto rpt2
;timeout:

way_to_exit ;exit in all other cases; must be BANK0/1
bank1
bcf RCSTA,SPEN ; deactivate USART
bank0_no_status
goto programMain

;******************************************************************************
;  MAINLINE CODE                                                      
;******************************************************************************

TomBootloader
;init serial port
bank0_no_status
clrf INTCON ; disable all interupts
bank1
movlw 0x00 ^ ( 1 << 2 ) ; Port B all output except RX on B2
movwf TRISB ^ 0x080
movlw b'01100010' ; bits for OSCCON internal clock at 4MHz
movwf OSCCON^0x080
; set up bank 1 part of AUSART
movlw 0x19 ; decimal 25 at 4 MHz for 9600 baud
movwf SPBRG^0x080
; txsta gets b'00100100' enables asynch transmit and fast(brgh)
movlw 0x00 ^ ( ( 1 << TXEN ) + ( 1 << BRGH ) )
movwf TXSTA ^ 0x080
bank0_no_status ; puts us in bank0
; rcsta gets b'10010000' enables serial port and continuous receive
movlw 0x00 ^ ( ( 1 << SPEN ) + ( 1 << CREN ) )
movwf RCSTA
movlw startSignal ; send startSignal to begin process
call sendByte
;wait for computer
call Receive
sublw startSignal ;Expect C1
skpz
goto way_to_exit

;******************************************************************************
;  ERASE ROUTINES                                                      
;******************************************************************************

; for the 16F87/88, flash memory must be erased before writing
; erasing can only be done by blocks of 32 words, with address = integer x 32
; so : 1. save the 4 first words in buffer
;      2. erase all the user memory (0x000 to 0F40)
;      3. erase the block containing the final jump (block at 0xF80)
;      4. rewrite the 4 first words from buffer
;      5. write the user program & data in flash or eeprom

; first read the 4 first words of program
movlw 4 ; and copy them back after bulkerase
call Initb

loopread ; (or direct fill of 8 bytes in buffer)
bank3
bsf EECON1^0x180,EEPGD ; select flash program memory
bsf EECON1^0x180,RD ; select read
nop
nop
bank2 ; now in bank 2
movf EEDATA^0x100,W ; store bytes in buffer
movwf INDF
incf FSR,F
movf EEDATH^0x100,W
movwf INDF
incf FSR,F
incf EEADR^0x100,F
decfsz counter,F
goto loopread
bulkErase ; erase 120 blocks of 32 words
movlw bootLoader/32
call Initb ;
loopErase
call eraseBlock
decfsz counter,F
goto loopErase
movlw rewriteAddrH
movwf EEADRH^0x100
movlw rewriteAddrL
movwf EEADR^0x100
call eraseBlock ; and erase block where user's first 4 go
goto writeJump

eraseBlock
bank3 ; now in bank 3
bcf EECON1^0x180,RD
bsf EECON1^0x180,EEPGD ; select flash program memory
bsf EECON1^0x180,WREN
bsf EECON1^0x180,FREE
clrf INTCON ; shouldn't need to, but disable all interrupts
movlw 0x55
movwf EECON2^0x180
movlw 0xAA
movwf EECON2^0x180
bsf EECON1^0x180,WR ; erase 1 block
nop
nop
bcf EECON1^0x180,WREN
bcf EECON1^0x180,FREE
bank2 ; now in bank 2
movlw 32 ; add 32 to flash memory pointer
addwf EEADR^0x100,F
btfsc STATUS,C ; if we overflow, increment addr high
incf EEADRH^0x100,F
return

writeJump ; rewrite the 4 first words of bootloader program
movlw 4
call Initb
call writeloop

;******************************************************************************
;  RECEIVE PACKETS ROUTINES                                                      
;******************************************************************************

MainLoop ; back to original program
bank0_no_status ; puts us in bank0
movlw 'k'
call sendByte
mainl
clrf crc
call Receive ;H
bank2
movwf EEADRH^0x100
;movwf flag ;used to detect if is eeprom  NOT USED FOR NOW...
call Receive ;L
bank2 ;bank2
movwf EEADR^0x100
call Receive ;counter = numInstr
movwf counter
movwf i
;incf i,F
movlw buffer ;reset FSR to index 0
movwf FSR

receivePacket ; put the data packet and crc into buffer
call Receive
movwf INDF
incf FSR,F
call Receive
movwf INDF
incf FSR,F
decfsz i,F
goto receivePacket
call Receive ; get the crc
movwf INDF
movf crc,f ;check crc
skpz
goto checksumError ;write
bank2
movlw buffer ; reset FSR to index 0
movwf FSR

call writeloop

goto MainLoop

checksumError
movlw 'n'
call sendByte
goto mainl


;******************************************************************************
;  SPACE FOR USER'S FIRST FOUR INSTRUCTIONS CODE                                                    
;******************************************************************************

ORG oneBefore

programMain
;  This is where the program's first 4 instructions will go.
;  The 4 nops will be overwritten with the first 4 instructions of the
;  user's program
;  The next 28 instructions are wasted space, needed for the 32 byte erase
clrf PCLATH ; reset to first page, so loaded program's

ORG userFirstFour
; first 4 instructions can execute
nop
nop
nop
nop

;*************************************************************
; After reset
; Do not expect the memory to be zero,
; Do not expect registers to be initialised like in catalog.

            END

No comments:

Post a Comment