10.3.4 Page Write
A page is written by first loading the buffer registers in the buffer RAM. All
buffer registers are then written to PFM by setting the NVMADR to an address
within the intended address range of the target PFM page, setting the NVMCMD
bits to ‘b101
, and then executing the unlock sequence and
setting the GO bit.
If the PFM address in the NVMADR is write-protected, or if NVMADR points to an invalid location, the GO bit is cleared without any effect, and the WRERR bit is set.
CPU operation is suspended during a page write cycle and resumes when the operation is complete. The page write operation completes in one extended instruction cycle. When complete, the GO bit is cleared by hardware and NVMIF is set. An interrupt will occur if NVMIE is also set. The buffer registers and NVMCMD bits are not changed throughout the write operation.
The internal programming timer controls the write time. The write/erase voltages are generated by an on-chip charge pump and rated to operate over the voltage range of the device.
0
’ to a ‘1
’. When
modifying individual bytes with a page write operation, it is necessary to
load all buffer registers with either 0xFF or the existing contents of
memory before executing a page write operation. The fastest way to do this
is by performing a page read operation.In this device a PFM page is 128 words (256 bytes). This is the same size as one bank of general purpose RAM (GPR). This area of GPR space is dedicated as a buffer area for NVM page operations. The buffer areas for each device in the family are shown in the following table:
Device | GPR Bank Number |
---|---|
PIC18Fx6Q20 | 21 |
PIC18Fx5Q20 | 13 |
PIC18Fx4Q20 | 9 |
- Using the
TBLRD
andTBLWT
instructions - Using the indirect FSR registers
- Direct read and writes to specific GPR locations
Neglecting the bank select bits, the 8 address bits of the GPR buffer space correspond to the 8 LSbs of each PFM page. In other words, there is a one-to-one correspondence between the NVMADRL register and the FSRxL register, where the x in FSRx is 0, 1 or 2.
The sequence of events for programming a page of PFM is:
- Set the NVMADR registers to an address within the intended page.
- Set the NVMCMD to
‘b110
(Erase Page). - Disable all interrupts.
- Perform the unlock sequence as described in the Unlock Sequence section.
- Set the GO bit to start the PFM page erase.
- Monitor the GO bit or NVMIF interrupt flag to determine when the erase has completed.
- Set NVMCMD to
‘b101
(Page Write). - Perform the unlock sequence.
- Set the GO bit to start the PFM page write.
- Monitor the GO bit or NVMIF interrupt flag to determine when the write has completed.
- Interrupts can be enabled after the GO bit is clear.
- Set the NVMCMD control
bits to
‘b000
.
Writing a Page of Program Flash Memory in C
// Code sequence to write a page of PFM // Input[] is the user data that needs to be written to PFM // PFM target address is specified by PAGE_ADDR #define PAGESIZE 128 // PFM page size // Save Interrupt Enable bit Value uint8_t GIEBitValue = INTCON0bits.GIE; // The BufferRAMStartAddr will be changed based on the device, refer // to the "Memory Organization" chapter for more details uint16_t bufferRAM __at(BufferRAMStartAddr); // Defining a pointer to the first location of the Buffer RAM uint16_t *bufferRamPtr = (uint16_t*) & bufferRAM; //Copy application buffer contents to the Buffer RAM for (uint8_t i = 0; i < PAGESIZE; i++) { *bufferRamPtr++ = Input[i]; } // Load NVMADR with the base address of the memory page NVMADR = PAGE_ADDR; NVMCON1bits.CMD = 0x06; // Set the page erase command INTCON0bits.GIE = 0; // Disable interrupts //––––––––– Required Unlock Sequence ––––––––– NVMLOCK = 0x55; NVMLOCK = 0xAA; NVMCON0bits.GO = 1; // Start page erase //––––––––––––––––––––––––––––––––––––––––––––– while (NVMCON0bits.GO); // Wait for the erase operation to complete // Verify erase operation success and call the recovery function if needed if (NVMCON1bits.WRERR){ ERASE_FAULT_RECOVERY(); } // NVMADR is already pointing to target page NVMCON1bits.CMD = 0x05; // Set the page write command //––––––––– Required Unlock Sequence ––––––––– NVMLOCK = 0x55; NVMLOCK = 0xAA; NVMCON0bits.GO = 1; // Start page write //––––––––––––––––––––––––––––––––––––––––––––– while (NVMCON0bits.GO); // Wait for the write operation to complete // Verify write operation success and call the recovery function if needed if (NVMCON1bits.WRERR){ WRITE_FAULT_RECOVERY(); } INTCON0bits.GIE = GIEBitValue; // Restore interrupt enable bit value NVMCON1bits.CMD = 0x00; // Disable writes to memory