6.4.5 NVMREG Write to Program Memory

Program memory is programmed using the following steps:
  1. Load the address of the row to be programmed into NVMADRH:NVMADRL.
  2. Load each write latch with data.
  3. Initiate a programming operation.
  4. Repeat steps 1 through 3 until all data is written.

Before writing to program memory, the word(s) to be written must be erased or previously unwritten. Program memory can only be erased one row at a time. No automatic erase occurs upon the initiation of the write.

Program memory can be written one or more words at a time. The maximum number of words written at one time is equal to the number of write latches. See Figure 6-4 for more details.

The write latches are aligned to the Flash row address boundary defined by the upper ten bits of NVMADRH:NVMADRL (NVMADRH[6:0]:NVMADRL[7:5]), with the lower five bits of NVMADRL (NVMADRL[4:0]) determining the write latch being loaded. Write operations do not cross these boundaries. At the completion of a program memory write operation, the data in the write latches is reset to contain 0x7FFF.

The following steps need to be completed to load the write latches and program a row of program memory. These steps are divided into two parts. First, each write latch is loaded with data from NVMDATH:NVMDATL using the unlock sequence with LWLO = 1. When the last word to be loaded into the write latch is ready, the LWLO bit is cleared and the unlock sequence executed. This initiates the programming operation, writing all the latches into Flash program memory.
Important: The special unlock sequence is required to load a write latch with data or initiate a Flash programming operation. If the unlock sequence is interrupted, writing to the latches or program memory will not be initiated.
  1. Set the WREN bit of the NVMCON1 register.
  2. Clear the NVMREGS bit of the NVMCON1 register.
  3. Set the LWLO bit of the NVMCON1 register. When the LWLO bit of the NVMCON1 register is ‘1’, the write sequence will only load the write latches and will not initiate the write to Flash program memory.
  4. Load the NVMADRH:NVMADRL register pair with the address of the location to be written.
  5. Load the NVMDATH:NVMDATL register pair with the program memory data to be written.
  6. Execute the unlock sequence. The write latch is now loaded.
  7. Increment the NVMADRH:NVMADRL register pair to point to the next location.
  8. Repeat steps 5 through 7 until all but the last write latch has been loaded.
  9. Clear the LWLO bit of the NVMCON1 register. When the LWLO bit of the NVMCON1 register is ‘0’, the write sequence will initiate the write to Flash program memory.
  10. Load the NVMDATH:NVMDATL register pair with the program memory data to be written.
  11. Execute the unlock sequence. The entire program memory latch content is now written to Flash program memory.
Important: The program memory write latches are reset to the Blank state (0x7FFF) at the completion of every write or erase operation. As a result, it is not necessary to load all the program memory write latches. Unloaded latches will remain in the Blank state.

An example of the complete write sequence is shown in Writing to Program Flash Memory. The initial address is loaded into the NVMADRH:NVMADRL register pair; the data is loaded using indirect addressing.

Figure 6-4. NVMREG Writes to Program Flash Memory with 32 Write Latches
Figure 6-5. Program Flash Memory Flowchart
Note:
  1. See Figure 6-2 for an example of the unlock sequence.

Writing to Program Flash Memory

   ; This write routine assumes the following:
   ; 1. 64 bytes of data are loaded, starting at 
   ; the address in DATA_ADDR
   ; 2. Each word of data to be written is made up of two adjacent 
   : bytes in DATA_ADDR,stored in little endian format
   ; 3. A valid starting address (the Least Significant bits = 00000)
   : is loaded in ADDRH:ADDRL
   ; 4. ADDRH and ADDRL are located in common RAM (locations 0x70-0x7F)
   ; 5. NVM interrupts are not taken into account
	
     BANKSEL    NVMADRH
     MOVF       ADDRH,W
     MOVWF      NVMADRH          ; Load initial address
     MOVF       ADDRL,W
     MOVWF      NVMADRL
     MOVLW      LOW DATA_ADDR    ; Load initial data address
     MOVWF      FSR0L
     MOVLW      HIGH DATA_ADDR
     MOVWF      FSR0H
     BCF        NVMCON1,NVMREGS  ; Set Program Flash as write location
     BSF        NVMCON1,WREN     ; Enable writes
     BSF        NVMCON1,LWLO     ; Load only write latches

   LOOP
     MOVIW      FSR0++
     MOVWF      NVMDATL          ; Load first data byte
     MOVIW      FSR0++
     MOVWF      NVMDATH          ; Load second data byte
     MOVF       NVMADRL,W
     XORLW      0x1F             ; Check if lower bits of address 
                                 ; are 00000
     ANDLW      0x1F             ; and if on last of 32 addresses
     BTFSC      STATUS,Z         ; Last of 32 words?
     GOTO       START_WRITE      ; If so, go write latches into memory
     CALL       UNLOCK_SEQ       ; If not, go load latch
     INCF       NVMADRL,F        ; Increment address
     GOTO       LOOP
		
   START_WRITE
     BCF        NVMCON1,LWLO     ; Latch writes complete, 
                                 ; Now write memory
     CALL       UNLOCK_SEQ       ; Perform required unlock sequence
     BCF        NVMCON1,WREN     ; Disable writes

   UNLOCK_SEQ
     MOVLW      55h
     BCF        INTCON,GIE       ; Disable interrupts
     MOVWF      NVMCON2          ; Begin unlock sequence
     MOVLW      AAh
     MOVWF      NVMCON2
     BSF        NVMCON1,WR
     BSF        INTCON,GIE       ; Re-enable interrupts
                                 ; Unlock sequence complete
     return