Зарегистрирован: Чт мар 05, 2015 07:14:58 Сообщений: 131
Рейтинг сообщения:0
Решил воспользоваться микрочиповским бутлодером AN1310 вроде все сделал как в даташите: настроил конфигурационные биты: Подкорректировал bootconfig.inc в соответствии со схемой и камнем (использую UART2): Спойлер
Код:
; Copyright (c) 2002-2011, Microchip Technology Inc. ; ; Microchip licenses this software to you solely for use with Microchip ; products. The software is owned by Microchip and its licensors, and ; is protected under applicable copyright laws. All rights reserved. ; ; SOFTWARE IS PROVIDED "AS IS." MICROCHIP EXPRESSLY DISCLAIMS ANY ; WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT ; NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ; FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ; MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR ; CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR ; EQUIPMENT, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY ; OR SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED ; TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, ; OR OTHER SIMILAR COSTS. ; ; To the fullest extent allowed by law, Microchip and its licensors ; liability shall not exceed the amount of fees, if any, that you ; have paid directly to Microchip to use this software. ; ; MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE ; OF THESE TERMS.
;#define TBLWT_BUG ; Enable this to work around timing bug found in some PIC18Fxx20's ;#define INVERT_UART ; If you don't have an RS232 transceiver, you might want this option #define USE_MAX_INTOSC ; Sets OSCCON<IRCF2:IRCF0> for maximum INTOSC frequency (8MHz) #define USE_PLL ; Sets OSCTUNE.PLLEN bit at start up for frequency multiplication. ;#define PICDEM_LCD2 ; RB0 = 1 required to enable MAX3221 TX output on PICDEM LCD 2 demo board #define USE_SOFTBOOTWP ; enable software boot block write protection ;#define USE_SOFTCONFIGWP ; enable software config words write protection
; Autobaud will be used by default. To save code space or to force a specific baud rate to be used, ; you can optionally define a BAUDRG value instead. Most PIC18's support BRG16 mode and use the ; following equation: ; BAUDRG = Fosc / (4 * Baud Rate) - 1 ; ; Old PIC18's without BRG16 mode need this equation instead: ; BAUDRG = Fosc / (16 * Baud Rate) - 1 ; ; Examples: ;#define BAUDRG .51 ; 19.2Kbps from 4MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .103 ; 115.2Kbps from 48MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .85 ; 115.2Kbps from 40MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .68 ; 115.2Kbps from 32MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .16 ; 115.2Kbps from 8MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .11 ; 1Mbps from 48MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .9 ; 1Mbps from 40MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .4 ; 2Mbps from 40MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .3 ; 3Mbps from 48MHz (BRG16 = 1, BRGH = 1) ;#define BAUDRG .12 ; 19.2Kbps from 4MHz, 115.2Kbps from 24MHz (BRG16 = 0, BRGH = 1) ;#define BAUDRG .10 ; 115.2Kbps from 19.6608MHz (BRG16 = 0, BRGH = 1)
; Bootloader must start at the beginning of a FLASH Erase Block. If unspecified, ; bootloader will automatically be located at the end of program memory address space. #define BOOTLOADER_ADDRESS 0 ; bootloader at beginning, application start/ISR vectors require remapping ;#define BOOTLOADER_ADDRESS END_FLASH - (ERASE_FLASH_BLOCKSIZE * 20) ; useful for running under debugger (debug executive wants to reside at the end of memory space too) ;#define BOOTLOADER_ADDRESS (END_FLASH - ERASE_FLASH_BLOCKSIZE) ; use on J parts to locate inside flash config erase block
#ifdef BOOTLOADER_ADDRESS #if BOOTLOADER_ADDRESS == 0 ; For Bootloader located at program memory address 0, the application firmware must ; provide remapped reset and interrupt vectors outside of the Boot Block. The following ; #defines tell the bootloader firmware where application entry points are to be expected: #define AppVector 0x400 ; application start up code should be located here. #define AppHighIntVector 0x408 ; application high priority interrupt should be located here #define AppLowIntVector 0x418 ; application low priority interrupt should be located here #endif #endif
; Define UART pins and registers. ; Modify the following lines if you want to use a different UART module. ; ; Note: If your UART's RX pin happens to be multiplexed with analog ANx input ; functionality, you may need to edit the "preprocess.inc" DigitalInput ; macro. Code there needs to enable the digital input buffer (refer to ; ADC chapter of your device's datasheet). #define UARTNUM 2 #if UARTNUM == 1 #define UxSPBRG SPBRG #define UxSPBRGH SPBRGH #define UxRCSTA RCSTA #define UxTXSTA TXSTA #define UxRCREG RCREG #define UxTXREG TXREG #define UxPIR PIR1 #define UxRCIF RCIF #define UxTXIF TXIF #define UxBAUDCON BAUDCON
; #define RXPORT PORTC ; RX on RC7 is used by default for most PIC18's. ; #define RXPIN .7
; #define RXPORT PORTG ; RG2 is default RX2 pin for some high pin count PIC18's. ; #define RXPIN .2
; #define RXPORT PORTD ; RX2 pin PPS'ed to RD4/RP21 on PIC18F46J11 for example. ; #define RXPIN .4
; #define RXANSEL ANSELH ; On PICs where RX is multiplexed with ANx analog inputs, ; #define RXAN .3 ; the digital input buffer needs to be enabled via ANSELx SFRs
; devices that use PPS to remap UART2 pins will need these lines defined: ; #define PPS_UTX .5 ; PPS code for TX2/CK2 output function ; #define PPS_UTX_PIN RPOR23 ; UART TX assigned to RP23 pin ; #define PPS_URX_PIN .21 ; UART RX assigned to RP21 pin ; #define PPS_URX RPINR16 ; PPS register for RX2/CK2 input function #endif
; If you get linker errors complaining "can not fit the absolute section," you might want to ; increase BOOTLOADERSIZE below or set the BOOTLOADER_ADDRESS above to a smaller address number.
; Because we need to know the total size of the bootloader before the assembler has finished ; compiling the source code, we have to estimate the final bootloader size and provide it ; here as BOOTLOADERSIZE. This number is in bytes (twice the instruction word count). ; ; If you see the bootloader is reserving more FLASH memory than it really needs (you'll ; see a bunch of FFFF/NOP instructions at the end of the bootloader memory region), ; you can try reducing BOOTLOADERSIZE. #define BOOTLOADERSIZE .708
#define MAJOR_VERSION .1 ; Bootloader Firmware Version #define MINOR_VERSION .5
Скомпиллировал, прошил, подключаю к компу через usb-uart , а программа пишет: Bootloader not found. Что я делаю не так?
Когда-то тоже возился с этим загрузчиком. В итоге для отладки пришлось написать прогу-терминал под Windows. А точно USART2 правильно работает? Я бы сначала на тестовой прошивке попробовал бы связаться, а потом уже с загруэчиком разбираться...
Зарегистрирован: Чт мар 05, 2015 07:14:58 Сообщений: 131
Рейтинг сообщения:0
-=Vovka=- писал(а):
А точно USART2 правильно работает?
В смысле? Он может работать неправильно? Непонятен смысл написания прошивки для проверки UART2. Могу написать простенькую программку на си, которая будет возвращать то что приняла. Уверен на 99,999% что она будет работать.
Зарегистрирован: Чт мар 05, 2015 07:14:58 Сообщений: 131
Рейтинг сообщения:0
На других МК - не пробовал. Вход осуществляется установкой логического нуля на RX при старте МК. Делаю это с помощью утилиты входящей в комплект AN1310 (Нужно нажать соответствующую кнопку). Может посоветует кто-нибудь проверенный бутлоадер для вышеуказанного камня? В MPLAB Code Generator есть библиотека загрузчика, попробовал её использовать, но она не компиллируется, вылетает куча ошибок. Да и непонятно как вообще им пользоваться на стороне ПК?
Как-то странно звучит ваш ответ, т.к. вы уже тестом проверили работу с USART - значит понимаете что это за зверь, а вот в загрузчике "не обратили внимание" на BAUDRG и остальные настройки USART и не только...
Зарегистрирован: Чт мар 05, 2015 07:14:58 Сообщений: 131
Рейтинг сообщения:0
Я же попросил
Dmitry888 писал(а):
пожалуйста, объясните на что именно смотреть?
Если Вы не можете дать однозначный ответ, постараюсь угадать что-же Вы имели в виду. Возможно Вас смутило что все строки с указанием BAUDRG закомментированы?
Я вот как-то не могу вас понять: с одной стороны вы написали тестовую прошивку, в которой настраивали USART, указывая скорость и т.д., а в загрузчике не убрали комментарий с нужной строки! Так же не сделали настройку порта на USART2...
Сначала нужно сделать на фиксированной скорости! И на всякий случай, для отладки, я бы поставил кварц Ноги порта для USART2 правильно выставлены? Все "лишнее" отключено? Прерывания?
Зарегистрирован: Чт мар 05, 2015 07:14:58 Сообщений: 131
Рейтинг сообщения:0
Утром я проверил на тестовой прошивке , работает на фиксированной с внутренним кварцем. Попробовал в bootconfig.inc указать
Код:
#define BAUDRG .207
По моим подсчётам это 9600 при 8MHz внутреннего генератора - так не работает. Для внешнего кварца настроек в bootconfig.inc не предусмотрено, а в ассемблере я не силён.
Зарегистрирован: Чт мар 05, 2015 07:14:58 Сообщений: 131
Рейтинг сообщения:0
Ошибочка, при
Код:
#define USE_MAX_INTOSC
, по коду это: OSCCON<IRCF2:IRCF0> 111 - частота внутреннего генератора будет 16MHz. Переделал так:
Код:
#define BAUDRG .103 ; 38.4 16MHz
Один хрен не работает.
-=Vovka=- писал(а):
это для каких значений SYNC, BRGH и BRG16?
SYNC = 0 (Asynchronous mode) С остальными я не разобрался. По коду мне непонятно. Привожу тут исходники, может кто подскажет: bootloader.asm Спойлер
Код:
; Copyright (c) 2002-2011, Microchip Technology Inc. ; ; Microchip licenses this software to you solely for use with Microchip ; products. The software is owned by Microchip and its licensors, and ; is protected under applicable copyright laws. All rights reserved. ; ; SOFTWARE IS PROVIDED "AS IS." MICROCHIP EXPRESSLY DISCLAIMS ANY ; WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT ; NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ; FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ; MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR ; CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR ; EQUIPMENT, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY ; OR SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED ; TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, ; OR OTHER SIMILAR COSTS. ; ; To the fullest extent allowed by law, Microchip and its licensors ; liability shall not exceed the amount of fees, if any, that you ; have paid directly to Microchip to use this software. ; ; MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE ; OF THESE TERMS. ; ; Author Date Comment ; ************************************************************************ ; E. Schlunder 07/20/2010 Software Boot Block Write Protect code ; improved. 96KB memory size devices should ; work now. ; E. Schlunder 02/26/2010 Changed order of start up code so that PLLEN ; is enabled before we wait for RXD IDLE state. ; This improves connection time/reliablity on ; J devices. ; E. Schlunder 08/28/2009 Software Boot Block Write Protect option. ; E. Schlunder 07/09/2009 Brought back support for bootloader at ; address 0 for hardware boot block write ; protection on certain devices. ; E. Schlunder 05/07/2009 Replaced the simple checksum with a ; 16-bit CCIT CRC checksum. ; Added ReadFlashCrc command for quick verify. ; E. Schlunder 05/02/2009 Improved autobaud code to handle 1Mbps ; and BRG16/BRGH. ; E. Schlunder 05/01/2009 Added support for DEVICES.INC generated ; from Device Database tool. ; E. Schlunder 04/29/2009 Added support for locating the bootloader ; at the end of program memory instead of ; the beginning. This will eventually let us ; use normal application firmware code without ; linker script modifications. ; E. Schlunder 04/26/2009 Optimized Config Write routine to avoid ; re-writing values matching existing config ; data. ; E. Schlunder 04/24/2009 Optimized EEPROM Write routine a little bit. ; Optimized FLASH Read routine to stream data ; directly from FLASH instead of using RAM ; buffer. ; Added option for faster STX acknowledgements. ; E. Schlunder 04/17/2009 Added code to enter bootloader mode if ; a serial break condition is detected on ; RXD as we come out of reset. This will ; make it possible to re-enter the bootloader ; even if the application firmware is missing ; code to re-enter bootloader mode. ; This also simplies the bootloader, as ; we do not need a boot flag any more. ; E. Schlunder 04/15/2009 Removed EOF command 8, new PC software ; does 64 byte block aligned writes at all ; times on J device, so there is no need for ; this command going forward. ; E. Schlunder 04/14/2009 Added a BootloadMode vector back at the ; beginning of program memory so that user ; applications can jump back into the boot ; loader without having to erase the boot flag. ; E. Schlunder 04/08/2009 Now initializes FSR2 to 0 so that the code ; can operate under Extended Instruction Set ; mode if necessary. ; E. Schlunder 04/01/2009 Fixed bug in J_FLASH erase address increment. ; Added support for enabling PLL. ; Added support for inverted UART signaling. ; Added support for fixed (non-autobaud) ; operation, helps with debugging code under ICD. ; E. Schlunder 03/25/2009 No longer attempts to use EEADRH on PIC18F4321. ; ; UART Bootloader for PIC18F by Ross Fosler ; 09/01/2006 Modified to support PIC18xxJxx & 160k PIC18Fxxx Flash Devices ; 03/01/2002 ... First full implementation ; 03/07/2002 Changed entry method to use last byte of EEDATA. ; Also removed all possible infinite loops w/ clrwdt. ; 03/07/2002 Added code for direct boot entry. I.E. boot vector. ; 03/09/2002 Changed the general packet format, removed the LEN field. ; 03/09/2002 Modified the erase command to do multiple row erase. ; 03/12/2002 Fixed write problem to CONFIG area. Write was offset by a byte. ; 03/15/2002 Added work around for 18F8720 tblwt*+ problem. ; 03/20/2002 Modified receive & parse engine to vector to autobaud on a checksum ; error since a chechsum error could likely be a communications problem. ; 03/22/2002 Removed clrwdt from the startup. This instruction affects the TO and ; PD flags. Removing this instruction should have no affect on code ; operation since the wdt is cleared on a reset and boot entry is always ; on a reset. ; 03/22/2002 Modified the protocol to incorporate the autobaud as part of the ; first received <STX>. Doing this improves robustness by allowing ; re-sync under any condition. Previously it was possible to enter a ; state where only a hard reset would allow re-syncing. ; 03/27/2002 Removed the boot vector and related code. This could lead to customer ; issues. There is a very minute probability that errent code execution ; could jump into the boot area and cause artificial boot entry. ; ***************************************************************************** #include <p18cxxx.inc> #include "devices.inc" #include "bootconfig.inc" #include "preprocess.inc" ; *****************************************************************************
#ifndef AppVector ; The application startup GOTO instruction will be written just before the Boot Block, ; courtesy of the host PC bootloader application. #define AppVector (BootloaderStart-.4) #endif ; *****************************************************************************
; ***************************************************************************** #if BOOTLOADER_ADDRESS != 0 ORG 0 ; The following GOTO is not strictly necessary, but may startup faster ; for large microcontrollers running at extremely slow clock speeds. ;goto BootloaderBreakCheck
ORG BOOTLOADER_ADDRESS BootloaderStart: bra BootloadMode
; ***************************************************************************** ; Determine if the application is supposed to be started or if we should ; go into bootloader mode. ; ; If RX pin is in BREAK state when we come out of MCLR reset, immediately ; enter bootloader mode, even if there exists some application firmware in ; program memory. BootloaderBreakCheck: DigitalInput ; set RX pin as digital input on certain parts #ifdef INVERT_UART btfss RXPORT, RXPIN GotoAppVector: goto AppVector ; no BREAK state, attempt to start application #else btfsc RXPORT, RXPIN GotoAppVector: goto AppVector ; no BREAK state, attempt to start application #endif
BootloadMode: DigitalInput ; set RX pin as digital input on certain parts #else ; BOOTLOADER_ADDRESS == 0 **************************************************************** ORG 0 BootloaderStart: DigitalInput ; set RX pin as digital input on certain parts movlw low(AppVector) ; load address of application reset vector bra BootloaderBreakCheck
BootloaderBreakCheck: #ifdef INVERT_UART btfsc RXPORT, RXPIN bra BootloadMode #else btfss RXPORT, RXPIN bra BootloadMode #endif CheckAppVector: ; Read instruction at the application reset vector location. ; If we read 0xFFFF, assume that the application firmware has ; not been programmed yet, so don't try going into application mode. movwf TBLPTRL movlw high(AppVector) movwf TBLPTRH bra CheckAppVector2
CheckAppVector2: movlw upper(AppVector) movwf TBLPTRU tblrd *+ ; read instruction from program memory incfsz TABLAT, W ; if the lower byte != 0xFF, GotoAppVector: goto AppVector ; run application.
tblrd *+ ; read instruction from program memory incfsz TABLAT, W ; if the lower byte == 0xFF but upper byte != 0xFF, bra GotoAppVector ; run application. ; otherwise, assume application firmware is not present because we read a NOP (0xFFFF). ; fall through to bootloader mode... BootloadMode: #endif ; end BOOTLOADER_ADDRESS == 0 ****************************************** lfsr FSR2, 0 ; for compatibility with Extended Instructions mode.
#ifdef USE_MAX_INTOSC movlw b'01110000' ; set INTOSC to maximum speed (usually 8MHz) iorwf OSCCON, f #endif
#ifdef USE_PLL #ifdef PLLEN #ifdef OSCTUNE bsf OSCTUNE, PLLEN ; enable PLL for faster internal clock #else ; 18F8680, 18F8585, 18F6680, and 18F6585 doesn't have OSCTUNE register. ; Instead, PLLEN bit is in OSCCON. bsf OSCCON, PLLEN ; enable PLL for faster internal clock #endif #else #ifdef SPLLEN bsf OSCTUNE, SPLLEN ; PIC18F14K50 has SPLLEN at bit 6 #endif #endif #endif
#ifdef INVERT_UART btfsc RXPORT, RXPIN ; wait for RX pin to go IDLE bra $-2 #else btfss RXPORT, RXPIN ; wait for RX pin to go IDLE bra $-2 #endif
#ifdef BRG16 bsf UxBAUDCON, BRG16 movlw b'00000010' ; 1:8 prescaler - no division required later (but no rounding possible) #else movlw b'00000011' ; 1:16 prescaler - thus we only have to divide by 2 later on. #endif movwf T0CON
#ifdef PICDEM_LCD2 bsf LATB, LATB0 ; PICDEM LCD 2 demoboard requires RB0 high to enable MAX3221 TX output to PC. bcf TRISB, TRISB0 #endif ; *****************************************************************************
; ***************************************************************************** #ifdef USE_AUTOBAUD DoAutoBaud: ; ___ __________ ________ ; \__/ \__________/ ; | | ; |-------- 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, BRG16 = 0 ; SPBRG = (p / 8) - 1 BRGH = 1, BRG16 = 1
bcf UxRCSTA, CREN ; Stop receiving movf UxRCREG, W ; Empty the buffer movf UxRCREG, W
RetryAutoBaud: clrf TMR0H ; reset timer count value clrf TMR0L bcf INTCON, TMR0IF rcall WaitForRise ; wait for a start bit to pass by bsf T0CON, TMR0ON ; start timer counting for entire D7..D0 data bit period. rcall WaitForRise ; wait for stop bit bcf T0CON, TMR0ON ; stop the timer from counting further.
btfsc INTCON, TMR0IF ; if TMR0 overflowed, we did not get a good baud capture bra RetryAutoBaud ; try again
#ifdef BRG16 ; save new baud rate generator value movff TMR0L, UxSPBRG ; warning: must read TMR0L before TMR0H holds real data movff TMR0H, UxSPBRGH #else movff TMR0L, UxSPBRG ; warning: must read TMR0L before TMR0H holds real data ; TMR0H:TMR0L holds (p / 16). rrcf TMR0H, w ; divide by 2 rrcf UxSPBRG, F btfss STATUS, C ; rounding decf UxSPBRG, F #endif
bsf UxRCSTA, CREN ; start receiving
WaitForHostCommand: rcall ReadHostByte ; get start of transmission <STX> xorlw STX bnz DoAutoBaud ; got something unexpected, perform autobaud #else ; not using autobaud movlw low(BAUDRG) ; set fixed baud rate generator value movwf UxSPBRG #ifdef UxSPBRGH #if high(BAUDRG) != 0 movlw high(BAUDRG) movwf UxSPBRGH #endif #endif bsf UxRCSTA, CREN ; start receiving DoAutoBaud: WaitForHostCommand: rcall ReadHostByte ; get start of transmission <STX> xorlw STX bnz WaitForHostCommand ; got something unexpected, keep waiting for <STX> #endif ; end #ifdef USE_AUTOBAUD
; ***************************************************************************** ; Read and parse packet data. StartOfLine: movlw STX ; send back start of response rcall SendHostByte
lfsr FSR0, COMMAND-1 ; Point to the buffer
ReceiveDataLoop: rcall ReadHostByte ; Get the data xorlw STX ; Check for an unexpected STX bz StartOfLine ; unexpected STX: abort packet and start over.
NoSTX: movf RXDATA, W xorlw ETX ; Check for a ETX bz VerifyPacketCRC ; Yes, verify CRC
NoETX: movf RXDATA, W xorlw DLE ; Check for a DLE bnz AppendDataBuffer
rcall ReadHostByte ; DLE received, get the next byte and store it
AppendDataBuffer: movff RXDATA, PREINC0 ; store the data to the buffer bra ReceiveDataLoop
VerifyPacketCRC: lfsr FSR1, COMMAND clrf CRCL clrf CRCH movff POSTDEC0, PRODH ; Save host packet's CRCH to PRODH for later comparison ; CRCL is now available as INDF0 VerifyPacketCrcLoop: movf POSTINC1, w rcall AddCrc ; add new data to the CRC
movf FSR1H, w cpfseq FSR0H bra VerifyPacketCrcLoop ; we aren't at the end of the received data yet, loop movf FSR1L, w cpfseq FSR0L bra VerifyPacketCrcLoop ; we aren't at the end of the received data yet, loop
movf CRCH, w cpfseq PRODH bra DoAutoBaud ; invalid CRC, reset baud rate generator to re-sync with host movf CRCL, w cpfseq INDF0 bra DoAutoBaud ; invalid CRC, reset baud rate generator to re-sync with host
; *********************************************** ; Pre-setup, common to all commands. clrf CRCL clrf CRCH
movf ADDRESS_L, W ; Set all possible pointers movwf TBLPTRL #ifdef EEADR movwf EEADR #endif movf ADDRESS_H, W movwf TBLPTRH #ifdef EEADRH movwf EEADRH #endif movff ADDRESS_U, TBLPTRU lfsr FSR0, PACKET_DATA ; ***********************************************
; *********************************************** ; Test the command field and sub-command. CheckCommand: movlw .10 cpfslt COMMAND bra DoAutoBaud ; invalid command - reset baud generator to re-sync with host
; This jump table must exist entirely within one 256 byte block of program memory. #if ($ & 0xFF) > (0xFF - .24) ; Too close to the end of a 256 byte boundary, push address forward to get code ; into the next 256 byte block. messg "Wasting some code space to ensure jump table is aligned." ORG $+(0x100 - ($ & 0xFF)) #endif JUMPTABLE_BEGIN: movf PCL, w ; 0 do a read of PCL to set PCLATU:PCLATH to current program counter. rlncf COMMAND, W ; 2 multiply COMMAND by 2 (each BRA instruction takes 2 bytes on PIC18) addwf PCL, F ; 4 Jump in command jump table based on COMMAND from host bra BootloaderInfo ; 6 00h bra ReadFlash ; 8 01h bra VerifyFlash ; 10 02h bra EraseFlash ; 12 03h bra WriteFlash ; 14 04h bra ReadEeprom ; 16 05h bra WriteEeprom ; 18 06h bra WriteConfig ; 20 07h bra GotoAppVector ; 22 08h reset ; 24 09h
#if (JUMPTABLE_BEGIN & 0xFF) > ($ & 0xFF) error "Jump table is not aligned to fit within a single 256 byte address range." #endif ; *****************************************************************************
#ifdef INVERT_UART WaitForRise: clrwdt
WaitForRiseLoop: btfsc INTCON, TMR0IF ; if TMR0 overflowed, we did not get a good baud capture return ; abort
btfss RXPORT, RXPIN ; Wait for a falling edge bra WaitForRiseLoop
WtSR: btfsc RXPORT, RXPIN ; Wait for starting edge bra WtSR return #else ; not inverted UART pins WaitForRise: clrwdt
WaitForRiseLoop btfsc INTCON, TMR0IF ; if TMR0 overflowed, we did not get a good baud capture return ; abort
btfsc RXPORT, RXPIN ; Wait for a falling edge bra WaitForRiseLoop
WtSR: btfss RXPORT, RXPIN ; Wait for rising edge bra WtSR return #endif ; end #ifdef INVERT_UART ; *****************************************************************************
; Provides information about the Bootloader to the host PC software. BootInfoBlock: db low(BOOTBLOCKSIZE), high(BOOTBLOCKSIZE) db MAJOR_VERSION, MINOR_VERSION db 0xFF, 0x84 ; command mask : family id db low(BootloaderStart), high(BootloaderStart) db upper(BootloaderStart), 0 BootInfoBlockEnd:
movlw (BootInfoBlockEnd - BootInfoBlock) movwf DATA_COUNTL clrf DATA_COUNTH ;; fall through to ReadFlash code -- send Bootloader Information Block from FLASH.
; In: <STX>[<0x01><ADDRL><ADDRH><ADDRU><0x00><BYTESL><BYTESH>]<CRCL><CRCH><ETX> ; Out: <STX>[<DATA>...]<CRCL><CRCH><ETX> ReadFlash: tblrd *+ ; read from FLASH memory into TABLAT movf TABLAT, w rcall SendEscapeByte rcall AddCrc
decf DATA_COUNTL, f ; decrement counter movlw 0 subwfb DATA_COUNTH, f
movf DATA_COUNTL, w ; DATA_COUNTH:DATA_COUNTH == 0? iorwf DATA_COUNTH, w bnz ReadFlash ; no, loop bra SendChecksum ; yes, send end of packet
movf TBLPTRL, w ; have we crossed into the next block? #if ERASE_FLASH_BLOCKSIZE > .255 bnz VerifyFlash movf TBLPTRH, w andlw high(ERASE_FLASH_BLOCKSIZE-1) #else andlw (ERASE_FLASH_BLOCKSIZE-1) #endif bnz VerifyFlash
movf CRCL, w call SendEscapeByte movf CRCH, w call SendEscapeByte
decf DATA_COUNTL, f ; decrement counter movlw 0 subwfb DATA_COUNTH, f
movf DATA_COUNTL, w ; DATA_COUNTH:DATA_COUNTH == 0? iorwf DATA_COUNTH, w bnz VerifyFlash ; no, loop bra SendETX ; yes, send end of packet
#ifdef SOFTWP reset ; this code -should- never be executed, but reset ; just in case of errant execution or buggy reset ; firmware, these reset instructions may protect reset ; against accidental erases. #endif
; In: <STX>[<0x03><ADDRL><ADDRH><ADDRU><0x00><PAGESL>]<CRCL><CRCH><ETX> ; Out: <STX>[<0x03>]<CRCL><CRCH><ETX> EraseFlash: #ifdef SOFTWP #define ERASE_ADDRESS_MASK (~(ERASE_FLASH_BLOCKSIZE-1)) #if upper(ERASE_ADDRESS_MASK) != 0xFF movlw upper(ERASE_ADDRESS_MASK) ; force starting address to land on a FLASH Erase Block boundary andwf TBLPTRU, f #endif #if high(ERASE_ADDRESS_MASK) != 0xFF movlw high(ERASE_ADDRESS_MASK) ; force starting address to land on a FLASH Erase Block boundary andwf TBLPTRH, f #endif #if low(ERASE_ADDRESS_MASK) != 0xFF movlw low(ERASE_ADDRESS_MASK) ; force starting address to land on a FLASH Erase Block boundary andwf TBLPTRL, f #endif
; Verify Erase Address does not attempt to erase beyond the end of FLASH memory movlw low(END_FLASH) subwf TBLPTRL, w movlw high(END_FLASH) subwfb TBLPTRH, w movlw upper(END_FLASH) subwfb TBLPTRU, w bn EraseEndFlashAddressOkay
clrf EECON1 ; inhibit writes for this block bra NextEraseBlock ; move on to next erase block #endif ; end #ifdef USE_SOFTBOOTWP
EraseEndFlashAddressOkay: #ifdef USE_SOFTCONFIGWP #ifdef CONFIG_AS_FLASH movlw low(END_FLASH - ERASE_FLASH_BLOCKSIZE) subwf TBLPTRL, w movlw high(END_FLASH - ERASE_FLASH_BLOCKSIZE) subwfb TBLPTRH, w movlw upper(END_FLASH - ERASE_FLASH_BLOCKSIZE) subwfb TBLPTRU, w bn EraseConfigAddressOkay
clrf EECON1 ; inhibit writes for this block bra NextEraseBlock ; move on to next erase block
EraseConfigAddressOkay: #endif ; end CONFIG_AS_FLASH #endif ; end USE_SOFTCONFIGWP
#ifdef USE_SOFTBOOTWP movlw low(BOOTLOADER_ADDRESS) subwf TBLPTRL, w movlw high(BOOTLOADER_ADDRESS) subwfb TBLPTRH, w movlw upper(BOOTLOADER_ADDRESS) subwfb TBLPTRU, w bn EraseAddressOkay
movlw low(BOOTLOADER_ADDRESS + BOOTBLOCKSIZE) subwf TBLPTRL, w movlw high(BOOTLOADER_ADDRESS + BOOTBLOCKSIZE) subwfb TBLPTRH, w movlw upper(BOOTLOADER_ADDRESS + BOOTBLOCKSIZE) subwfb TBLPTRU, w bnn EraseAddressOkay
clrf EECON1 ; inhibit writes for this block bra NextEraseBlock ; move on to next erase block
reset ; this code -should- never be executed, but reset ; just in case of errant execution or buggy reset ; firmware, these reset instruction may protect reset ; against accidental writes. #endif
NextEraseBlock: ; Decrement address by erase block size #if ERASE_FLASH_BLOCKSIZE >= .256 movlw high(ERASE_FLASH_BLOCKSIZE) subwf TBLPTRH, F clrf WREG subwfb TBLPTRU, F #else movlw ERASE_FLASH_BLOCKSIZE subwf TBLPTRL, F clrf WREG subwfb TBLPTRH, F subwfb TBLPTRU, F #endif
decfsz DATA_COUNTL, F bra EraseFlash bra SendAcknowledge ; All done, send acknowledgement packet
#ifdef SOFTWP reset ; this code -should- never be executed, but reset ; just in case of errant execution or buggy reset ; firmware, these reset instructions may protect reset ; against accidental writes. #endif
; In: <STX>[<0x04><ADDRL><ADDRH><ADDRU><0x00><BLOCKSL><DATA>...]<CRCL><CRCH><ETX> ; Out: <STX>[<0x04>]<CRCL><CRCH><ETX> WriteFlash: #ifdef SOFTWP #define WRITE_ADDRESS_MASK (~(WRITE_FLASH_BLOCKSIZE-1)) #if upper(WRITE_ADDRESS_MASK) != 0xFF movlw upper(WRITE_ADDRESS_MASK) ; force starting address to land on a FLASH Write Block boundary andwf TBLPTRU, f #endif #if high(WRITE_ADDRESS_MASK) != 0xFF movlw high(WRITE_ADDRESS_MASK) ; force starting address to land on a FLASH Write Block boundary andwf TBLPTRH, f #endif #if low(WRITE_ADDRESS_MASK) != 0xFF movlw low(WRITE_ADDRESS_MASK) ; force starting address to land on a FLASH Write Block boundary andwf TBLPTRL, f #endif
; Verify Write Address does not attempt to write beyond the end of FLASH memory movlw low(END_FLASH) subwf TBLPTRL, w movlw high(END_FLASH) subwfb TBLPTRH, w movlw upper(END_FLASH) subwfb TBLPTRU, w bn WriteEndFlashAddressOkay
clrf EECON1 ; inhibit writes for this block bra LoadHoldingRegisters; fake the write so we can move on to real writes #endif ; end #ifdef SOFTWP
WriteEndFlashAddressOkay: #ifdef USE_SOFTCONFIGWP #ifdef CONFIG_AS_FLASH movlw low(END_FLASH - ERASE_FLASH_BLOCKSIZE) subwf TBLPTRL, w movlw high(END_FLASH - ERASE_FLASH_BLOCKSIZE) subwfb TBLPTRH, w movlw upper(END_FLASH - ERASE_FLASH_BLOCKSIZE) subwfb TBLPTRU, w bn WriteConfigAddressOkay
clrf EECON1 ; inhibit writes for this block bra LoadHoldingRegisters; fake the write so we can move on to real writes
WriteConfigAddressOkay: #endif ; end CONFIG_AS_FLASH #endif ; end USE_SOFTCONFIGWP
#ifdef USE_SOFTBOOTWP movlw low(BOOTLOADER_ADDRESS) subwf TBLPTRL, w movlw high(BOOTLOADER_ADDRESS) subwfb TBLPTRH, w movlw upper(BOOTLOADER_ADDRESS) subwfb TBLPTRU, w bn WriteAddressOkay
movlw low(BOOTLOADER_ADDRESS + BOOTBLOCKSIZE) subwf TBLPTRL, w movlw high(BOOTLOADER_ADDRESS + BOOTBLOCKSIZE) subwfb TBLPTRH, w movlw upper(BOOTLOADER_ADDRESS + BOOTBLOCKSIZE) subwfb TBLPTRU, w bnn WriteAddressOkay
clrf EECON1 ; inhibit writes for this block bra LoadHoldingRegisters ; fake the write so we can move on to real writes
reset ; this code -should- never be executed, but reset ; just in case of errant execution or buggy reset ; firmware, these reset instruction may protect reset ; against accidental writes. #endif
LoadHoldingRegisters: movff POSTINC0, TABLAT ; Load the holding registers pmwtpi ; Same as tblwt *+
movf TBLPTRL, w ; have we crossed into the next write block? andlw (WRITE_FLASH_BLOCKSIZE-1) bnz LoadHoldingRegisters; Not finished writing holding registers, repeat
tblrd *- ; Point back into the block to write data rcall StartWrite ; initiate a page write tblrd *+ ; Restore pointer for loading holding registers with next block
decfsz DATA_COUNTL, F bra WriteFlash ; Not finished writing all blocks, repeat bra SendAcknowledge ; all done, send ACK packet
; In: <STX>[<0x05><ADDRL><ADDRH><0x00><0x00><BYTESL><BYTESH>]<CRCL><CRCH><ETX> ; Out: <STX>[<DATA>...]<CRCL><CRCH><ETX> #ifdef EEADR ; some devices do not have EEPROM, so no need for this code ReadEeprom: clrf EECON1 ReadEepromLoop: bsf EECON1, RD ; Read the data movf EEDATA, w #ifdef EEADRH infsnz EEADR, F ; Adjust EEDATA pointer incf EEADRH, F #else incf EEADR, F ; Adjust EEDATA pointer #endif rcall SendEscapeByte rcall AddCrc
#ifdef EEADRH decf DATA_COUNTL, f ; decrement counter movlw 0 subwfb DATA_COUNTH, f
movf DATA_COUNTL, w ; DATA_COUNTH:DATA_COUNTH == 0? iorwf DATA_COUNTH, w bnz ReadEepromLoop ; no, loop bra SendChecksum ; yes, send end of packet #else decfsz DATA_COUNTL, F bra ReadEepromLoop ; Not finished then repeat bra SendChecksum #endif #endif ; end #ifdef EEADR
; In: <STX>[<0x06><ADDRL><ADDRH><0x00><0x00><BYTESL><BYTESH><DATA>...]<CRCL><CRCH><ETX> ; Out: <STX>[<0x06>]<CRCL><CRCH><ETX> #ifdef EEADR ; some devices do not have EEPROM, so no need for this code WriteEeprom: movlw b'00000100' ; Setup for EEPROM data writes movwf EECON1
btfsc EECON1, WR ; wait for write to complete before moving to next address bra $-2
#ifdef EEADRH infsnz EEADR, F ; Adjust EEDATA pointer incf EEADRH, F #else incf EEADR, f ; Adjust EEDATA pointer #endif
#ifdef EEADRH decf DATA_COUNTL, f ; decrement counter movlw 0 subwfb DATA_COUNTH, f
movf DATA_COUNTL, w ; DATA_COUNTH:DATA_COUNTH == 0? iorwf DATA_COUNTH, w bnz WriteEepromLoop ; no, loop bra SendAcknowledge ; yes, send end of packet #else decfsz DATA_COUNTL, f bra WriteEepromLoop bra SendAcknowledge #endif #endif ; end #ifdef EEADR
; In: <STX>[<0x07><ADDRL><ADDRH><ADDRU><0x00><BYTES><DATA>...]<CRCL><CRCH><ETX> ; Out: <STX>[<0x07>]<CRCL><CRCH><ETX> #ifndef CONFIG_AS_FLASH ; J flash devices store config words in FLASH, so no need for this code #ifndef USE_SOFTCONFIGWP WriteConfig: movlw b'11000100' movwf EECON1 tblrd * ; read existing value from config memory
WriteConfigLoop: movf POSTINC0, w cpfseq TABLAT ; is the proposed value already the same as existing value? rcall TableWriteWREG ; write config memory only if necessary (save time and endurance) tblrd +* ; increment table pointer to next address and read existing value decfsz DATA_COUNTL, F bra WriteConfigLoop ; If more data available in packet, keep looping
bra SendAcknowledge ; Send acknowledge #endif ; end #ifndef USE_SOFTCONFIGWP #endif ; end #ifndef CONFIG_AS_FLASH
;************************************************
; *********************************************** ; Send an acknowledgement packet back ; ; <STX><COMMAND><CRCL><CRCH><ETX>
; Some devices only have config words as FLASH memory. Some devices don't have EEPROM. ; For these devices, we can save code by jumping directly to sending back an ; acknowledgement packet if the PC application erroneously requests them. #ifdef CONFIG_AS_FLASH WriteConfig: #else #ifdef USE_SOFTCONFIGWP WriteConfig: #endif #endif ; end #ifdef CONFIG_AS_FLASH
#ifndef EEADR ReadEeprom: WriteEeprom: #endif
SendAcknowledge: clrf EECON1 ; inhibit write cycles to FLASH memory
movf COMMAND, w rcall SendEscapeByte ; Send only the command byte (acknowledge packet) rcall AddCrc
bra WaitForHostCommand ; *****************************************************************************
; ***************************************************************************** ; Write a byte to the serial port while escaping control characters with a DLE ; first. SendEscapeByte: movwf TXDATA ; Save the data
xorlw STX ; Check for a STX bz WrDLE ; No, continue WrNext
movf TXDATA, W xorlw ETX ; Check for a ETX bz WrDLE ; No, continue WrNext
movf TXDATA, W xorlw DLE ; Check for a DLE bnz WrNext ; No, continue WrNext
WrDLE: movlw DLE ; Yes, send DLE first rcall SendHostByte
WrNext: movf TXDATA, W ; Then send STX
SendHostByte: clrwdt btfss UxPIR, UxTXIF ; Write only if TXREG is ready bra $-2
reset ; this code -should- never be executed, but reset ; just in case of errant execution or buggy reset ; firmware, these instructions may protect clrf EECON1 ; against accidental erase/write operations.
; ***************************************************************************** ; Unlock and start the write or erase sequence. TableWriteWREG: movwf TABLAT tblwt *
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения