PIC24F Bootloader- Unable to set "Preserve Program memory range" with Pickit3 - Page 1
Forum section: electronics / general

author: muthukural001
author_rank: Regular Contributor
timestamp: May 04, 2018, 09:28:10 am
content: Hello All,I have been developing UART boot loader for My PIC24FJ128GB206 for past two days. As a reference for developing this, I used to read Application note "an1157" from microchip.And I modified the linker scripts shared in thehttp://www.microchip.com/forums/m656979.aspxfor My MCU.For Reference, I attached the two linker scripts.Well coming to the problem:I will first load My bootloader and then test code like Led blinking.So, I need to preserve bootloader code from erasing.For this, I need to set Pickit 3 in MPLAB so that it will not erase them while flash LED blink code.Here is how I am setting Pickit 3 for that:* Went to Properities->Pickit3->Memories to Program->Manually select Memories and Ranges*Selected "Manually select memories and ranges"*Checked "Configuration memory" and "Program memory"*Set "Program memory range" to 0x1400 - 0x157f7 as My boot loader code resides below 0x1400.*Checked "Preserve Program Memory"Problem:*Tried to set "Preserve Program Memory range" to 0x00 - 0x13FF to prevent My Boot loader code from Overwriting.But, it is not allowing to set the range and the correspondig field shaded with "red" colour.*Also, tried to uncheck "Erase all Before Program". But, it was greyed out (disabled).*Attached images of the errors and linkker scripts.

author: max_134
author_rank: Newbie
timestamp: July 29, 2025, 05:45:45 pm
content: Have you found a solution to this? I am also currently stuck with this issue. I have a custom bootloader programmed into boot flash and I'm trying to run debug mode while retaining the contents of that memory space

author: JPortici
author_rank: Super Contributor
timestamp: July 30, 2025, 07:27:08 am
content: I believe it's not possible to preserve the first page, as it contains the reset vector and IVT, and *logically* there would be no reason to preserve them.Unfortunately things are not as easy as in XC8, where you add the bootloader as a loadable project and the debugger happily understands both.If you can't just debug the application project (or you are in the phase of testing how both behave), this workaround always worked for me* set bootloader project as main project* program the bootloader for debug* stop the debug session* set application project as main project*buildthe application project for debug (to get debugging symbols)*launchthe debugger,don't programNow you'll be in a debug session, in bootloader mode.Download the application through the bootloader interface and switch to the application.Now you'll be in a debug session, with both the bootloader and the application. Pausing / hitting a breakpoint while executing application code will work as if you were debugging the application.Reset may take a while before hitting application's main, or may "fail" by showing "no lines of code found at address xxxx" because it's in the bootloader area and the debugger has no information about that. Just let it run to the application main and you're set.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: July 30, 2025, 09:24:07 am
content: Not sure what you are trying to do here - why do you need to perserve anything?The way I handle bootloaders is the application code source includes a dummy bootloader that just jumps over the non-existent bootloader, so it can be compiled and debugged by itself.The Bl is a standalone project, which can also be debugged by itself.That way the BL and App code can be written and debugged completely independently from each other.The methods of doing this vary, possibly just as I found different ways of making this work with different compilers over the years- for XC32 I have some constant words in the linker file representing the jump instructions.For XC8 I add a CODEOFFSET to shift the code, and add the following to the app codeQuoteTo create a final composite image of BL+App for production programminng, I just run the BL, upload the app code, and read the resulting image out of the device.ISTR having to do quite a lot of fiddling with XC8 before I got it to work & not done it on the PIC24 - is there something about the XC24 compiler that prevents the same method being used ?

author: JPortici
author_rank: Super Contributor
timestamp: July 30, 2025, 10:21:34 am
content: Quote from: mikeselectricstuff on July 30, 2025, 09:24:07 amI wrote a c++ program that parses and combine arbitrary hex files, and run as a post build scriptQuote from: mikeselectricstuff on July 30, 2025, 09:24:07 amCodeoffset etc don't exist in GCC, it's an XC8 specific thing i'm afraid. XC16 (and XC32... and XC8 in AVR mode) simply can't operate like XC8 (for PIC) in this regard.My experience was quite the opposite, XC8 was pretty straightforward:- restrict ROM range in bootloader project- Optional: Add interrupt redirect code for devices without the VIC. In devices with VIC, disable locking in configuration words and use attribute base to redirect the IVT to be in application space- Add Bootloader project as loadable project in application project- Add codeoffset option to application project- Use the same config words in both projectsand done. Build will build a combined hex ("combined" in build folder) and debug will halt in either project depending on the program counter. If only it was this easy in GCC..

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: July 30, 2025, 10:34:18 am
content: Quote from: JPortici on July 30, 2025, 10:21:34 amIn PIC32 (GCC, so presumably others that use GCC) you can do it all in the linker file - both the code offsetting and patching the vectors.For example for pic32MX1xx, shifting everything up by 4K ( because the boot area on this part is tiny so the BL lives at 0)Disclaimer : this was tweaked from the original by poking at things like a monkey until it worked - I don't claim to understand all of this. I rarely use the debugger so quite possible this does not deal correctly with stuff used for debugging, but should be fixable if notCode:PROVIDE(_vector_spacing = 0x00000001);_ebase_address = 0x9D002000;/************************************************************************** Memory Address Equates* _RESET_ADDR -- Reset Vector* _BEV_EXCPT_ADDR -- Boot exception Vector* _DBG_EXCPT_ADDR -- In-circuit Debugging Exception Vector* _DBG_CODE_ADDR -- In-circuit Debug Executive address* _DBG_CODE_SIZE -- In-circuit Debug Executive size* _GEN_EXCPT_ADDR -- General Exception Vector*************************************************************************/_RESET_ADDR = (0x9D002000 + 0x1000);_BEV_EXCPT_ADDR = ((0x9D002000 + 0x1000) + 0x380);_DBG_EXCPT_ADDR = ((0x9D002000 + 0x1000) + 0x480);_DBG_CODE_ADDR = 0x9FC00490;_DBG_CODE_SIZE = 0x760 ;_GEN_EXCPT_ADDR = _ebase_address + 0x180;_ORIGINAL_RESET_ADDR = 0xBFC00000;_SUM_ADDR = 0x9D002000 ;/************************************************************************** Memory Regions*=* Memory regions without attributes cannot be used for orphaned sections.* Only sections specifically assigned to these regions can be allocated* into these regions.*************************************************************************//*for 130f064 - 64k flash, 16k ram*/MEMORY {kseg0_program_mem (rx) : ORIGIN = (0x9D002000 + 0x1000 + 0x490), LENGTH = 0x10000 - (0x6000 + 0x1000 + 0x490) /* All C Files will be located here */exception_mem : ORIGIN = 0x9D002000, LENGTH = 0x1000 /* Interrupt vector table */debug_exec_mem : ORIGIN = 0x9FC00490, LENGTH = 0x760kseg0_boot_mem : ORIGIN = 0x9D002000, LENGTH = 0x0 /* This memory region is dummy */kseg1_boot_mem : ORIGIN = (0x9D002000 + 0x1000), LENGTH = 0x490 /* C Startup code */config3 : ORIGIN = 0xBFC00BF0, LENGTH = 0x4config2 : ORIGIN = 0xBFC00BF4, LENGTH = 0x4config1 : ORIGIN = 0xBFC00BF8, LENGTH = 0x4config0 : ORIGIN = 0xBFC00BFC, LENGTH = 0x4kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x8000 /* 64K */sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000configsfrs : ORIGIN = 0xBFC00BF0, LENGTH = 0x10origreset (rx) : ORIGIN = 0xBFC00000, LENGTH = 0x08sumloc (rx) : ORIGIN = 0x9D002000, LENGTH = 0x08}/************************************************************************** Configuration-word sections*************************************************************************/SECTIONS{ /* create a jump instruction at the reset address to bypass the non-present bootloader when compiling standalone */.origreset _ORIGINAL_RESET_ADDR :{LONG( ((_reset >> 2) & 0x03FFFFFF) | 0x08000000);LONG(0);} > origreset}

author: JPortici
author_rank: Super Contributor
timestamp: July 30, 2025, 12:08:41 pm
content: Quote from: mikeselectricstuff on July 30, 2025, 10:34:18 amOf course, what i meant is that there is not a linker option doing it for youone can do all sorts of stuff with the linker script