12.1.4.1 PFM Sector Write Sequence
The sequence of events for programming a block of internal program memory location should be:
- Set NVMADR with the target sector address.
- Read the PFM sector into RAM with the SECRD operation.
- Execute the sector erase procedure (see 12.1.3.1 PFM Erase Sequence).
- SECER is set as the last step in the erase sequence.
- The CPU will stall for the duration of the erase (about 10 ms using internal timer).
- Load TBLPTR with address of first byte being updated.
- Write the n-byte block into the holding registers with auto-increment. Refer to the Flash memory organization by device table for the number of holding registers.
- Disable interrupts.
- Execute the sector write unlock sequence (see 12.1.2 NVM Unlock Sequence).
- SECWR bit is set as last step in the unlock sequence.
- The CPU will stall for the duration of the write (about 10 ms using internal timer).
- Re-enable interrupts.
- Verify the memory (table read).
This procedure will require about 20 ms to update each block of memory. See the "Memory Programming Specifications" for more details. An example of the required code is given below.
Important: Before setting the SECWR
bit, the NVMADR value needs to be within the intended address range of the target PFM
sector.
Writing a Sector of Program Flash Memory
; Code sequence to modify one word in a programmed sector of PFM
; Calling routine should check WREG for the following errors:
;
; 00h = Successful modification
; 01h = Read error
; 02h = Erase error
; 03h = Write error
;
READ_BLOCK:
MOVLW CODE_ADDR_UPPER ; load NVMADR with the base
MOVWF NVMADRU ; address of the memory sector
MOVLW CODE_ADDR_HIGH
MOVWF NVMADRH
MOVLW CODE_ADDR_LOW
MOVWF NVMADRL
BCF INTCON, GIE ; disable interrupts
BSF NVMCON0, NVMEN ; enable NVM
; ----- Required Sequence -----
MOVLW 0BBh
MOVWF NVMCON2 ; first unlock byte = 0BBh
MOVLW 44h
MOVWF NVMCON2 ; second unlock byte = 44h
BSF NVMCON1, SECRD ; start sector read (CPU stall)
; ------------------------------
BTFSC NVMCON0, NVMERR ; Verify no error occurred during read
BRA NVM_RDERR ; return read error code
ERASE_BLOCK: ; NVMADR is already pointing to target block
; ----- Required Sequence -----
MOVLW 0CCh
MOVWF NVMCON2 ; first unlock byte = 0CCh
MOVLW 33h
MOVWF NVMCON2 ; second unlock byte = 33h
BSF NVMCON1, SECER ; start sector erase (CPU stall)
; ------------------------------
BTFSC NVMCON0, NVMERR ; 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 holding register
MOVWF TABLAT
TBLWT*+
MOVLW NEW_DATA_HIGH
MOVWF TABLAT
TBLWT*+
PROGRAM_MEMORY: ; NVMADR is already pointing to target block
; ----- Required Sequence -----
MOVLW 0DDh
MOVWF NVMCON2 ; first unlock byte = 0DDh
MOVLW 22h
MOVWF NVMCON2 ; second unlock byte = 22h
BSF NVMCON1, SECWR ; start sector programming (CPU stall)
; ------------------------------
BTFSC NVMCON0, NVMERR ; 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 01h
BRA NVM_EXIT
NVM_ERERR:
MOVLW 02h
BRA NVM_EXIT
NVM_WRERR:
MOVLW 03h
NVM_EXIT:
BCF NVMCON0, NVMEN ; disable NVM
BSF INTCON, GIE ; re-enable interrupts
RETURN