The sequence of events for programming an internal program memory location should be:
This procedure will require about 6 ms to update each write block of memory. An example of the required code is given in below.
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