Search code examples
cbootloadermicrochipmplabpic32

Pic32 bootloader writing to memory


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.


Solution

  • 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.