10.4.2 Writing to DFM

To write a DFM location, the address must first be written to the NVMADR register, the data written to the NVMDATL register, and the Write operation command set in the NVMCMD bits. The sequence shown in Unlock Sequence must be followed to initiate the write cycle. Multibyte Page writes are not supported for the DFM.

The write will not begin if the NVM unlock sequence is not exactly followed for each byte. It is strongly recommended to disable interrupts during this code segment.

When not actively writing to the DFM, the NVMCMD bits need to be kept clear at all times as an extra precaution against accidental writes. The NVMCMD bits are not cleared by hardware.

After a write sequence has been initiated, NVMCON0, NVMCON1, NVMADR and NVMDAT cannot be modified.

Each DFM write operation includes an implicit erase cycle for that byte. CPU execution continues in parallel and at the completion of the write cycle, the GO bit is cleared in hardware and the NVM Interrupt Flag (NVMIF) bit is set. The user can either enable the interrupt or poll the bit. NVMIF must be cleared by software.

The sequence of events for programming one byte of DFM is:

  1. Set NVMADR registers with the target byte address.
  2. Load NVMDATL register with desired byte.
  3. Set the NVMCMD control bits to ‘b011 (Byte Write).
  4. Disable all interrupts.
  5. Perform the unlock sequence as described in the Unlock Sequence section.
  6. Set the GO bit to start the DFM byte write.
  7. Interrupts can be enabled after the GO bit is set. If it is not desired to have interrupts during DFM write, then enable interrupts after the next step when the GO bit is cleared.
  8. Monitor the GO bit or NVMIF interrupt flag to determine when the write has been completed.
  9. Set the NVMCMD control bits to ‘b000.

Writing a Byte to Data Flash Memory in C

// Code sequence to write one byte to a DFM
// DFM target address is specified by DFM_ADDR
// Target data are specified by ByteValue

// Save interrupt enable bit value
uint8_t GIEBitValue = INTCON0bits.GIE;

// Load NVMADR with the target address of the byte
NVMADR = DFM_ADDR;              
NVMDATL = ByteValue;               // Load NVMDAT with the desired value
NVMCON1bits.CMD = 0x03;            // Set the byte write command
INTCON0bits.GIE = 0;               // Disable interrupts
//––––––––– Required Unlock Sequence ––––––––– 
NVMLOCK = 0x55;
NVMLOCK = 0xAA;
NVMCON0bits.GO = 1;                // Start byte write
//–––––––––––––––––––––––––––––––––––––––––––––––
INTCON0bits.GIE = GIEBitValue;     // Restore interrupt enable bit value (if interrupts are desired during DFM write)
while (NVMCON0bits.GO);            // Wait for the write operation to complete

// Verify byte write operation success and call the recovery function if needed
if (NVMCON1bits.WRERR){            
   WRITE_FAULT_RECOVERY();
}

NVMCON1bits.CMD = 0;               // Disable writes to memory