Bootloader for PIC24EP?
I have successfully completed bootloader for pic24EP256GP204. There were two issue with my bootloader:


The first bug in my bootloader was in interpreting HEX file format for pic microcontrollers. The address field in the hex file is double that of the PIC device address. I didn't know that. I was using that address directly without dividing it. So, i need to divide the address in a record of hex file by 2 and should use that address for programming pic.
The second bug was in writing the flash. My pic (pic24ep256gp204) supports double instruction flash write operation only. I was making a small mistake in writing the instructions if we need to write a single instruction. I found some code online using it i can write a single instruction by masking either the upper or lower instruction with a double instruction flash write operation. The code i found is pasted below:

unsigned NVMemWriteWord(uint32_t address, uint32_t data)
{
DWORD_VAL writeAddress;
DWORD_VAL writeData;

writeAddress.Val = address;
writeData.Val = data;

NVMCON = 0x4001;        //Perform WORD write next time WR gets set = 1.
NVMADRU = writeAddress.word.HW;
NVMADR = writeAddress.word.LW;

// Set the table address of "Latch". The data is programmed into the FLASH from a temporary latch. 
TBLPAG = 0xFA;
//The smallest block of data that can be programmed in
//a single operation is 2 instruction words (6 Bytes + 2 Phantom Bytes).
// Mask the high or low instruction words depending on the address and write either high or low instruction word.
if(address % 4)
{
    __builtin_tblwtl(0, 0xFFFF);                //Mask the low word of 1-st instruction into the latch.
    __builtin_tblwth(1, 0x00FF);                //Mask the high word of 1-st instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))

    __builtin_tblwtl(2, writeData.word.LW);     //Write the low word of 2-nd instruction into the latch
    __builtin_tblwth(3, writeData.word.HW);     //Write the high word of 2-nd instruction into the latch        

}
else
{
    __builtin_tblwtl(0, writeData.word.LW);     //Write the low word of 1-st instruction into the latch
    __builtin_tblwth(1, writeData.word.HW);     //Write the high word of 1-st instruction into the latch 
    __builtin_tblwtl(2, 0xFFFF);                //Mask the low word of 2-nd instruction into the latch.
    __builtin_tblwth(3, 0x00FF);                //Mask the high word of 2-nd instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))

}       

INTCON2bits.GIE = 0;                            //Disable interrupts for next few instructions for unlock sequence
__builtin_write_NVM();
while(NVMCONbits.WR == 1){}
INTCON2bits.GIE = 1;                            // Re-enable the interrupts (if required).

// Return WRERR state.
return NVMCONbits.WRERR;
 }