14.2 Without the PE

Flash memory write operations are controlled by the NVMCON register. Programming is performed by setting the NVMCON register to select the type of write operation and initiating the programming sequence by setting the WR control bit (NVMCON[15]).
Figure 14-1. Initiating Flash Write without the PE

In the Flash write procedure (see Table 14-1), the Row Programming method is used to program the Flash memory, as it is typically the most expedient. word and Quad Word programming methods are also available, depending on the device, and may be used or required depending on your application. Refer to the “Flash Program Memory” chapter in the specific device data sheet and the related section of the “PIC32 Family Reference Manual” for more information.

The following steps are required to initiate a Flash write:
  1. XferInstruction (op code).
  2. Repeat step 1 until the last instruction is transferred to the CPU.
Table 14-1. Initiate Flash Row Write OP Codes
Step NumberOp CodeInstruction
Step 1All the PIC32 devices: Initialize constants. Registers a1, a2, and a3 are set for WREN = 1 or NVMOP[3:0] = 0011, WR = 1 and WREN = 1, respectively. Registers s1 and s2 are set for the unlock data values and s0 is initialized to ‘0’.
34054003ori a1, $0,0x4003
34068000ori a2,$0,0x8000
34074000ori a3,$0,0x4000
3c11aa99lui s1,0xaa99
36316655ori s1,s1,0x6655
3c125566lui s2,0x5566
365299aaori s2,s2,0x99aa
3c100000lui s0,0x0000
Step 2PIC32MX family devices only: Set register a0 to the base address of the NVM register (0xBF80_F400).
3c04bf80lui a0,0xbf80
3484f400ori a0,a0,0xf400
Step 3PIC32MK and PIC32MZ family devices only: Set register a0 to the base address of the NVM register (0xBF80_0600). Register s3 is set for the value used to disable write protection in NVMBPB.
3c04b480lui a0,0xbf80
34840600ori a0,a0,0x0600
34138080ori s3,$0,0x8080
Step 4PIC32MK and PIC32MZ family devices only: Unlock and disable boot Flash write protection.
ac910010sw s1,16(a0)
ac920010sw s2,16(a0)
ac930090sw s3,144(a0)
00000000nop
Step 5All the PIC32 devices: Set the NVMADDR register with the address of the Flash row to be programmed.
3c08<ADDR>lui t0,<FLASH_ROW_ADDR(31:16)>
3508<ADDR>ori t0,t0,<FLASH_ROW_ADDR(15:0)>
ac880020sw t0,32(a0)
Step 6PIC32MX devices only: Set the NVMSRCADDR register with the physical source SRAM address (offset is 64).
3c10<ADDR>lui s0, <RAM_ADDR(31:16)>
3610<ADDR>ori s0,s0,<RAM_ADDR(15:0)>
ac900040sw s0,64(a0)
Step 7PIC32MK and PIC32MZ family devices only: Set the NVMSRCADDR register with the physical source SRAM address (offset is 112).
3c10<ADDR>lui t0,<FLASH_PAGE_ADDR(31:16)>
3610<ADDR>ori s0,s0,<RAM_ADDR(15:0)>
ac900070sw s0,112(a0)
Step 8All the PIC32 devices: Set up the NVMCON register for write operation.
ac850000sw a1,0(a0)
delay (6 us)
Step 9PIC32MX devices only: Poll the LVDSTAT register.
here1:
8c880000lw t0,0(a0)
31080800andi t0,t0,0x0800
1500fffdbne t0,$0,here1
00000000nop
Step 10All the PIC32 devices: Unlock the NVMCON register and start the write operation.
ac910010sw s1,16(a0)
ac920010sw s2,16(a0)
ac860008sw a2,8(a0)
Step 11All the PIC32 devices: Loop until the WR bit (NVMCON[15]) is clear.
here2:
8c880000lw t0,0(a0)
01064024and t0,t0,a2
1500fffdbne t0,$0,here2
00000000nop
Step 12All the PIC32 devices: Wait at least 500 ns after the WR bit (NVMCON[15]) clears before writing to any of the NVM registers. This requires inserting a delay in the execution. The programming tools and program executive utilizes the FRC 8 MHz clock. Therefore four NOP instructions equate to 500 ns(1).
00000000nop
00000000nop
00000000nop
00000000nop
Step 13All the PIC32 devices: Clear the WREN bit (NVMCON[14]).
ac870004sw a3,4(a0)
Step 14All the PIC32 devices: Check the WRERR bit (NVMCON[13]) to ensure the successful completion of the program sequence. If an error occurs, jump to the error processing routine.
8c880000lw t0,0(a0)
30082000andi t0,zero,0x2000
1500<ERR_PROC>bne t0,$0,<err_proc_offset>
00000000nop
Note:
  1. For programming the Flash at runtime in the user’s application, the following code is recommended:
    while(NVMCON.WR) // waitfor WR bit(NVMCON[15]) to clear
    {};
    {
    unsigned int start_count = _CP0_GET_COUNT();
    unsigned int total_count = (.00000025 * SYSCLK); //count for 500 ns and CPU
    frequency in MHz
    while ((_CP0_GET_COUNT()- start_count) < total_count);
    }