12.1.4.1 Program Flash Memory Write Sequence

The sequence of events for programming an internal program memory location must be:

  1. Read appropriate number of bytes into RAM. Refer to the memory organization table for Write latch size.
  2. Update data values in RAM as necessary.
  3. Load TBLPTR with address within the row to be erased.
  4. Execute the block erase procedure.
  5. Load TBLPTR with address of first byte being written.
  6. Write the n-byte block into the holding registers with auto-increment. Refer to the memory organization table for Write latch size.
  7. Set NVMREG bits to point to program memory.
  8. Clear FREE bit and set WREN bit register.
  9. Disable interrupts.
  10. Execute the unlock sequence (see NVM Unlock Sequence).
  11. WR bit is set as last step in the unlock sequence.
  12. The CPU will stall for the duration of the write (about 2 ms using internal timer).
  13. Re-enable interrupts.
  14. Verify the memory (table read).

This procedure will require about 6 ms to update each write block of memory. An example of the required code is given in below.

Important: Before setting the WR bit, the Table Pointer address needs to be within the intended address range of the bytes in the holding registers.
Figure 12-9. Program Flash Memory (PFM) Write Flowchart

Writing to Program Flash Memory

        MOVLW   D'64’                   ; number of bytes in erase block
        MOVWF   COUNTER
        MOVLW   BUFFER_ADDR_HIGH        ; point to buffer
        MOVWF   FSR0H
        MOVLW   BUFFER_ADDR_LOW
        MOVWF   FSR0L
        MOVLW   CODE_ADDR_UPPER         ; Load TBLPTR with the base
        MOVWF   TBLPTRU                 ; address of the memory block
        MOVLW   CODE_ADDR_HIGH
        MOVWF   TBLPTRH
        MOVLW   CODE_ADDR_LOW
        MOVWF   TBLPTRL
READ_BLOCK:
        TBLRD*+                         ; read into TABLAT, and inc
        MOVF    TABLAT, W               ; get data
        MOVWF   POSTINC0                ; store data
        DECFSZ  COUNTER                 ; done?
        BRA     READ_BLOCK              ; repeat
MODIFY_WORD:
        MOVLW   BUFFER_ADDR_HIGH        ; point to buffer
        MOVWF   FSR0H
        MOVLW   BUFFER_ADDR_LOW
        MOVWF   FSR0L
        MOVLW   NEW_DATA_LOW            ; update buffer word
        MOVWF   POSTINC0
        MOVLW   NEW_DATA_HIGH
        MOVWF   INDF0
ERASE_BLOCK:
        MOVLW   CODE_ADDR_UPPER         ; load TBLPTR with the base
        MOVWF   TBLPTRU                 ; address of the memory block
        MOVLW   CODE_ADDR_HIGH
        MOVWF   TBLPTRH
        MOVLW   CODE_ADDR_LOW
        MOVWF   TBLPTRL
        BCF     NVMCON1, NVMREG0        ; point to Program Flash Memory
        BSF     NVMCON1, NVMREG1        ; point to Program Flash Memory
        BSF     NVMCON1, WREN           ; enable write to memory
        BSF     NVMCON1, FREE           ; enable Erase operation
        BCF     INTCON, GIE             ; disable interrupts
; ----- Required Sequence -----       
        MOVLW   55h
        MOVWF   NVMCON2                 ; write 55h
        MOVLW   AAh
        MOVWF   NVMCON2                 ; write 0AAh
        BSF     NVMCON1, WR             ; start erase (CPU stall)
; ------------------------------        
        BSF     INTCON, GIE             ; re-enable interrupts
        TBLRD*-                         ; dummy read decrement
        MOVLW   BUFFER_ADDR_HIGH        ; point to buffer
        MOVWF   FSR0H
        MOVLW   BUFFER_ADDR_LOW
        MOVWF   FSR0L
        WRITE_  BUFFER_BACK
        MOVLW   BlockSize               ; number of bytes in holding register
        MOVWF   COUNTER
        MOVLW   D’64’/BlockSize          ; number of write blocks in 64 bytes
        MOVWF   COUNTER2
WRITE_BYTE_TO_HREGS:
        MOVF    POSTINC0, W             ; get low byte of buffer data
        MOVWF   TABLAT                  ; present data to table latch
        TBLWT+*                         ; write data, perform a short write
                                        ; to internal TBLWT holding register.
        DECFSZ  COUNTER                 ; loop until holding registers are full
        BRA     WRITE_WORD_TO_HREGS
PROGRAM_MEMORY:
        BCF     NVMCON1, NVMREG0        ; point to Program Flash Memory
        BSF     NVMCON1, NVMREG1        ; point to Program Flash Memory
        BSF     NVMCON1, WREN           ; enable write to memory
        BCF     NVMCON1, FREE           ; enable write to memory
        BCF     INTCON, GIE             ; disable interrupts
; ----- Required Sequence -----       
        MOVLW   55h
        MOVWF   NVMCON2                 ; write 55h
        MOVLW   0AAh
        MOVWF   NVMCON2                 ; write 0AAh
        BSF     NVMCON1, WR             ; start program (CPU stall)
; ------------------------------        
        DCFSZ   COUNTER2                ; repeat for remaining write blocks
        BRA     WRITE_BYTE_TO_HREGS
        BSF     INTCON, GIE             ; re-enable interrupts
        BCF     NVMCON1, WREN           ; disable write to memory