; Title "ROMzap BootLoader V021200 by Bubble Software 2000." ; list P = 16F876 ; include "P16f876.inc" ; ; ------------------ ; CONFIGURATION FUSE ; ------------------ ; __CONFIG _CP_OFF & _WRT_ENABLE_ON & _HS_OSC & _WDT_OFF & _PWRTE_OFF & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF ; ; CRYSTAL SPEED = 4000000Hz ; WRN equ 2h ; wren label defined different in .inc files ; ; ---------------------------------------------------- ; RAM REGISTERS NEEDED FOR BOOT AND BREAK ROUTINES. ; ; DO NOT CHANGE OR USE THE LAST 4 RAM REGISTERS IN ANY ; RAM PAGE IF YOU ARE USING BREAK POINTS IN YOUR CODE. ; ---------------------------------------------------- ; CBLOCK 0x7C ; W_Hold ; storage for W S_Hold ; storage for STATUS dataH ; data H dataL ; data L ; ENDC ; ; ------------- ; PROGRAM START ; ------------- ; These instructions jump to the boot code first. ; org 0x0000 ; startup = 0000h ; Start movlw high(BCode) movwf PCLATH goto BCode ; ; -------------------------- ; USER START ADDRESS = 0003h ; -------------------------- ; org 0x0003 ; User code start address ; UCode goto UCode ; ; ----------------------------- ; START OF BREAK CODE EXECUTION ; ----------------------------- ; org 0x1F00 ; MonCode movwf dataH ; save break code value swapf STATUS,W clrf STATUS ; RAM Page 0 movwf S_Hold movf FSR,W ; save FSR to PC movwf TXREG ; swapf S_Hold,W movwf STATUS swapf dataL,W ; send PCLATH clrf STATUS ; RAM Page 0 movwf TXREG call TransWt ; wait for TX to end ; swapf S_Hold,W ; send STATUS movwf TXREG ; movwf STATUS movf W_Hold,W ; send W Reg clrf STATUS ; RAM Page 0 movwf TXREG call TransWt ; wait for TX to end ; swapf S_Hold,W movwf STATUS movf dataH,W ; send break code number clrf STATUS ; RAM Page 0 movwf TXREG call TransWt ; wait for TX to end ; goto WaitCom ; wait and receive commands from PC ; ; --------------------------- ; END OF BREAK CODE EXECUTION ; --------------------------- ; EndBrk call Receive ; restore FSR value movwf FSR call Receive ; get PCLATH value movwf dataL call Receive ; get STATUS value movwf S_Hold call Receive ; get W reg value movwf W_Hold bsf STATUS,RP0 ; make sure in both RAM pages movwf W_Hold call RestEEP ; restore normal EEPROM access movlw 'M' ; resume ack to PC movwf TXREG call TransWt ; wait for TX to end ; movf dataL,W movwf PCLATH movf S_Hold,W movwf STATUS swapf W_Hold,F swapf W_Hold,W return ; ; ------------------------------------ ; BOOT CODE START AND INITIALISE PORTS ; ------------------------------------ ; BCode movlw b'00000000' movwf PORTA movlw b'00000000' movwf PORTB movlw b'01000000' movwf PORTC bsf STATUS,RP0 ; RAM Page 1 movlw b'11000011' movwf TRISA movlw b'00010000' movwf TRISB movlw b'10000000' movwf TRISC ; ; ------------------------- ; SET ANALOG/DIGITAL INPUTS ; ------------------------- ; movlw b'00000100' movwf ADCON1 ; ; ------------------------------------ ; SET BAUD RATE TO COMMUNICATE WITH PC ; ------------------------------------ ; Boot Baud Rate = 19200, No Parity, 1 Stop Bit ; movlw 0x0C ; 19200 baud movwf SPBRG movlw b'00100100' ; brgh = high (2) movwf TXSTA ; enable Async Transmission, set brgh movlw b'10010000' ; enable Async Reception clrf STATUS ; RAM Page 0 movwf RCSTA ; ; ------------------------------------ ; PROVIDE A SETTLING TIME FOR START UP ; ------------------------------------ ; clrf dataL settle decfsz dataL,F goto settle ; movf RCREG,W movf RCREG,W movf RCREG,W ; flush receive buffer ; ; ------------------------------ ; SEND Boot Loader COMMAND TO PC ; ------------------------------ ; movlw 'B' ; send boot online to PC movwf TXREG movlw 'L' movwf TXREG ; ; ------------------------------------ ; IF RX RECEIVED IN TIME, EXECUTE BOOT ; ------------------------------------ ; clrf dataH BCheck call RestEEP ; just does a small delay btfsc PIR1,RCIF ; (5) check for received data goto GotChar ; decfsz dataL,F goto BCheck decfsz dataH,F goto BCheck goto UProg ; GotChar movf RCREG,W ; clear RX register ; ; ------------------------------ ; SET PROGRAMMING FOR ROM ACCESS ; ------------------------------ ; SetROM bsf STATUS,RP1 ; RAM Page 2 bsf STATUS,RP0 ; RAM Page 3 bsf EECON1,WRN ; enable writes bsf EECON1,EEPGD ; point to program ROM ; ; ---------------------- ; WAITING FOR PC COMMAND ; ---------------------- ; WaitCom call Receive ; wait and read from RS232 addwf PCL,F goto ProgROM ; program rom location (0) goto UpAddr ; change address (1) goto IncAdd ; increment address (2) goto ReadRAM ; read RAM (3) goto ModRAM ; change RAM (4) goto UProg ; start user code (5) goto EndBrk ; return to user code after a break (6) movlw 'U' ; ack to PC and run from 0000h (7) movwf TXREG call TransWt ; wait for TX to end call RestEEP ; user code accesses EEPROM clrf PCLATH goto Start ; UProg call RestEEP ; user code accesses EEPROM ToUser movlw High(UCode) ; set user code ROM page into pclath movwf PCLATH goto UCode ; ; ----------- ; PROGRAM ROM ; ----------- ; ProgROM call Receive ; ROM data h movwf dataH call Receive ; ROM data l movwf dataL ; ; Do not program ROM if old data is the same ; bsf STATUS,RP1 ; RAM Page 2 bsf STATUS,RP0 ; RAM Page 3 call ReadROM btfsc STATUS,Z goto IncAdd ; old data is same as new data ; ; Begin programming ROM ; movf dataH,W movwf EEDATH ; hi ROM data ; movf dataL,W movwf EEDATA ; lo ROM data ; ; Begin programming process ; bsf STATUS,RP0 ; RAM Page 3 call WrProc ; start the write process ; ; Read back data from newly programmed location to verify it ; call ReadROM btfsc STATUS,Z goto IncAdd ; verified OK ; ; A programming error occurred - send 'E' response to PC ; movlw 'E' ; tell PC, programming error goto SendACK ; ; ------------------ ; CHANGE ROM ADDRESS ; ------------------ ; UpAddr call Receive ; ROM data h bsf STATUS,RP1 ; RAM Page 2 movwf EEADRH ; hi ROM address xorlw 0xFF ; if = 0xFF then return Chip and UART flags btfsc STATUS,Z goto CDUART ; call Receive ; ROM data l bsf STATUS,RP1 ; RAM Page 2 movwf EEADR ; lo ROM address goto PCack ; ; --------------------- ; CHIP TYPE - UART FLAG ; --------------------- ; CDUART call Receive movlw 0xE5 goto SendACK ; ; -------------------------- ; INCREMENT ROM ADDRESS ONCE ; -------------------------- ; IncAdd bsf STATUS,RP1 ; RAM Page 2 incf EEADR,F ; increment ROM address btfsc STATUS,Z incf EEADRH,F ; ; ----------------- ; ACKNOWLEDGE TO PC ; ----------------- ; PCack movlw 'A' SendACK clrf STATUS ; RAM Page 0 movwf TXREG goto WaitCom ; ; ------------------ ; FINISHED WITH UART ; ------------------ ; endUART bsf STATUS,RP0 ; RAM Page 1 clrf TXSTA ; disable UART TX clrf STATUS ; RAM Page 0 clrf RCSTA ; disable UART RX return ; ; ---------------------- ; SUBROUTINE TO READ RAM ; ---------------------- ; ReadRAM call Receive ; get RAM address btfsc STATUS,Z goto Eread ; 0 = read EEPROM ; movwf FSR call Receive ; get STATUS IRP value bcf STATUS,IRP btfsc RCREG,7 bsf STATUS,IRP ; movf INDF,W ; send byte of RAM data to PC goto SendACK ; ; ------------------------- ; SUBROUTINE TO MODIFIY RAM ; ------------------------- ; RAM values are sent back from PC with address first ; ModRAM call Receive ; get RAM address btfsc STATUS,Z goto Ewrite ; 0 = write EEPROM ; movwf FSR call Receive ; get STATUS IRP value bcf STATUS,IRP btfsc RCREG,7 bsf STATUS,IRP ; call Receive ; get RAM data movwf INDF goto SendACK ; ; ---------------------------- ; RECEIVE CHARACTER FROM RS232 ; ---------------------------- ; This routine does not return until a character is received. ; Receive clrf STATUS ; RAM Page 0 RecA btfss PIR1,RCIF ; (5) check for received data goto RecA ; movf RCREG,W return ; ; ------------------------------------ ; WAIT UNTIL RS232 IS FINISHED SENDING ; ------------------------------------ ; TransWt bsf STATUS,RP0 WtHere btfss TXSTA,TRMT ; (1) transmission is complete if hi goto WtHere ; clrf STATUS ; RAM Page 0 return ; ; ----------------------------------------- ; SUBROUTINE COMPARE ROM VALUE WITH dataH/L ; ----------------------------------------- ; If values compare OK, then Z flag is set = 1 on return ; STATUS points to RAM Page 3 on entry, Page 2 on exit ; ReadROM bsf EECON1,RD ; read back ROM location nop ; NOP's needed for read nop bcf STATUS,RP0 ; RAM Page 2 movf EEDATA,W xorwf dataL,W btfss STATUS,Z return ; error ; movf EEDATH,W andlw 3Fh xorwf dataH,W return ; ; ---------------------------------------------- ; RESTORE DEFAULT PROGRAMMING TO INTERNAL EEPROM ; ---------------------------------------------- ; RestEEP bsf STATUS,RP0 ; RAM Page 3 bsf STATUS,RP1 bcf EECON1,WRN ; disable writes bcf EECON1,EEPGD ; point to EEPROM clrf STATUS ; RAM Page 0 return ; ; ----------- ; EEPROM READ ; ----------- ; Eread call Receive ; wait and read from RS232 bsf STATUS,RP1 ; RAM Page 2 movwf EEADR bsf STATUS,RP0 ; RAM Page 3 bcf EECON1,EEPGD ; point to EEPROM bsf EECON1,RD bcf STATUS,RP0 ; RAM Page 2 movf EEDATA,W goto EndEEP ; ; ------------ ; EEPROM WRITE ; ------------ ; Ewrite call Receive ; wait and read from RS232 bsf STATUS,RP1 ; RAM Page 2 movwf EEDATA ; call Receive ; wait and read from RS232 bsf STATUS,RP1 ; RAM Page 2 movwf EEADR ; bsf STATUS,RP0 ; RAM Page 3 bcf EECON1,EEPGD ; point to EEPROM bsf EECON1,WRN call WrProc ; start the write process ; WtEep btfsc EECON1,WR goto WtEep ; bcf EECON1,WRN bsf EECON1,EEPGD ; point to ROM EndEEP clrf STATUS movwf TXREG goto SetROM ; ; ---------------------- ; EEPROM WRITE PROCEDURE ; ---------------------- ; WrProc movlw 55h movwf EECON2 movlw 0xaa movwf EECON2 bsf EECON1,WR nop ; NOP's needed for internal write nop return ; ; -------------------------------- ; DIRECT ENTRY POINT FOR BOOT CODE ; -------------------------------- ; org 0x1FFF ; goto SetROM ; ; end