Word-Write
long DataWord1;
long DataWord2;
long DataWord3;
long DataWord4;
long TargetWriteAddress;
NVMCONbits.NVMOP = 1;
NVMCONbits.WREN = 1;
NVMADR = TargetWriteAddress ;
NVMDATA0 = DataWord1;
NVMDATA1 = DataWord2;
NVMDATA2 = DataWord3;
NVMDATA3 = DataWord4;
NVMCONbits.WR = 1;
while (NVMCONbits.WR == 1);
CRC Checksum Calculation
long StartAddress;
long StartAddress;
long EndAddress;
int InitialValue;
int DelayValue;
int IdleValue;
NVMCRCCONbits.CRCIDL = IdleValue;
NVMCRCCONbits.DELAY = DelayValue;
NVMCRCCONbits.ON = 1;
NVMCRCST = StartAddress;
NVMCRCEND = EndAddress;
NVMCRCSEED = InitialValue;
NVMCRCCONbits.START = 1;
while(IFS0bits.NVMCRCIF == 0);
Partition Swap
// Note: The below function must be identical and be at identical addresses
on both partitions. Partition Swap is effective immediately, so GOTO W0 instruction executes
//from the just-swapped-to partition.
void _attribute((address(_PROGRAM_BASE), keep, naked, noinline))
SwapPartitions(void)
{
asm volatile("\n mov.sl #%0, w1"
"\n mov.l [w1], w1" // w1 = Inactive Partition FBTSEQ value
(first word of last row)
"\n mov.sl #0xC00000, w0"
"\n mov.l [w0], w0" // w0 = Inactive Partition reset vector
destination (__reset label on Inactive Partition)
"\n bootswp w1"
"\n goto w0"
: /* no outputs */ : "i"(0x400000ul | (__PROGRAM_BASE +
__PROGRAM_LENGTH - 0x10ul)) : "w0", "w1");
}