PFM Page Write Sequence

The sequence of events for programming a page of internal program memory are as follows:

  1. 1.Set the NVMADR registers with the target page address.
  2. 2.Read the PFM page into RAM with the Page Read operation. (This is required only for read-modify-write operations)
  3. 3.Execute the Page Erase operation (see PFM Erase Sequence). The GO bit is set as the last step in the erase sequence.
  4. 4.The CPU will stall for the duration of the erase (about 10 ms using the internal timer).
  5. 5.Load the TBLPTR registers with address of first byte being updated.
  6. 6.Write the n-byte modification into the buffer registers.
  7. 7.Disable interrupts.
  8. 8.Execute the Unlock sequence (see Unlock Sequence). The GO bit is set as last step in the unlock sequence.
  9. 9.The CPU will stall for the duration of the write (about 10 ms using internal timer).
  10. 10.Re-enable interrupts.
  11. 11.Verify the memory.

This procedure will require about 20 ms to update each page of memory. See the “Memory Programming Specifications” for more detail. An example of the required code is given below.

Important: Before executing the Page Write operation, the NVMADR value needs to be within the intended address range of the target PFM page.
Figure 1. Program Flash Memory (PFM) Write Flowchart

Writing a Page of Program Flash Memory

; Code sequence to modify one word in a programmed page of PFM
; Calling routine should check WREG for the following errors:
;
;    00h = Successful modification
;    01h = Read error
;    02h = Erase error
;    03h = Write error 
;
READ_PAGE:
; load NVMADR with the base address of the memory sector

        MOVLW   CODE_ADDR_HIGH
        MOVWF   NVMADRH
        MOVLW   CODE_ADDR_LOW
        MOVWF   NVMADRL
        BCF     INTCON0, GIE        ; disable interrupts
        MOVLW   0x02                ; page read command
        MOVWF   NVMCON1             ; set command
        BSF     NVMCON0, GO         ; start page read
        BTFSC   NVMCON1, WRERR      ; Verify no error occurred during read
        BRA     NVM_RDERR           ; return read error code
ERASE_PAGE:                         ; NVMADR is already pointing to target page
        MOVLW   0x06                ; Page Erase command
        MOVWF   NVMCON1             ; set command
; ----- Required Sequence -----       
        MOVLW   0x55
        MOVWF   NVMLOCK             ; first unlock byte = 0x55
        MOVLW   0xAA
        MOVWF   NVMLOCK             ; second unlock byte = 0xAA
        BSF     NVMCON0, GO         ; start page erase (CPU stall)
; ------------------------------        
        BTFSC   NVMCON1, WRERR      ; Verify no error occurred during erase
        BRA     NVM_ERERR           ; return erase error code
MODIFY_WORD:
        MOVLW   TARGET_ADDR_UPPER   ; load TBLPTR with the target address
        MOVWF   TBLPTRU             ; of the LSByte
        MOVLW   TARGET_ADDR_HIGH
        MOVWF   TBLPTRH
        MOVLW   TARGET_ADDR_LOW
        MOVWF   TBLPTRL
        MOVLW   NEW_DATA_LOW        ; update buffer register
        MOVWF   TABLAT
        TBLWT*+
        MOVLW   NEW_DATA_HIGH
        MOVWF   TABLAT
        TBLWT*+

PROGRAM_MEMORY:                     ; NVMADR is already pointing to target page
        MOVLW   0x05                ; page write command
        MOVWF   NVMCON1             ; set command
; ----- Required Sequence -----       
        MOVLW   0x55
        MOVWF   NVMLOCK             ; first unlock byte = 0x55
        MOVLW   0xAA
        MOVWF   NVMLOCK             ; second unlock byte = 0xAA
        BSF     NVMCON0, GO         ; start page write (CPU stall)
; ------------------------------        
        BTFSC   NVMCON1, WRERR      ; Verify no error occurred during write
        BRA     NVM_WRERR           ; return sector write error code
        CLRF    WREG,F              ; return with no error
        BRA     NVM_EXIT
NVM_RDERR:
        MOVLW   0x01
        BRA     NVM_EXIT
NVM_ERERR:
        MOVLW   0x02
        BRA     NVM_EXIT
NVM_WRERR:
        MOVLW   0x03
NVM_EXIT:
        CLRF   NVMCON1              ; disable NVM writes
        BSF    INTCON0, GIE         ; re-enable interrupts
        RETURN