There are probably simpler ways, but I have documented the procedure I used. Note that I started with Mechanique's MCLoader.
Disclaimer: This is a complicated process that requires some knowledge of assembly. It also works
better with chips that have some "space" above MCLoader. If you use this approach on chips that don't have
at least one erase block above MCLoader (such as an 18F452), if programming is interrupted before successful completion, the BOOTLOADER WILL CEASE TO FUNCTION. This is because PIC memory must be erased before being
written. All codespace below MCLoader (which resides in high memory) is erased before the new program is
loaded.
Proceed at your own risk!
The scheme is basically as follows: (assuming 18F8722 here).
Look at the chip's datasheet and find the "block size" in the section on writing to FLASH memory. Note the ERASE block size and the WRITE block size. On an 18F8722 those are both 64 bytes.
Import the appropriate MCLoader .HEX file into MPLAB. View PROGRAM MEMORY, which basically does a disassembly of the code. Leave this window open, you will be using it again.
#1. Note the jump address - found at address 2 & 3 (it is a WORD, so it takes two bytes). In an 18F8722, this address is 0x1fd04.
Now scroll down to the address pointed to in step #1.
#2. About 16 bytes before this, (1FCF0 in a 18F8722) you will find a series of bytes filled with "0000"'s (the surrounding bytes will be filled with "FFFF"'s). The first byte of these "0000" is the INIT jump vector address. Write that address down as the "INIT JUMP VECTOR LOCATION"
#3. Scroll to the end of MCLoader and check if there is at least one "erase block size" between the end of MCLoader and the end of memory. In an 18F8722 there is. In an 18F450 there is not - Skip to step #5.
#4. Look for a byte on a segment boundary (evenly divisible by the erase segment size) that is just ABOVE the last address used by MCLoader. Write this address down as the "INTERCEPT ADDRESS". This address is 1FFC0 in an 18F8722. Go to step #6
#5. Look for a byte on a segment boundary (evenly divisible by the erase segment size) that is at least 1 erase block size BELOW the address you found in Step #2. Write this address down as the "INTERCEPT ADDRESS".
You will need to modify MCLoader. You can do this in at least two ways: Modify the appropriate MCLoader .HEX file (not for the timid). or you can write a "patcher" in PBP. I have done both.
If you choose to write a patcher, it needs to reside above the first block of memory (you will use the code itself to erase that block, so put an "@ ORG 0x40" at the beginning of your code to make sure it loads above that point. You need to modify the JUMP instruction at location 2 (&3) to point to your INTERCEPT ADDRESS. Before you can write to FLASH, you must erase it, so use the instruction "ERASECODE 0". This will erase the first block of FLASH.
Now use WRITECODE to write the ENTIRE first block of memory and put INTERCEPT ADDRESS in locations 2 & 3. For
an 18F8722 this would be:
WRITECODE $0,$0000
WRITECODE $2,$EFE0 ; Change the initial jump vector to 0x1FFC0
WRITECODE $4,$F0FF
FOR X = $6 TO $3E STEP 2 ; Finish writing the block
WRITECODE X,$FF
NEXT X
Next, you will have to add an instruction at 0x1FFC0 (or whatever INTERCEPT ADDRESS you are using) to add a JUMP to the address found in step #1 - the beginning of MCLoader (Don't forget to erase the block first).
1FFC0 = FFD6 EF82
1FFC2 = FFD8 F0FE
(This is for 0x1FD04)
What you have done is to cause the code to immediately jump to an address of YOUR choosing, and then jump to the
beginning of MCLoader. All this is necessary because you want the bootloader to be able to load your code the first time. So far, all will work normally.
;END OF BOOTLOADER PATCHING
Now, for the application code modification:
A. Add a block in your program to read the INTERCEPT ADDRESS to determine whether or not it is pointing to the beginning of MCLoader.
B. Go to a block that first ERASES the block starting at the INTERCEPT ADDRESS and changes the jump vector there to the INIT JUMP VECTOR LOCATION found in step #2.
C. Write another block that ERASES the block starting at the INTERCEPT ADDRESS and changes the jump vector there to the beginning of MCLoader.
When the program starts, it should perform "A" to see if the jump vector is pointing to MCLoader. If it is, it should call block "B". (Don't write to FLASH unless you really need to change it).
When you wish to unprotect the loader, call block "C"
Bookmarks