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:
XferInstruction
(op code).
Repeat step 1 until the last
instruction is transferred to the CPU.
Table 14-1. Initiate Flash Row Write OP
Codes
Step Number
Op Code
Instruction
Step 1
All 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’.
34054003
ori a1, $0,0x4003
34068000
ori a2,$0,0x8000
34074000
ori a3,$0,0x4000
3c11aa99
lui s1,0xaa99
36316655
ori s1,s1,0x6655
3c125566
lui s2,0x5566
365299aa
ori s2,s2,0x99aa
3c100000
lui s0,0x0000
Step 2
PIC32MX family devices only: Set
register a0 to the base address of the NVM register
(0xBF80_F400).
3c04bf80
lui a0,0xbf80
3484f400
ori a0,a0,0xf400
Step 3
PIC32MK 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.
3c04b480
lui a0,0xbf80
34840600
ori a0,a0,0x0600
34138080
ori s3,$0,0x8080
Step 4
PIC32MK and PIC32MZ family devices
only: Unlock and disable boot Flash write protection.
ac910010
sw s1,16(a0)
ac920010
sw s2,16(a0)
ac930090
sw s3,144(a0)
00000000
nop
Step 5
All 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)>
ac880020
sw t0,32(a0)
Step 6
PIC32MX 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)>
ac900040
sw s0,64(a0)
Step 7
PIC32MK 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)>
ac900070
sw s0,112(a0)
Step 8
All the PIC32 devices: Set up the
NVMCON register for write operation.
ac850000
sw a1,0(a0)
—
delay (6 us)
Step 9
PIC32MX devices only: Poll the
LVDSTAT register.
—
here1:
8c880000
lw t0,0(a0)
31080800
andi t0,t0,0x0800
1500fffd
bne t0,$0,here1
00000000
nop
Step 10
All the PIC32 devices: Unlock the
NVMCON register and start the write operation.
ac910010
sw s1,16(a0)
ac920010
sw s2,16(a0)
ac860008
sw a2,8(a0)
Step 11
All the PIC32 devices: Loop until the
WR bit (NVMCON[15]) is clear.
—
here2:
8c880000
lw t0,0(a0)
01064024
and t0,t0,a2
1500fffd
bne t0,$0,here2
00000000
nop
Step 12
All 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).
00000000
nop
00000000
nop
00000000
nop
00000000
nop
Step 13
All the PIC32 devices: Clear the WREN
bit (NVMCON[14]).
ac870004
sw a3,4(a0)
Step 14
All 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.
8c880000
lw t0,0(a0)
30082000
andi t0,zero,0x2000
1500<ERR_PROC>
bne t0,$0,<err_proc_offset>
00000000
nop
Note:
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
{};
{
unsignedint start_count = _CP0_GET_COUNT();
unsignedint total_count = (.00000025 * SYSCLK); //count for 500 ns and CPU
frequency in MHz
while ((_CP0_GET_COUNT()- start_count) < total_count);
}