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.
Operation | WREN Setting | Unlock Sequence Required |
---|---|---|
Changing value of NVMOP[3:0] (NVMCON[3:0]) | 0 | No |
Setting WR (NVMCON[15]) to start a write or erase operation | 1 | Yes |
Changing any fields in the NVMPWP* register | — | Yes |
Changing any fields in the NVMLBWP register | — | Yes |
The following steps must be followed in the exact order as shown to enable writes to registers that require this unlock sequence:
- Write 0x00000000 to NVMKEY.
- Write 0xAA996655 to NVMKEY.
- Write 0x556699AA to NVMKEY.
- 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.
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);
}
1
will fail, as this line of code compiles to a
read-modify-write sequence.