24.11 NVMKEY Register Unlocking Sequence

Important register settings that could compromise the Flash memory if inadvertently changed are protected by a register unlocking sequence. This feature is implemented using the NVMKEY register. The NVMKEY register is a write-only register that is used to implement an unlock sequence to help prevent accidental writes or erasures of Flash memory.

In some instances, the operation is also dependent on the setting of the WREN bit (NVMCON[14]), as shown in the following table.

Table 24-4. NVMKEY Register Unlocking and WREN
OperationWREN SettingUnlock Sequence Required
Changing value of NVMOP[3:0] (NVMCON[3:0])0No
Setting WR (NVMCON[15]) to start a write or erase operation1Yes
Changing any fields in the NVMPWP* registerYes
Changing any fields in the NVMLBWP registerYes

The following steps must be followed in the exact order as shown to enable writes to registers that require this unlock sequence:

  1. Write 0x00000000 to NVMKEY.
  2. Write 0xAA996655 to NVMKEY.
  3. Write 0x556699AA to NVMKEY.
  4. Write the value to the register NVMCON, NVMCON2, NVMPWP* or NVMLBWP requiring the unlock sequence.

When using the unlock sequence to set or clear bits in the NVMCON register, as shown in Step 4, Steps 2 through 4 must be executed without any other activity on the peripheral bus that is in use by the Flash Controller. Interrupts and DMA transfers that access the same peripheral bus as the Flash Controller must be disabled. In addition, the operation in Step 4 must be atomic. The Set, Clear and Invert registers may be used, where applicable, for the target register in Step 4.

The following code shows code written in the C language to initiate a NVM Operation (NVMOP) command. In this particular example, the WR bit is being set in the NVMCON register and, therefore, must include the unlock sequence.

Initiate NVM Operation (System Unlock Sequence Example):
void NVMInitiateOperation(void)
{ 
  // Disable Interrupts
  asm volatile(“di%0” : “=r”(int_status)); 
  uint32_t globalInterruptState= __get_PRIMASK();
// Disable Interrupts    
__disable_irq();
  NVMKEY = 0x0;
  NVMKEY = 0xAA996655; 
  NVMKEY = 0x556699AA; 
  NVMCONSET = 1 << 15;// must be an atomic instruction 
  
  // Restore Interrupts
  __set_PRIMASK(globalInterruptState);
}
Note: Once the unlock codes are written to the NVMKEY register, the next activity on the same peripheral bus as the Flash Controller will Reset the lock. As a result, only atomic operations can be used. Use of the NVMCONSET register sets the WR bit in a single instruction without changing other bits in the register. Using NVMCONbits.WR = 1 will fail, as this line of code compiles to a read-modify-write sequence.