PFM Word Write Sequence

The sequence of events for programming an erased single word of internal program memory location should be:

  1. 1.Set NVMADR with the target word address.
  2. 2.Load NVMDAT with desired word.
  3. 3.Disable interrupts.
  4. 4.Execute the word/byte write unlock sequence (see NVM Unlock Sequence).
  5. 5.WR bit is set as last step in the unlock sequence.
  6. 6.The CPU will stall for the duration of the write (about 50 μs using internal timer).
  7. 7.Re-enable interrupts.
  8. 8.Verify the memory (word read).

Writing a Word of Program Flash Memory

; Code sequence to program one erased word of PFM
; Target address is in WORD_ADDR_UPPER:WORD_ADDR_HIGH:WORD_ADDR_LOW
; Target data is in WORD_HIGH_BYTE:WORD_LOW_BYTE
; Calling routine should check WREG for the following errors:
;
;    00h = Successful modification
;    03h = Write error 
;
WORD_WRITE:
        MOVF    WORD_ADDR_UPPER, W  ; load NVMADR with the target
        MOVWF   NVMADRU             ; address of the word
        MOVF    WORD_ADDR_HIGH, W
        MOVWF   NVMADRH
        MOVF    WORD_ADDR_LOW, W
        MOVWF   NVMADRL
        MOVF    WORD_HIGH_BYTE, W   ; load NVMDAT with desired
        MOVWF   NVMDATH             ; word
        MOVF    WORD_LOW_BYTE, W
        MOVWF   NVMDATL
        BCF     INTCON, GIE         ; disable interrupts
        BSF     NVMCON0, NVMEN      ; enable NVM
PROGRAM_WORD:
; ----- Required Sequence -----       
        MOVLW   055h
        MOVWF   NVMCON2             ; first unlock byte = 055h
        MOVLW   0AAh
        MOVWF   NVMCON2             ; second unlock byte = 0AAh
        BSF     NVMCON1, WR         ; start word programming (CPU stall)
; ------------------------------        
        BTFSC   NVMCON0, NVMERR     ; Verify no error occurred during write
        BRA     NVM_WRERR           ; return sector write error code
VERIFY_WORD:
        BSF     NVMCON0, RD         ; Retrieve word from PFM
        MOVF    WORD_HIGH_BYTE, W   ; Verify high byte
        CPFSEQ  NVMDATH
        BRA     NVM_RDERR           ; not equal - return error code
        MOVF    WORD_LOW_BYTE, W    ; Verify low byte
        CPFSEQ  NVMDATL
        BRA     NVM_RDERR           ; not equal - return error code

        CLRF    WREG,F              ; return with no error
        BRA     NVM_EXIT
NVM_RDERR:
        MOVLW   01h
        BRA     NVM_EXIT
NVM_WRERR:
        MOVLW   03h
NVM_EXIT:
        BCF    NVMCON0, NVMEN       ; disable NVM
        BSF    INTCON, GIE          ; re-enable interrupts
        RETURN