13 Initiating a Page Erase

An individual page may be erased rather than erasing all of Flash memory. The PE is not used in this case.

PIC32MK family devices can perform an erase retry on a page by increasing the internal voltage used to perform the erase.

Table 13-1. Page Erase 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] = 0100, WR = 1 and WREN = 1, respectively. Registers s1 and s2 are set for the unlock data values and s0 is initialized to ‘0’.
34054004ori a1, $0,0x4004
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 5PIC32MK family devices only: Save the contents of NVMCON2.
8c9400a0lw s4,160(a0)
Step 6PIC32MK family devices only: Set the initial programming voltage level and enable page testing (unlock required).
36953000ori s5,s4,0x3000
32b5fcffandi s5,s5,0xFCFF
here3:
ac910010sw s1,16(a0)
ac920010sw s2,16(a0)
ac860008sw a2,8(a0)
ac9500a0sw s5,160(a0)
Step 7All the PIC32 devices: Set the NVMADDR register with the address of the Flash page to be erased.
3c08<ADDR>lui t0,<FLASH_PAGE_ADDR(31:16)>
3508<ADDR>ori t0,t0,<FLASH_PAGE_ADDR(15:0)>
ac880020sw t0,32(a0)
Step 8All the PIC32 devices: Poll the LVDSTAT register.
ac850000sw a1,0(a0)
delay (6 us)
Step 9PIC32MX devices only: Set up the NVMCON register for write operation.
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 14PIC32MK family devices only: Check that all data in the page has been erased. If not, adjust the voltage and try again. If all voltages levels have been tried, fail, and go to error procedure.
ac870004sw a3, 4(a0)
20171000addi s7, $0, 4096
00005020add t2, $0, $0
8c880020lw t0, 32(a0)
01194020add t0, t0, t9
here5:
8d090000lw t1, 0(t0)
15200005bne t1, $0, here6
214a0010addi t2, t2, 16
11570009beq t2, s7, here7
00000000nop
1000fffabeq $0, $0, here5
21080010addi t0, t0, 16
here6:
22b50100addi s5, s5, 256
32b60300andi s6, s5, 768
16c0ffdebne s6, $0, here3
00000000nop
10000005beq $0, $0, err_proc
00000000nop
Step 15PIC32MK family devices only: Restore the NVMCON2 register.
here7:
ac9400a0sw s4,160(a0)
Step 16All 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,t0,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);
    }