I am having issues getting a bootloader for the PIC32MX795F512L working.
I based it off of the example code on the microchip website.
Here is the section of code that I have that should write the memory, I have verified the bootloader up to this point (parses the hex file just fine and the data reaches this point but does not get written to memory):
#define NVMOP_WORD_PGM 0x4001
// Write the data into flash.
Result = NVMemWriteWord(ProgAddress, WrData);
// Assert on error. This must be caught during debug phase.
if(Result != 0)
{
ASSERT(Result==0);
}
UINT NVMemWriteWord(void* address, UINT data)
{
UINT res;
NVMADDR = KVA_TO_PA((unsigned int)address);
// Load data into NVMDATA register
NVMDATA = data;
// Unlock and Write Word
res = NVMemOperation(NVMOP_WORD_PGM);
return res;
}
UINT __attribute__((nomips16)) NVMemOperation(UINT nvmop)
{
int int_status;
int susp;
// Disable DMA & Disable Interrupts
#ifdef _DMAC
int_status = INTDisableInterrupts();
susp = DmaSuspend();
#else
int_status = INTDisableInterrupts();
#endif // _DMAC
// Enable Flash Write/Erase Operations
NVMCON = nvmop;//NVMCON_WREN | nvmop;
// Data sheet prescribes 6us delay for LVD to become stable.
// To be on the safer side, we shall set 7us delay.
delay_us(7);
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA;
NVMCONSET = NVMCON_WR;
// Wait for WR bit to clear
while(NVMCON & 0x8000);//NVMCON_WR);
// Disable Flash Write/Erase operations
NVMCONCLR = NVMCON_WREN;
// Enable DMA & Enable Interrupts
#ifdef _DMAC
DmaResume(susp);
INTRestoreInterrupts(int_status);
#else
INTRestoreInterrupts(int_status);
#endif // _DMAC
// Return Error Status
return(NVMemIsError());
}
An Example of a program address that is being loaded is: 0x9D033358 with data being 2403000E
the configuration bits are set in code and are as follows:
Address Setting
1FC02FF0 FCFFFFFF
1FC02FF4 FFF8FFDF
1FC02FF8 FF69CC5B
1FC02FFC 7FFFFFFF
Couldn't tell you what all the bits do but the flash bit is set to writeable and the code protect is disabled.
Flash memory works differently from normal RAM. In order to write to it you first need to erase the block you want to write. This sets all the bits in the block to 1. You can then use a program operation to change 1 bits to 0 bits. There is no write operation which sets the bits to 0 or 1, you have to combine these two operations to get the same effect.
Note that it is possible to perform a program operation without erasing first. It will still work in the sense that it will change 1 bits to 0 bits. However since it can't change already programmed 0 bits to 1 bits, you probably won't get the result you want.
One thing to watch out for is that the erase operation damages the flash memory, slowly wearing it out. The datasheet for your controller only lists a minimum of 1000 erase/write cycles before failure. That's more than sufficient for periodic firmware updates and configuration values, but might not be enough if you're using it to store frequently updated data.