Proton BASIC Compiler - A Universal PIC18 Bootloader for PDS


  • Pic® Basic


  • A Universal PIC18 Bootloader for PDS

    The "AGV Bootloader V5.0" allows loading firmware via serial port (UART1 or UART2) without the need for dedicated host software using the "Proton Development Suite®". Modern microcontrollers have an interesting ability to write to their own memory and this feature opens up an entirely different programming method. A special program running on the microcontroller could communicate with an external device and receive data containing the desired program that it could then write to itself.

    History:
    After a bad experience with the fuses with an external bootloader, I decided to try to learn how these systems work.
    It has been a long way for me to understand how to write a PIC® and the different protocols used. The documentations in the web are not always clear or precise, sometimes erroneous. But I was puzzled because the protocol of specialized programs that send the hex file always missing. I could not waste much time for decoding firmwares in "C" language.

    The challenge:
    To get rid of the specialized programs running in a computer, I decided that all the decoding software of the HEX file would be done in the PIC®, using only the PDS® compiler and the PIC® datasheet.

    What to choose?
    Reading a lot of experience of others, I realized that the best and reliable solution would be to create an unique and customized firmware FOR EACH USER PROJECT.
    In this way you could get several firmwares for a given PIC. What is the problem?

    General Features: (For High Side Memory)
    - The bootloader has been written with the Proton Basic Compiler Version 3.5.8.6. and all code is included in one BASIC file only.
    - It does not require a special download management PC application.
    - The Host computer program would be a simple RS232 communicator software.
    - It requires a handshaking software XON/XOFF.
    - That is the most automatic possible. The user does not waste time to write the code.
    - Customized firmware for each user project.
    - Self-protects so that large user applications do not over-write the bootloader.
    - The bootloader code does not use the interrupt that avoid some issues.
    - Successful downloads start user application automatically.
    - Only uses three wires for communication: TX, RX, ground and the pin Reset for starting.
    - All resources are released after download and available to the user application.
    - Highly adaptable/maintainable using the PDS® compiler.
    - Can be compiled for many combinations of crystal speeds and PIC® family members. (PIC18® ROM >= 128KB)
    - Many controls have been introduced in the code making a very secure bootloader.
    - Several additionals routines are available to debug the downloading file.
    - Several additionals OPTIONS are available for the PDS user.

    Specific Features:
    - To Write to 128KB ROM (- bootloader size). (or more) Version 2.0
    - To Write discontinued or plain user code.
    - To Write to Program FLASH and Data EEPROM.
    - Download user code by using the UART1 or UART2, at 115200, 57600, 38400 Bauds adjusted automatically to maximun speed according to the FOSC used.
    - Wide range of usable FOSC: 64, 48, 40, 32, 25, 24, 20, 16, 14 (14.32MHz), 12, 10.
    - FOSC = 80 Mhz for the PIC18FxxK20 series. Version 2.0
    - The firmware uses a doble UART buffer to increase speed and reliability.
    - Self write the boot "Goto PIC#Loader#Boot" in position 0 of ROM.
    - Check the "Goto proton#main#start" in position 4 of ROM.
    - Can be compiled with all options of the Watch-dog Timer.
    - To control the PIC® device ID before to write.
    - To Write the Config Fuses is not supported for security.
    - Enable/Disable the Notice Strings when the compilation is successfull. (Save 68 Bytes) version 2.0

    Firmware Options:
    - To write the ID Locations (8 bytes) (_EnableWriteIDLOCS_)
    - To print the PIC® device ID and revision. (_EnablePrintDeviceID_)
    - To erase the eeprom memory before to write. The user can define the range of erasing the EEPROM. (_EnableEraseEeprom_)
    - To test the erased user ROM. (_CheckUserROMerased_)

    Download debugging:
    These options are available to download the hex file and they are occasionally used for the downloading control.
    - To debug the ID LOCS. (_DebugIDLOCS_)
    - To debug the Config Fuse. (only reading the values) (_DebugCONFIG_)
    - To debug the RX UART LINE. (reading all the bytes directly from the UART) (_DebugRX_UART_LINE_)
    - To debug the eeprom write. (_DebugEEP_)
    - To debug the ROM write. (_DebugWRITEROM_)
    - To print an information to the terminal every time the OPCODE is written. (_DebugPrintOPCODE_)
    - To print the RCON Status and oher important informations at reset or power-up. (_debugRESET_)

    Not good always use Debug Routines in the final firmware. These routines occupy many bytes, it is not as efficient and slows the customer download file. However you could use (_debugRESET_).

    Compiled Firmware:
    The firmware is always positioned dinamically at the top of the ROM in every compilation. Its size and position (PIC#Loader#Boot = label) is automatically calculated according of the choice of the number of options and/or debugs. The firmware does not need an external program to write or/and compile the boot. This Bootloader does not need any modification of the Asm file executed manually or by the MPLAB®.
    The vector "Goto PIC#Loader#Boot" is written by the firmware at the first Reset of the PIC® (use the OPCODE debug to see it). Then it is necessary to make only a Reset after loading the Bootloader firmware by a programmer.

    After compile the bootloader.bas file or the user.bas file, the ASM files must be like this.

    Bootloader file after compiling:
    Code:
    proton#code#start
        Org 0
        Nop
        Nop
        GoTo proton#main#start
        Org 8
    ...
    proton#main#start    
    ...
    PIC#Loader#Boot
    ...
    Bootloader code in the PIC® ROM after a first reset:
    Code:
    proton#code#start
        Org 0
        Goto PIC#Loader#Boot    ' Address 0 of ROM
        GoTo proton#main#start    ' Address 4 of ROM
        Org 8
    ...
    proton#main#start    
    ...
    PIC#Loader#Boot
    ...
    The user file with "Declare Watchdog = On":
    Code:
    proton#code#start
        Org 0
        clrwdt
        clrwdt
        GoTo proton#main#start
        Org 8
    ...
    proton#main#start    
    ...
    After compiling the bootloader code the user can check the Bootloader.lst file to see how the firmware is located.

    WARNING .def & .PPI files:
    I recommend to verify the .def and .PPI file, reading theses files with the NotePad and compare with the datasheet before to built a new firmware for a new PIC®. Sure you will find some differences. As I have bad luck, in some PIC®'s I had tested some .def and .PPI files that are erroneous about the Write block, the number of Banks or other informations.
    I enclose all copies of the new modified files. Before doing anything make a copy of all .def & .PPI files of the PDS® compiler.

    The Watchdog:
    All PIC®'s have not the same WDT configuration in the fuses list.
    Some PIC®'s have:
    WDTEN = On ' "WDT always enabled"
    WDTEN = Off ' "WDT disabled (control is placed on the SWDTEN bit)" (It is not really disabled!!!!)

    Others PIC®'s have:
    WDTEN = ON ' "WDT Always Enabled"
    WDTEN = SWON ' "WDT is controlled by SWDTEN bit of the WDTCON register"
    WDTEN = NOSLP ' "WDT is disabled in sleep, otherwise enabled. SWDTEN bit has no effect"
    WDTEN = OFF ' "Always Disabled" (Really disabled!)
    To choose the correct option please read the datasheet.

    How to configurate the firmware?
    Eleven steps are needed to configure the firmware for a particular project. (X) CONFIG BY USER:
    The different steps (like a label: STEP00 to STEPT11) could be found quickly in the "Code Explorer" window in the left part of the IDE.

    STEP01: Declare the PIC® device.
    Device = 18F25K22

    STEP02: Declare the FOSC.
    FOSC availabled: 64, 48, 40, 32, 25, 24, 20, 16, 14 (14.32MHz), 12, 10
    The FOSC = 64, 40, 20, 16, 10 Mhz have been tested.
    Declare Xtal = 64

    STEP03: Declare the UART1 SFR's and its pins.
    $define UART_USED_FOR_BOOTLOADER UART1
    $define UART_PORT PORTC
    $define UART_ANSEL ANSELC
    $define UART_ANSEL_TXbit ANSELCbits_ANSC6
    $define UART_ANSEL_RXbit ANSELCbits_ANSC7
    $define UART_TX_TRISBIT TRISCbits_TRISC6
    $define UART_RX_TRISBIT TRISCbits_TRISC7
    $define _TXIF_ PIR1Bits_TXIF
    $define _TXIE_ PIE1Bits_TXIE
    $define _RCIF_ PIR1Bits_RCIF
    $define _RCIE_ PIE1Bits_RCIE

    It is the same for UART2 (with others pins).
    The baud rate is set automatically at maximum speed depending of the FOSC value. See the table.
    A lower baud rate can be chosen by the user.

    STEP04: Declare the PIC® features.
    Many parameters are automatically defined by the data we have available in the compiler.

    Write the Device ID:
    Read the value from the "DeviceList.Inc" file, also from the PICxxxx.dev files in the Device MPLAB® folder or from the datasheet. Transform the hex value ID (from MPLAB or datasheet) (id=0x5540) to binary => (01010101000000). Shift the value to the right 5 times (>> 5). And transform the new value to decimal (010101010) => 682.
    $if _device = _18F25K22
    $define __DEVICE_ID 682
    $endif

    Write Size of the Code Memory Erase Segment (in Bytes):
    $define ERASE_FLASH_BLOCKSIZE 64

    Write the IDLOCS address in memory map:
    Symbol ID_LOCATION_ADDRESS = $200000

    Write the CONFIG address in memory map:
    Symbol CONFIG_ADDRESS = $300000

    Write the ID LOCS address in memory map:
    Symbol ID_ADDRESS = $3FFFFE

    Write the EEPROM address in memory map:
    Symbol EEP_ADDRESS = $F00000

    Define the RANGE to erase the eeprom Data.
    $define EEP_ERASE_LOW_ADDRESS 0 ' Low address from be erased. (MIN = 0)
    $define EEP_ERASE_HIGH_ADDRESS _eeprom - 1 ' High address to be erased. (MAX = _eeprom - 1)

    STEP05: The user can choose some options.
    (1) Check the empty ROM memory after erase the User space.
    $define _CheckUserROMerased_
    This option takes some time to execute.

    (2) Erase the eeprom memory before to write it. If it is enabled then you define the range.
    $define _EnableEraseEeprom_
    This option takes some time to execute. (4mS per eeprom Byte)

    (3) Write the ID LOCATIONS.
    $define _EnableWriteIDLOCS_

    (4) Print the Devide ID number and revision of the PIC to the terminal.
    $define _EnablePrintDeviceID_

    STEP06: Declare some options for debugging.
    In case of issues or to see how the code runs, the PDS® user can choose a debug option.

    (1) Print the ID Locations (write & read).
    $define _DebugIDLOCS_

    (2) Print the config fuses only.
    $define _DebugCONFIG_

    (3) Print the incomming datas of every line reading the UART directly.
    $define _DebugRX_UART_LINE_

    (4) Print the Data from buffer and eeprom memory
    $define _DebugEEP_

    (5) Print the input buffer and read the ROM after write.
    $define _DebugWRITEROM_

    (6) Print "WOC" (Write OpCode) in the terminal every time the OPCODE is written.
    $define _DebugOPCODE_

    (7) Print the RCON Status and oher informations at reset or power-up.
    $define _debugRESET_

    STEP07: Write or use the config fuses list generated by the "PIC® Fuse Configurator".

    STEP08: Using the ID LOCS option.
    Modify, copy and paste in the user main code if the ID LOCS option is needed. (at the end of the user .bas file)
    (ASCII characters or NUMBERS)
    Asm
    __IDLOCS 0x200000,"A" ; Or 0x01 (or your numbers)
    __IDLOCS 0x200001,"G" ; Or 0x02
    __IDLOCS 0x200002,"V" ; Or 0x03
    __IDLOCS 0x200003," " ; Or 0x04
    __IDLOCS 0x200004,"V" ; Or 0x05
    __IDLOCS 0x200005,"1" ; Or 0x06
    __IDLOCS 0x200006,"." ; Or 0x07
    __IDLOCS 0x200007,"0" ; Or 0x08
    EndAsm

    STEP09A: Define the position of the arrays in the RAM.
    A bad position of the arrays in the RAM could produce some writing/readings errors of the buffers. It is more important that the Arrays are not between BankA and Bank0. A dummy array is created automatically to move out the Buffers of the BankA, nothing to do if the Bank0 is large enough. Please see the explanation in the .bas file and verify the result after compiling.

    STEP09B: Configuration of the Internal Oscillator (if needed). Version 2.1
    Each PIC® family has the very specific oscillator block, consult the datasheet.
    In this version 3 SFRs have been configured, OSCCON2, OSCCON and OSCTUNE
    Enabled the "
    $define _InternalOSC_" line in the STEP04.
    Please, you have to respect the different FOSC values used by the bootloader.
    The code in STEP09B could be modified by experimented users.
    Code:
        $ifdef _OSCCON2
        OSCCON2 = 0                         ' MFINTOSC is not used, Secondary oscillator is shut off, Primary Oscillator Drive Circuit Shutdown
        $endif
        OSCCON = 110000                  ' Internal oscillator: Sleep, 16Mhz, R, R, Primary clock.  
        OSCTUNEBits_PLLEN = 1               ' PLL enabled (FOSC = 64Mhz)
        OSCTUNEBits_INTSRC = 1              ' 1 = 31.25 kHz device clock derived from 16 MHz HFINTOSC source (divide-by-512 enabled) (if necessary)
        While OSCCONBits_IOFS = 0 : Wend    ' Wait untill OSC is stable (not a good job)
    After each reset and/or write of the configuration registers the oscillator is not stable. A delay has been added (25mS).

    STEP10: Do the user settings. (Write your parameters if necessary)
    Once the user has to initialize some variables of the PIC®. These variables must be set by the USER for every different PIC®. Set the PIC® to digital for used pins and more... If the user writes some stuff, it could be necessary to add some bytes in "USER_CODE_SIZE" (STEP00) value to avoid a ROM space issue in compilation. Usely it is already done by me in the templates.

    STEP11: Undo the user settings.
    It might be necessary to put again the PIC® into reset state. Undo the user settings.
    It could be necessary to add some bytes in "USER_CODE_SIZE" (STEP00) value to avoid a ROM space issue in compilation. Usely it is already done by me in the templates.

    VERY IMPORTANT:
    The user main code must have the same configuration as the bootloader.
    Device = 18F25K22
    Declare Xtal = 64
    Declare Optimiser_Level = 2
    Declare Dead_Code_Remove = On
    Declare Bootloader = Off
    Declare Watchdog = On ' (if necessary)
    Add the same list of Config Fuses. (mandatory)
    Add the ID LOCS table if necessary. (this option must be activated in the bootloader code)

    Please use the "Dev_18F23K22_18F46k22.bas" or the "Dev_18F2682_18F4685.bas" file as a template to design all new PIC® bootloader. (version 2.0)

    STEP12: Your bootloader release. (mandatory version 2.0):
    If you have chained several options and/or debug options, and because the new template is written for ROM up to 128 KB, the PDS user must adjust the position of the firmware at the top of the memory to save some bytes. (mandatory for ROM < or = 64 KB) The PDS user MUST to execute the STEP12 of the configuration.
    1- Configure your PIC.
    2- Choose the options.
    3- Compile.
    4- Read the final of the Bootloader.lst file with the notepad.
    5- Count the number of bytes used by the bootloader only (Do not include the lines with block number 0000)
    6- Edit the STEP12 of the Bootloader BAS file. Place the number of bytes of your new firmware. (Symbol LOADER_SIZE_MIN = xxxx)
    7- Disable the upper line (comment the line): 'Symbol LOADER_SIZE_MIN = LOADER_CODE_SIZE + OPTIONS_CODE_SIZE + DEBUGS_CODE_SIZE
    8- Compile again and the Bootloader code is placed correctly at the top of the Flash Memory using the last erase memory block.
    9- The result (file.hex) is your bootloader firmware for your proyect.

    How does the bootloader run?
    After a first reset the OPCODE is written in the position 0 of the ROM.
    The booloader stars at reset or power up.

    Step1:
    At reset the code jumps to the bootloader label.
    If is waiting bytes from the UART, after a time out of 2 seconds, if there is an user code, jumps to the position 4 of the ROM (goto proton#main#start); otherwise the code will go to a waiting loop.

    Step2:
    If the first line of the .hex file is properly decoded then the bootloader checks the Device ID.
    In this state it is considered that the process is correct and everything can begin.

    Step3:
    Erase the eeprom If this option has been enabled by the user with a determinate range.

    Step4:
    Erase all USER FLASH memory.

    Step5:
    Print "LOD" (LOADING) to the terminal and start to read the second line and all datas from the .hex file.

    Step6:
    The bootloader reads the different lines of the .hex file. When a write block is completed then the bootloader writes it immediately. The bootloader can recognize where is the code of the new shifted line. The big challenge has been to recognize the hashed code and rebuild the full blocks to write. The hard work that the host PC program usually did, this firmware will do it too.

    Step7:
    Write the ID LOCS if this option has been activated.

    Step8:
    Read the Config fuses and do nothing.

    Step9:
    Write the eeprom if there are eeprom datas from the .HEX file.

    Step10:
    Check the final line of the .HEX file.
    Then the "DLS" message (DOWNLOAD SUCCES) is sent to the terminal.

    Step11:
    Write the OPCODE.
    The firmware self write the opcode "Goto PIC#Loader#Boot" in position 0 of the ROM.
    If the OPCODE debug has ben activated, then the "WOC" message (WRITE OPCODE) is sent to the terminal.

    Step12:
    Goto the user code.
    Then the "RUC" message (RUN USER CODE) is sent to the terminal.

    DETECTION OF ERRORS:
    All bytes that are written are fully checked, if only one bit fails an error is generated. When any error is detected then the writing process is immediately stopped and a warning is generated corresponding. It is still receiving the HEX file data but nothing is done until the end of the download file to avoid to crash the (any bad) Computer Terminal Software. After any error a new opcode is rebuilt.

    If the "Goto proton#main#start" opcode is erroneous then the "GSF" (General System Fails) message is sent.
    After a Time Out or an Error occured a final message "WRT" (WAITING A RESET) is sent to the terminal.

    I recommend to read carefully all the comments in the .BAS file and the table of errors.
    I have used a lot the preprocessor code to control the parameters written in the bootloader, avoiding mistakes that can delay the work of PDS® user.

    Some Bootloader Messages:
    First Reset after programm the firmware: with _DebugPrintOPCODE_ option.
    AGV BOOTLOADER V2.1 ' Version of the Bootloader
    WOC ' Write the OpCode "Goto PIC#Loader#Boot".
    WRT ' Waiting a Reset.

    First Reset after programm the firmware: without _DebugPrintOPCODE_ option.
    AGV BOOTLOADER V2.1 ' Version of the Bootloader
    WRT ' Waiting a Reset.

    An error not defined.
    AGV BOOTLOADER V2.1 ' Version of the Bootloader
    GSF ' General System Fails. Usually it could be a bad UART communication, a write ROM error, a bad "Goto proton#main#start" opcode and more...
    WRT ' Waiting a Reset.

    A successful Download: with _EnablePrintDeviceID_, _DebugPrintOPCODE_ options.
    AGV BOOTLOADER V2.1 ' Version of the Bootloader
    DEVICE ID: $0021 REV: $07 ' Device ID and revision. (18F452)
    LOD ' Loading begins...
    DLS ' Download Success
    WOC ' Write the OpCode "Goto PIC#Loader#Boot". (if the print option has been activated)
    RUC ' Run User Code.

    A unsuccessful Download: with _EnablePrintDeviceID_, _DebugPrintOPCODE_ options.
    AGV BOOTLOADER V2.1 ' Version of the Bootloader
    DEVICE ID: $0021 REV: $07 ' Device ID and revision. (18F452)
    LOD ' Loading begins...
    GSF ' General System Fails or another error message.
    WOC ' Rewrite the OpCode, because the memory has been altered. (seen if option has been activated)
    WRT ' Waiting a Reset.

    A unsuccessful Download: Because the PIC® ID is not correct.
    AGV BOOTLOADER V2.1 ' Version of the Bootloader
    DEVICE ID: $0021 REV: $07 ' Real Device ID and revision. (18F452) (If the print option has been activated)
    DVF ' Device ID Fails, the PIC® in board is not correct.
    WRT ' Waiting a Reset.

    For more examples, see the errors table.

    The external communication software:
    A simple RS232 communicator software is needed to send the .HEX file to the PIC® with software Handshake protocol XON/XOFF capability. A push button conected to the reset pin of the PIC® is needed to start the bootloader.

    I am using a good and simple terminal: The CoolTerm Version 1.4.6 built 322 for WIN7. (It is the best for me)
    CoolTerm is a simple serial port terminal application (not a terminal emulation). It is quite fast sending the ASCII bytes of the .HEX file. All terminals do not work with same speed when using the XON/XOFF protocol(?).

    Setting the CoolTerm Terminal communication:
    Press the OPTIONS icon.

    Serial Port:
    set the COM Port: COMx
    Baudrate: 115200 (for example for FOSC = 64Mhz)
    Data Bits: 8
    Parity: none
    Stop Bits: 2
    Flow Control: XON
    Initial Line States when Port open: DTR Off, RTS Off.

    Terminal:
    Standard settings = OK
    Special character handling: Set the "Convert Non printable character".

    Receive:
    Ignore receive signal errors (version 2.1)
    Receive Buffer Size: 100000 (for debugging)
    Wait for terminate string: Termination string OD, OA
    Others: NO change

    Transmit: (for password, version 4.0)
    Send String Options: Termination String (Hex) = 0D 0A

    Miscellaneous:
    Automatically disconnect on close.

    Press OK and connect. If a recepction error occured then reconnect.

    How to download a .HEX file:
    In the tool bar, press "Connection".
    Press "Send Text File"...
    Browse the .HEX file.
    Press the Reset button of the PIC® board. (2 seconds Time Out)
    Press the "OPEN" icon. => sending hex file.

    How to download a .HEX file with Password:
    In the tool bar, press "Connection".
    Press "Send String"...
    In the new window, set ASCII option. Copy your Password in the new Window (including the ":" first character).
    Press the Reset button of the PIC® board. (2 seconds Time Out)
    Press "Send" in the Send String window (Password) (Now a new 10 seconds Time Out is starting)
    Browse the .HEX file.
    Press the "OPEN" icon. => sending hex file.
    After flashing the firmware the first password is always (: AAAAAAAA) without KEY coding.


    A manual harware reset could be done (for the Amicus18 Board) pressing/depressing the green LED DTR in the lower right side of the terminal window.

    Developpment Board:
    During the developpment I was using 2 Amicus18 Boards and different shields.
    Some issues could occur using the PICkit3® and ICD3® to flash the firmware. (Perhaps same issue with other programmers)
    - The R3 (connected to the reset pin to +VDD) must to be a 4k7 resistor in serie with a diode (1N4008 not included in board), for the +5V board. For the +3,3V board I connected a 2K7 resistor in serie with a 1N4008 diode.
    - The VDD pin of the ICSP connector is disconnected. The ICD3® programmer cannot see the PIC®.
    - It is mandatory to connect a wire from the VDD pin of the ICSP connector to the pin 20 of the PIC®. (NOT to +3,3V or +5V)

    The bootloader code length:
    The basic code occupies only 1520 bytes (more or less) without any options.
    With eeprom, ID LOCS and print Device ID options, the code can occupy less then 2KBytes of ROM. The lenght of several routines could change according with the PIC® familly. I think it is very satisfactory considering the complexity of the project.

    Test Files:
    The "Codetest_uart1.bas" or "Codetest_uart2.bas" files:
    All library files for this test file are awailable in the INC_Files folder.
    This code is written to test the bootloader for all the functions that could fail.
    - Use the UART1 or UART2.
    - Use the interrupts.
    - Use the Watchdog.
    - Use the strings of EEPROM memory that the bootloader wrote.
    - Read data ID LOCS that the bootloader wrote.
    - Read the strings written in the ROM memory.
    - Use the ports pins of the PIC® for 8 push buttons and 10 LEDs.
    - Write a hashed code when this option is enabled. several code jumps are generated.
    - Try the new commando ORG_EBlock(Address) or ORG_WBlock(Address).
    - Use the new HRSOut command sending bytes with 2 stop bits to have compatibility with the Computer Software.
    - Used 28 or 40 pins PIC®.
    The PDS user can try downloading the "Codetest_uartX.bas" without needing the special hardware (LEDs and Push buttons).
    - New "Codetest_uart1_80Mhz.bas" test files for the PIC18FxxK20 series. (version 2.0)

    Tips'n & Tricks:
    Hashed user code:
    If the programmer uses one or several "ORG" commands placed in the .bas file, the code becomes hashed. The new lines of code are not synchronized with the Write Block.
    This issue has been solved in the bootloader code. The firmware has been only tested for 8, 16, 32, 64 Write Blocks Bytes and 64 Erase Block Bytes. For best security I recommand to use my new "ORG" macro that syncronizes the ORG PDS command with every Erase Blocks for this one and new versions of the bootloader.
    Download the "ORG_SyncBlock.Inc" file and use the "ORG_EBlock(3550)" macro. (Erase Block synchronized)
    HRSout:
    I wrote a new HRSout/HRSout2 commands (fully compatible with the user code) to communicate with the PC sending bytes with 2 stop bits.

    Example of a hashed code:
    Code:
    MEMORY USAGE MAP ('X' = USED,  '-' = UNUSED)
    0000 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    00C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0140 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0180 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    01C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0280 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    02C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0300 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0340 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0380 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    03C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0400 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0440 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0480 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    04C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0500 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0540 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0580 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    05C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0600 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0640 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0680 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    06C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0700 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0740 : XXXXXXXXXXXXXX-- ---------------- ---------------- ----------------
    0DC0 : ---------------- --------------XX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0E00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0E40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0E80 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0EC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0F00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0F40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0F80 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0FC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1000 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    10C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1140 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1180 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    11C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1280 : XXXXXXXXXXXXXX-- ---------------- ---------------- ----------------
    2040 : ---------------- ---------------- ------------XXXX XXXXXXXXXXXXXXXX
    2080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    20C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2140 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2180 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    21C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2280 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    22C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2300 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2340 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2380 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    23C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2400 : XXXXXXXXXXXXXXXX XXXXXXXX-------- ---------------- ----------------
    5C00 : ---------------- --XXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5C40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5C80 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5CC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5D00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5D40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXX---------- ----------------
    6E80 : ---------------- ---------------- ---------------- --------------XX
    6EC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    6F00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    6F40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXX--
    ALL OTHER MEMORY BLOCKS UNUSED.
    PROGRAM MEMORY BYTES USED:  4641
    Example of a hashed code synchronized with the Erase Block:
    Code:
    MEMORY USAGE MAP ('X' = USED,  '-' = UNUSED)
    0000 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    00C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0140 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0180 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    01C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0280 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    02C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0300 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0340 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0380 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    03C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0400 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0440 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0480 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    04C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0500 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0540 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0580 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    05C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0600 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0640 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0680 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    06C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0700 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0740 : XXXXXXXXXXXXXX-- ---------------- ---------------- ----------------
    0DC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0E00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0E40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0E80 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0EC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0F00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0F40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0F80 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    0FC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1000 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    10C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1140 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1180 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    11C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    1240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX ----------------
    2040 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2080 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    20C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2100 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2140 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2180 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    21C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2280 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    22C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2300 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2340 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    2380 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    23C0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXX---- ----------------
    5C00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5C40 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5C80 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5CC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5D00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    5D40 : XXXXXXXXXXXXXXXX XXXX------------ ---------------- ----------------
    6E80 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    6EC0 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    6F00 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
    ALL OTHER MEMORY BLOCKS UNUSED.
    PROGRAM MEMORY BYTES USED:  4641
    Templates:
    All firmwares must be generated from the mother file Dev_18F23K22_18F46K22.bas or Dev_18F2682_18F4685.bas. Changing data and settings to start [do in Step(10)] and to end [undo in Step(11)] other templates can be generated for different families of PIC®'s.
    The PIC18F46K22 in (Dev_18F23K22_18F46K22.bas) file has been tested with succes with the UART1 & UARt2.
    The PIC18F452 bootloader has been written to test the write blocks of 8 bytes. (Dev_18F242_18F458.bas)
    The PIC18F4520 bootloader has been written to test the write blocks of 32 bytes. (Dev_18F2420_18F4520.bas)
    The Dev_18F23K20_18F46K20.bas template can generate bootloaders with 16, 32 or 64 Write Blocks bytes according of the PIC®.

    Choose a PIC®:
    The PIC18F452, PIC18F4520 and PIC18F4620 are obsolete, better to choose the PIC18F46K22.
    Before you choose a PIC®, please check the erratas files from the Microchip© web. Some chip erratas could affect the bootloader funcionality. I did not study if my bootloader is compatible with the PIC18FJ series.

    This bootloader code could be a starting point for other more specialized. So I hope to write a new code for a PIC® that has more than 64KB of ROM. For this I'll need a new big PIC®!

    The pain of the Flow Control XON/XOFF with FTDI chip:
    Software flow control uses the TX and RX signals to send XOFF and XON control characters. The receiving side (PIC®) sends an XOFF character over its TX line to tell the transmitting side (Computer) to stop transmitting, and sends an XON character over its TX line to tell the transmitting side (Computer) to resume transmitting. Hardware flow control is more reliable. If cost is an issue you can use software flow control, provided your data does not conflict with the XON/XOFF characters. Usually the Software Flow Control is could be recommended for sending ASCII files.

    Data Throughput, Latency:
    For a USB device, data transfer is done in packets. If data is to be sent from the PC, then a packet of data is built up by the device driver and sent to the USB scheduler. This scheduler puts the request onto the list of tasks for the USB host controller to perform. This will typically take at least 1 millisecond to execute because it will not pick up the new request until the next 'USB Frame' (the frame period is 1 millisecond). Therefore there is a sizable overhead (depending on your required throughput) associated with moving the data from the application to the USB device. (Please read the FTDI information)

    FTDI issue?
    I tried 2 different FTDI chips and drivers, and the code always fails with the Software Flow Control in all Baud Rates. Why???
    For software flow control, the driver needs to check each incoming byte of data to see if an XON or XOFF character has been received. Doing this wastes time and is not reliable since before the XOFF character is received the driver may still need to read out data from the UART. This latency will cause the driver to send more data and may cause a data overrun on the receiving side (PIC®). Perhaps the internal Software Flow Control of the FTDI chip does not detect the XOFF byte correctly???

    When the terminal (computer side) is configured to send bytes with stop bits 2 and receiver (PIC® side) is configured to receive 1 stop bit, everything seems to change. When the "CR" character is detected, the receiver (Bootloader side) send as fast as possible a XOFF character before the computer side can send the "LF" character. It seems that 1 stop bit delay is sufficient that the start bit of the XOFF character could be detected and later stop the data flow.
    It could be that the "LF" character is left for the next line or miss. It is not important because a piece of code in the bootloader allows to synchronize each line with the character ":".

    As the system is fully configured the Software Flow Control works up to 115200 bauds (FOSC = 64Mhz or 40Mhz). I did not find any explanation in the FTDI documentation. When the Computer Side is sending a file with the XON control, the PIC® side cannot send a byte different of the XOFF until the downloading is complete.

    Many terminal programs have the option to add a delay at the end of each line. The CoolTerm can add a delay when a special character is detected, for example the "CR" charater. But curiously this solution does not work for the Software flow control with the FTDI chip. Adding a delay (minimum 1ms!!) in each character then the Software Flow Control can work with 1 stop bit. What it seems to confirm my theory that the XOFF character (PIC® side) must be detected between 2 bytes of the Computer transmitting side!!! Could be?
    A delay of 1 byte between transmiting bytes might be enough in the computer side. It seems that this issue is a mystery. Notice for computer programmers.
    I tested the bootloader with the Amicus18 board and the PICDEM2 PLUS board including another FTDI chip an driver. Hundreds of downloading files have been executed with full success at 115200 Baud rate without a character error with 2 stop bits configuration in the computer side.

    BOOTLOADER CODE WARNING:
    Any change in the bootloader code should be checked carefully and could affect other routines. I advise them to do so only for very experimented PDS users. It is not recommended you to change the Bootloader Code unless you know what you are doing.

    Version: V2.0 03/11/2016
    - The code has been modified to write the ROM up to 128KB.
    - Thanks to these changes the code is much more efficient and takes up less memory space.
    - The configuration "$define _EnableAffirmativeMessages_" has been added to save lines of code. The bootloader does not send any message when the downloading is succesfull. (only for the options: _CheckUserROMerased_ / _EnableEraseEeprom_ / _EnableWriteIDLOCS_) The bootloader becomes invisible.
    - Now the bootloader works with FOSC = 80 MHz for the PIC18FxxF20 series, fantastic!
    Please read the Les' article.

    Version: V2.1 10/11/2016
    - The code to use the bootloader with the internal oscillator has been added.
    The tests have allowed to operate the bootloader up to 115200 Bauds at 20ºC. For security the speed of the UART has been limited to 57600 bauds.
    Each PIC® family has the very specific oscillator block, consult the datasheet. In this version 3 SFRs have been configured, OSCCON2, OSCCON and OSCTUNE. In some new PIC® you must configure more registers. In this case, you can modify the code and the number of bytes for this option, always being an even number.

    Note:
    As the bootloader is for a given project, if the internal oscillator is configured in the bootloader it is not necessary to repeat the operation in the user code. This allows you to save some lines of code. However, you can change the frequency of the oscillator in the user code, always in the determined margins.

    Version: V4.0 07/12/2016
    I wrote a new bootloader, using the PDS only, for the Low Side of the flash Memory (bottom).

    The bootloader written in the bottom of the memory (Low Side of Memory) has a single advantage: it can be protected by the own PIC against writing or reading. To increase security I have developed a password system.
    But this system has two drawbacks:
    - Redirect the interrupt vectors. (2 goto's for every vector, only one "goto" for High Side Memory bootloader)
    - It is necessary to move the start address of the user program to a determined Address, in this case in the origin is 2048. (nothing to do for High Side Memory bootloader)

    Example for user code:
    Device = 18F25K20
    Declare Xtal = 64
    Declare Optimiser_Level = 2
    Declare Dead_Code_Remove = On
    Declare Bootloader = Off
    Declare Watchdog = On
    Declare PROTON_START_ADDRESS = 2048

    I have had to remove all the debug routines so that the bootloader can be less than 2048 bytes, that is the dimension of the Boot Block. In the same way I have reduced all information messages or errors to two only. Message "E" for any error and "W" when the bootloader waits for a reset. These usually indicate that there is no user program flashed.
    In version 4.0 a double password system has been developed.
    In order to obtain the maximum protection of the Boot Block/Bootloader/password it is necessary to configure the Config Fuses correctly. It is valid for a 2048 Bytes boot block only.
    I recommend these settings:
    CPD = On ;Data EEPROM code-protected
    CPB = On ;Boot block (000000-0007FFh) code-protected
    WRTB = On ;Boot Block (000000-0007FFh) write-protected
    WRTC = On ;Configuration registers (300000-3000FFh) write-protected
    EBRTB = On ;Boot Block (000000-0007FFh) protected from table reads executed in other blocks.

    Mode 0:
    This mode employs a very efficient random password system that can generate hundreds/thousands of different codes. After each download the bootloader generates a new password stored in eeprom memory, which should be protected against reading. The random password system uses a 4-byte binary key transformed into eight Ascii Hex characters. The eight characters written in the eeprom memory are also coded with another key. Which makes it harder to find out the written password. Each time you press the reset button to download, the bootloader asks for the password number. The user must always know the next code to use.
    Download a file with random password:

    How the password is written in the eeprom memory:

    Each project must have a different key (KEYNumber). To get the thousands of different passwords the bootloader will be used itself. Follow the code in STEP10.
    Enable the line "$define _EnablePassWordMode0_" for the random password.
    You will find a PN1DF4E178_01.txt file containing 1000 passwords with the key 1DF4E178.

    Mode 1:
    This mode employs one password only (eight Ascii Hex characters). Then the eeprom memory is not used.
    Enable the line "$define _EnablePassWordMode1_" for the unique password.

    Password enabled:
    Send a file with password error:
    The Bootloader sends a message error (E) and goes to the old user code.
    If error within downloading the hex file:
    The Bootloader sends a message error (E) and goes to an infinite loop waiting a Reset (W).
    Make a reset to goto to the old user code; if erased then goes to a infinite loop waiting a Reset (W).

    Version: V2.2 12/12/2016
    For the Bootloader in the High Side of the flash Memory (TOP).
    I have fixed a writing error of the first blocks of the ROM when the High and Low Interrupts are used. Rebuild the first blocks in all conditions is a difficult task.
    The version 4.0 is OK.

    Version: V3.0 13/01/2017
    For the Bootloader in the High Side of the flash Memory (TOP).
    I have removed the debug codes and messages of the V2.2, I have simplified and I have added more automatic configuration. The bootloader configuration is more readable. I added the password system too.

    Version: V4.1 15/01/2017
    For the Bootloader in the Low Side of the flash Memory (Bottom). I have simplified the configuration and it is more readable.

    PDSloaderK40 Version: V1.0 07/02/2017
    This version of the bootloader has been written for the PIC18FxxK40 series.
    The PIC® of the K40 series are very different. The timers must be configured differently. The reading/writing of the
    ROM is more complex. All these changes have needed more lines of code. I have added more security in the code. The PIC18F27K40 and PIC18F47K40 have been tested with real parts. The other PICs have the same structure. Different templates will be used for many PIC18FxxK40.
    For the LSM (Low Side of Memory) the ROM space is limited to 2048 bytes. If all options are included, there is not
    enough space left. Choose the most important options only.

    The Bootloader code is written from the beginning with low level commands. Which makes it insensitive to PDS® version changes.
    The user code should be written with the PDS® version 3.5.9.0 or higher, due to the difficulties generated by the
    changes of banks for the SFR registers. You can write your own code if you use the HRSOut_K40.inc library (for 5 UARTs). Insert this file at the beginning of your bas file (waiting a new version of PDS). At the top of this file enable the line "$define _Disable2StopBits_" to work with one stop bit.

    In the "STEP03:" of the configuration, the pins of the UART are automatically configured to be compatible with the
    PIC18F46K22 for testing (change is easy). The other UARTs have been configured using the default pins.
    To configure the pins of your project use the PPS_18FxxK40-inc file.

    I have verified and fixed all the .def and .ppi files for all PICs® used in these templates.
    I enclose all copies of the new modified files. Before doing anything make a copy of all .def & .PPI files of the PDS® compiler.

    Version: V5.0 23/12/2017
    New version of the Bootloader. It is more easy to use. Included Manual Part1.

    Enjoy the "AGV Bootloader V5.0" for the PDS® and Good Luck. Please write your comments or questions in the Wiki discussion forum.

    The "AGV Bootloader" is available HERE.

    Alberto

    PIC®, MPLAB®, PICkit3® and ICD3® are registered trademarks of Microchip Technology Inc©.
    Proton Development Suite® or PDS® are a registered trademark of Crownhill Associates Limited©.