11.1.4.1 Program Flash Memory Write Sequence
The sequence of events for programming an internal program memory location must be:
- Read appropriate number of bytes into RAM. Refer to the memory organization table for Write latch size.
- Update data values in RAM as necessary.
- Load TBLPTR with address within the row to be erased.
- Execute the block erase procedure.
- Load TBLPTR with address of first byte being written.
- Write the n-byte block into the holding registers with auto-increment. Refer to the memory organization table for Write latch size.
- Set NVMREG bits to point to program memory.
- Clear FREE bit and set WREN bit register.
- Disable interrupts.
- Execute the unlock sequence (see 11.1.2 NVM Unlock Sequence).
- WR bit is set as last step in the unlock sequence.
- The CPU will stall for the duration of the write (about 2 ms using internal timer).
- Re-enable interrupts.
- 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.
![](GUID-F0F6A7AE-78E1-40F7-9790-2C4D4CD08673-low.png)
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