Hi
Below is the code that I use which you may be able to reverse engineer to your environment. It is from the uTasker project so uses different headers and formatted output commands.
If you just want to read the values on your board you can simply load the iHex from here to do it https://www.utasker.com/iMX/Teensy_4_1.html - just command "eFUSE" in the Administrator menu (menu 4) to get it to print them out over the USB
Code:
{
int i;
volatile unsigned long *ptrRegister = HW_OCOTP_CFG0_ADD;
POWER_UP_ATOMIC(2, OCOTP_CTRL_CLOCK);
fnDebugMsg("eFUSEs\r\n======\r\nLOCK\r\n");
fnDebugHex(HW_OCOTP_LOCK, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugMsg("CFG\r\n");
i = 7;
while (i-- != 0) {
fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
ptrRegister += 4;
}
fnDebugMsg("MEM\r\n");
ptrRegister = HW_OCOTP_MEM0_ADD;
i = 5;
while (i-- != 0) {
fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
ptrRegister += 4;
}
fnDebugMsg("ANALOG\r\n");
ptrRegister = HW_OCOTP_ANA0_ADD;
i = 3;
while (i-- != 0) {
fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
ptrRegister += 4;
}
fnDebugMsg("SRK\r\n");
ptrRegister = HW_OCOTP_SRK0_ADD;
i = 8;
while (i-- != 0) {
fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
ptrRegister += 4;
}
fnDebugMsg("SJC\r\n");
fnDebugHex(HW_OCOTP_SJC_RESP0, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugHex(HW_OCOTP_SJC_RESP1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugMsg("MAC");
if ((HW_OCOTP_LOCK & eFUSE_LOCK_MAC_ADDR_LOCK_MASK) != 0) {
fnDebugMsg(" (locked)\r\n");
}
else {
fnDebugMsg("\r\n");
}
fnDebugHex(HW_OCOTP_MAC0, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugHex(HW_OCOTP_MAC1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
#if defined HW_OCOTP_MAC2
fnDebugHex(HW_OCOTP_MAC2, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugMsg("GP\r\n");
#else
fnDebugMsg("GP\r\n");
fnDebugHex(HW_OCOTP_GP3, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
#endif
fnDebugHex(HW_OCOTP_GP1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugHex(HW_OCOTP_GP2, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugMsg("SW GP\r\n");
ptrRegister = HW_OCOTP_SW_GP1_ADD;
i = 5;
while (i-- != 0) {
fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
ptrRegister += 4;
}
fnDebugMsg("MISC\r\n");
fnDebugHex(HW_OCOTP_MISC_CONF0, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugHex(HW_OCOTP_MISC_CONF1, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
fnDebugMsg("REVOKE\r\n");
fnDebugHex(HW_OCOTP_SRK_REVOKE, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
#if defined HW_OCOTP_ROM_PATCH0
fnDebugMsg("PATCH\r\n");
ptrRegister = HW_OCOTP_ROM_PATCH0_ADD;
i = 8;
while (i-- != 0) {
fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
ptrRegister += 4;
}
fnDebugMsg("GP3\r\n");
ptrRegister = HW_OCOTP_GP30_ADD;
i = 8;
while (i-- != 0) {
fnDebugHex(*ptrRegister, (WITH_SPACE | WITH_LEADIN | WITH_CR_LF | sizeof(unsigned long)));
ptrRegister += 4;
}
POWER_DOWN_ATOMIC(2, OCOTP_CTRL_CLOCK);
#endif
}
Note that the uTasker project simulates the i.MX RT 1062 and the Teensy board as well as the eFUSEs - I have a video showing the simulation of this and the security module in the chip (allowing XiP on-the-fly decryption to be used on the Teensy 4.1 too - without actually needing to program the eFUSEs): https://youtu.be/o7hQbOqhJoc
Regards
Mark