In case of MAX32660 it is not publicly documented, but in case of recently introduced MAX32690 It is documented in user guide (document UG7618; Rev 1) in section Debug Access Port (DAP). Later I googled some magic numbers from the provided algorithm and found that the algorithm is also documented for MAX32665/666 microcontrollers in user guide (document UG6971; Rev 3). Interestingly MCUs use slightly different magic constants and in case of MAX32690 there is also mistake becase Maxim attached wrong diagram. I tried to port algorithm to MAX32660 and it seems that works.
TLDR: Executing following code will lock MAX32660 (and MAX32690):
MXC_FLC0->ctrl = 0x20000000;
// magic values for unlocking FIB
MXC_FLC0->actrl = 0x3a7f5ca3;
MXC_FLC0->actrl = 0xa1e34f20;
MXC_FLC0->actrl = 0x9608b2c1;
// write address
MXC_FLC0->addr = 0x00040030;
// magic values to write (differs per lock/unlock/permlock) operations
MXC_FLC0->data[0] = 0x5A5AA5A5;
MXC_FLC0->data[1] = 0xDA5AA5A5;
MXC_FLC0->data[2] = 0xFFFFFFFF;
MXC_FLC0->data[3] = 0xFFFFFFFF;
MXC_FLC0->ctrl = 0x20000001;
while (MXC_FLC0->ctrl & MXC_F_FLC_CTRL_BUSY) {
// nop
}
MXC_FLC0->ctrl = 0;
MXC_FLC0->actrl = 0;
MCU locked in this way is single-time unlockable. Maxim MCU has two types of lock:
- Single-time unlockable: You can lock it onece, then unlock it once and then you can't use it anymore (at least documentation says that)
- Permanent lock: You can lock it once and then you can't unlock it anymore.
Locking basicaly works by writing to the one-time programmable area referred to as Flash Information Block (FIB). These area si documented and part of it is user-writable (see examples in MSDK: msdk/Examples/MAX32660/Info_Block_Usecase), but locks are in the Maxim-reserved area. In the same area there is unique id which is partially documented even in case of MAX32660 in user guide (document UG6659; Rev 1) in section Information Block Flash Memory.
In most Maxim MCUs FIB begins at address 0x10800000, but in case of MAX32660 it is at 0x00040000. Lock bits begins at offset 0x30. Documentation says that they are one-time programmable bits but practical experiments show that there is more complex logic and basically you can't write any value to them. It seems that invalid write attempts are ignored. Bits are readable after unlocking memory by magic (but documented) constants 0x3a7f5ca3, 0xa1e34f20, 0x9608b2c1. Interestingly magic values which are written to the FIB when locking MCU differs per MCU or at least documentation says that. Magic codes written to the FIB according MCU public documentation are following:
MAX32690:
- Single-time unlockable lock: 0x5A5AA5A5 0x5A5AA5A5 0xFFFFFFFF 0xFFFFFFFF !!!!
- Single-time unlockable unlock: 0x00000000 0xFFFFFFFF 0xFFFFFFFF 0x00000000
- Permanent lock: 0x5A5AA5A5 0x5A5AA5A5 0xFFFFFFFF 0xFFFFFFFF
MAX32665/666:
- Single-time unlockable lock: 0x5A5AA5A5 0x5A5AA5A5 0x5A5AA5A5 0xDA5AA5A5
- Single-time unlockable unlock: 0x00000000 0x00000000 0x00000000 0x00000000
- Permanent lock: 0x5A5AA5A5 0x5A5AA5A5 0x5A5AA5A5 0x5A5AA5A5
Note that values according to MAX32690 documentation codes for single-time unlockable and permanent lock are the same. This is mistake confirmed by Maxim Tech Support and in case of single-time unlockable lock second value should be 0xDA5AA5A5 instead of 0x5A5AA5A5.
I originally tried to lock MAX32660 using MAX32690 approach (which I found first), but it seems that more correct is MAX32665/666 approach. I made testing firmware which allows me to trigger lock procedures over UART and also allows me to execute memory operations. I locked it by writing 0x5A5AA5A5 0x5A5AA5A5 0xFFFFFFFF 0xFFFFFFFF and after power cycling I really lost access to debug port.
Then I tried it unlock it by MAX32690 procedure but it was unsuccessful. I tried writing 0x00000000 0xFFFFFFFF 0xFFFFFFFF 0x00000000 and interestingly some bytes changed, but not the written value and MCU remained locked. The new value in lock bits was 0x00000000 0xDA5AA5A5 0xFFFFFFFF 0x00000000 which is different value then I wrote to it, and it is also different value to value which was there at the beginning of this step.
So I tried unlocking procedure from different MCU. I tried writing all zeroes as MAX32665/666 documentation says, but because my MCU was locked I had to do it manually
and surprisingly MAX32660 unlocked. Permanent lock I did not tested. But it seems that procedure form MAX32665/666 is correct and may work with MAX32660 also.
References: