Here is the final installment. I feel like there must be MANY errors, but maybe not. I have not tried to compile yet, I thought maybe you kind folks might give it a look over for glaring errors.
Code:' ***************************************************************************** ' Software License Agreement ' ' The software supplied herewith by PBP forum members ' (the “Company”) for Microchip's PICmicro® Microcontroller's is ' intended and supplied to you, the Company’s customer, for use ' solely and exclusively on Microchip PICmicro Microcontroller ' products. The software is owned by the Company and/or its ' supplier, and is protected under applicable copyright laws. All ' rights are reserved. Any use in violation of the foregoing ' restrictions may subject the user to criminal sanctions under ' applicable laws, as well as to civil liability for the breach of ' the terms and conditions of this license. ' ' THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, ' WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED ' TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ' PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, ' IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR ' CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. ' ' ' This software has been ported from Microchip's AN851 bootloader ' Changes have been made and will be made as the company sees fit. ' This version is for 16F's, there is another version for 18F's ' ' ' Memory Map ' ----------------- ' | 0x0000 | Reset vector ' | | ' | 0x0004 | Interrupt vector ' | | ' | | ' |Boot Block | (this program) ' | | ' | 0x0200 | Re-mapped Reset Vector ' | 0x0204 | Re-mapped High Priority Interrupt Vector ' | | ' | | ' | | ' |Code Space | User program space ' | | ' | | ' | | ' | 0x3FFF | ' ----------------- ' ' Incomming data format: ' ' {STX}{STX}{DATA}{CHKSUM}{ETX} ' / \ ' ________/ \____________________________ ' / \ ' {COMMAND}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}... ' ' Definitions: ' ' STX - Start of packet indicator ' ETX - End of packet indicator ' LEN - Length of incomming packet ' DATA - General data up to 255 bytes ' CHKSUM - The 8-bit two's compliment sum of LEN & DATA ' COMMAND - Base command ' DLEN - Length of data associated to the command ' ADDR - Address up to 24 bits ' DATA - Data (if any) ' ' ' Commands: ' ' RD_VER 00 Read Version Information ' RD_MEM 01 Read Program Memory ' WR_MEM 02 Write Program Memory ' ER_MEM 03 Erase Program Memory (NOT supported by PIC16) ' RD_EE 04 Read EEDATA Memory ' WR_EE 05 Write EEDATA Memory ' RD_CONFIG 06 Read Config Memory (NOT supported by PIC16) ' WT_CONFIG 07 Write Config Memory (NOT supported by PIC16) ' ' **************************************************************************** ' ***************************************************************************** PRGADD VAR WORD DATAWORD VAR WORD PRGADDL VAR PRGADD.LOWBYTE PRGADDH VAR PRGADD.HIGHBYTE DATAWORDL VAR DATAWORD.LOWBYTE DATAWORDH VAR DATAWORD.HIGHBYTE CHKSUM VAR BYTE ' Checksum accumulator COUNTER VAR BYTE ' General counter ABTIME VAR BYTE RXDATA VAR BYTE TXDATA VAR BYTE TEMP VAR BYTE ARRAYPOINTER VAR BYTE FAKEW VAR BYTE BIGLOOP VAR BYTE TEMPFLAG VAR BIT PCLATH_TEMP VAR BYTE ' Interrupt context STATUS_TEMP VAR BYTE ' save/restore registers W_TEMP VAR BYTE ' Frame Format ' ' {STX}{STX}[{COMMAND}{DATALEN}{ADDRL}{ADDRH}{ADDRU}{...DATA...}]{CHKSUM}{ETX} DATA_BUFF VAR BYTE[37] ' Start of receive buffer SAME ADDRESS AS COMMAND COMMAND VAR DATA_BUFF[0] ' Data mapped in receive buffer SAME ADDRESS AS DATA_BYTE DATA_COUNT VAR DATA_BUFF[1] ADDRESS_L VAR DATA_BUFF[2] ADDRESS_H VAR DATA_BUFF[3] ADDRESS_U VAR DATA_BUFF[4] PACKET_DATA VAR DATA_BUFF[5] ' ***************************************************************************** ' This is the remapping section, note the interrupt also saves context ' ***************************************************************************** @ ORG 0x0000 ' Re-map Reset vector **Not sure how to set the address to start at VReset: PCLATH = 0 goto Setup @ ORG 0x0004 'standard interrupt vector **again not sure of the PBP equal for ORG VInt: W_TEMP = W 'I am assuming this will be the "W" register STATUS_TEMP = STATUS 'We may have trouble here. ASM uses SWAP so as not to affect the status STATUS = 0 PCLATH_TEMP = PCLATH PCLATH = 0 goto RVInt ' Re-map Interrupt vector ' ***************************************************************************** ***************************************************************************** ' Setup the appropriate registers. Setup: clrwdt READ $ff,temp 'get the value of last EEPROM location IF temp = $ff then goto SRX 'BL startup goto RVReset ' If not 0xFF then normal reset SRX: RCSTA = %10000000 ' Setup rx and tx, CREN disabled TRISC.6 = 0 ' Setup tx pin TXSTA = %00100110 STATUS.IRP = 1 ' ***************************************************************************** ' ***************************************************************************** Autobaud: ' ' ___ __________ ________ ' \__/ \__________/ ' | | ' |-------- p ----------| ' ' p = The number of instructions between the first and last ' rising edge of the RS232 control sequence 0x0F. Other ' possible control sequences are 0x01, 0x03, 0x07, 0x1F, ' 0x3F, 0x7F. ' ' SPBRG = (p / 32) - 1 BRGH = 1 OPTION_REG = %00000011 'sets tmr0 to 1:16 prescale STATUS.RP0 = 0 RCSTA.CREN = 0 gosub WaitForRise TMR0 = 0 ' Start counting gosub WaitForRise ABTIME = TMR0 ' Read the timer TEMPFLAG = ABTIME.0 ABTIME = ABTIME >> 1 IF !TEMPFLAG THEN ABTIME.0 = 0 'Rounding SPBRG = ABTIME RCSTA.CREN = 1 ' Enable receive TEMP = RCREG ' To clear the Rx buffer TEMP = RCREG ' Both of them OPTION_REG = %11111111 'Return Option Reg to reset state ' ***************************************************************************** ' ***************************************************************************** ' Read and parse the data. StartOfLine: GOSUB RdRS232 ' Look for a start of line IF RXDATA != STX THEN Autobaud '{STX}{STX} ARRAYPOINTER = 0 ' Point to the beginning of Array CHKSUM = 0 ' Reset checksum GetNextDat: GOSUB RdRS232 ' Get the data IF RXDATA = STX THEN StartOfLine ' Check for a STX ' Yes, start over NoSTX: IF RXDATA = ETX THEN CheckSum ' Check for a ETX ' Yes, examine checksum NoETX: IF RXDATA = DLE THEN GOSUB RdRS232 ' Check for a DLE ' Yes, Get the next byte NoDLE: DATA_BUFF[ARRAYPOINTER] = RXDATA ' Store the data CHKSUM = CHKSUM + RXDATA ' Get sum ARRAYPOINTER = ARRAYPOINTER + 1 goto GetNextDat CheckSum: IF CHKSUM = 0 THEN Autobaud ' Checksum test ' *********************************************** ' *********************************************** ' Pre-setup, common to all commands. PRGADDL = ADDRESS_L 'Set all possible pointers PRGADDH = ADDRESS_H ARRAYPOINTER = 5 'start of data in array COUNTER = DATA_COUNT 'Setup counter IF COUNTER = 0 THEN VReset 'Non valid count (Special Command) ' *********************************************** ' *********************************************** ' Test the command field and sub-command. CheckCommand IF COMMAND } 7 THEN Autobaud ' Test for a valid command SELECT CASE COMMAND ' Perform calculated jump CASE 0 goto ReadVersion ' 0 CASE 1 goto ReadProgMem ' 1 CASE 2 goto WriteProgMem ' 2 CASE 3 goto StartOfLine ' 3 CASE 4 goto ReadEE ' 4 CASE 5 goto WriteEE ' 5 CASE 6 goto StartOfLine ' 6 CASE 7 goto StartOfLine ' 7 'maybe add jump to reset vector in this table '*********************************************** ' *********************************************** ' Commands ' ************* Read Version ' In: {STX}{STX}[{0x00}{0x02}]{0xFF}{ETX} ' OUT: {STX}{STX}[{0x00}{VERL}{VERH}]{CHKSUM}{ETX} ReadVersion: DATA_BUFF[2] = MINOR_VERSION DATA_BUFF[3] = MAJOR_VERSION FAKEW = 4 goto WritePacket '*************Read Program Memory ' In: {STX}{STX}[{0x01}{DLEN}{ADDRL}{ADDRH}{ADDRU}]{CHKSUM}{ETX} ' OUT: {STX}{STX}[{0x01}{DLEN}{ADDRL}{ADDRH}{ADDRU}{DATA}...]{CHKSUM}{ETX} ReadProgMem: RPM1: READCODE PRGADD,DATAWORD DATA_BUFF[ARRAYPOINTER] = DATAWORDL DATA_BUFF[ARRAYPOINTER + 1] = DATAWORDH ARRAYPOINTER = ARRAYPOINTER + 2 PRGADD = PRGADD + 1 COUNTER = COUNTER - 1 IF COUNTER } 0 THEN RPM1 ' Not finished then repeat DATA_COUNT = (DATA_COUNT << 1) + 5 ' Setup packet length goto WritePacket '************* Write Program Memory ' In: {STX}{STX}[{0x02}{DLENBLOCK}{ADDRL}{ADDRH}{ADDRU}{DATA}...]{CHKSUM}{ETX} ' OUT: {STX}{STX}[{0x02}]{CHKSUM}{ETX} WriteProgMem: FOR BIGLOOP = COUNTER TO 0 STEP -1 EECON1 = %10000100 ' Setup writes EEADR = EEADR & %11111100 ' Force a boundry ' B2 FOR TEMP = 1 TO 4 WRITECODE PRGADD,DATAWORD[ARRAYPOINTER] ARRAYPOINTER = ARRAYPOINTER + 2 NEXT NEXT goto SendAcknowledge ' Send acknowledge '************** Read EE ' In: {STX}{STX}[{0x04}{DLEN}{ADDRL}{ADDRH}{0x00}]{CHKSUM}{ETX} ' OUT: {STX}{STX}[{0x04}{DLEN}{ADDRL}{ADDRH}{0x00}{DATA}...]{CHKSUM}{ETX} ReadEE: FOR BIGLOOP = COUNTER TO 0 STEP -1 READ PRGADD,DATA_BUFF[ARRAYPOINTER] ARRAYPOINTER = ARRAYPOINTER + 1 PRGADD = PRGADD + 1 NEXT FAKEW = DATA_COUNT + 5 GOTO WritePacket ' In: <STX><STX>[<0x05><DLEN><ADDRL><ADDRH><0x00><DATA>...]<CHKSUM><ETX> ' OUT: <STX><STX>[<0x05>]<CHKSUM><ETX> WriteEE: FOR BIGLOOP = 0 TO COUNTER WRITE PRGADD + BIGLOOP,DATA_BUFF[ARRAYPOINTER+BIGLOOP] NEXT goto SendAcknowledge ; Send acknowledge ' *********************************************** ' *********************************************** ' Send the data buffer back. ' ' {STX}{STX}[{DATA}...]{CHKSUM}{ETX} SendAcknowledge: FAKEW = 1 ' Send acknowledge WritePacket: COUNTER = FAKEW FAKEW = STX ' Send start condition GOSUB WrRS232 GOSUB WrRS232 CHKSUM = 0 ' Reset checksum ARRAYPOINTER = 0 SendNext: ' Send DATA FOR BIGLOOP = 1 TO COUNTER FAKEW = DATA_BUFF[ARRAYPOINTER] CHKSUM = CHKSUM + FAKEW GOSUB WrData NEXT '******************************************** comf CHKSUM,W ' Send checksum addlw 0x01 ' NEEDS CONVERTING!!!!! '*********************************************** GOSUB WrData FAKEW = ETX ' Send stop condition GOSUB WrRS232 goto Autobaud ' ***************************************************************************** ' ***************************************************************************** ' Write a byte to the serial port. WrData: TXDATA = FAKEW ' Save the data IF FAKEW = STX THEN WrDLE IF FAKEW = ETX THEN WrDLE IF FAKEW != DLE THEN WrNext WrDLE: GOSUB WrRS232 'Send DLE WrNext: FAKEW = TXDATA ' Then send DATA WrRS232: clrwdt WHILE !PIR1.TXIF WEND ' Write only if TXREG is ready TXREG = FAKEW ' Start sending return ' ***************************************************************************** ' ***************************************************************************** RdRS232: clrwdt IF RCSTA.OERR THEN VReset ' Reset on overun WHILE !PIR1.RCIF WEND ' Wait for data from RS232 RXDATA = RCREG ' Save the data return ' ***************************************************************************** ' ***************************************************************************** WaitForRise: WHILE PORTC.7 WEND ' Wait for a falling edge clrwdt ' Do we need this? WHILE !PORTC.7 WEND ' Wait for starting edge return ' ***************************************************************************** ' I DON'T THINK WE NEED THE NEXT 2 SECTIONS ' CAN ANYBODY TELL ME? ' ***************************************************************************** ' Unlock and start the write or erase sequence. StartWrite ; B3 clrwdt ; B2 bsf STATUS,RP0 ; B3 movlw 0x55 ; Unlock ; B3 movwf EECON2 ; B3 movlw 0xAA ; B3 movwf EECON2 ; B3 bsf EECON1,WR ; Start the write ; B3 nop ; B3 nop ; B3 bcf STATUS,RP0 ; B2 return ; B2 ; ***************************************************************************** ; ***************************************************************************** WriteWaitEEData ; B2 bsf STATUS,RP0 ; B3 movlw b'00000100' ; Setup for EEData ; B3 movwf EECON1 ; B3 call StartWrite ; B3 btfsc EECON1,WR ; Write and wait ; B3 goto $ - 1 ; B3 bcf STATUS,RP0 ; B2 return ; B2 ; ***************************************************************************** ; ***************************************************************************** RVReset: @ORG 0x100 RVInt: @ORG 0x104 ; ***************************************************************************** END




Bookmarks