4.3 OTPC Wrong Default Configuration
The default configuration of the OTPC cannot be used to access the OTP memory in Write mode.
Work Around
Prior to any write operation in the OTPC, the OTPC must be configured using the
following code. This operation needs to be performed only once before the first
write operation and whenever the peripheral reset (signal periph_nreset) is
asserted.
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/*
* writing one word lasts 350us
* the timeout was chosen to be enough for writing 10 words **/
#define TIMEOUT 500000
#define OTPC_0 (0x1u << 0)
#define OTPC_1 16
#define OTPC_2 (0xffffu << OTPC_1)
#define OTPC_3 (0x4391u << OTPC_1)
static void otp_sam9x60_fixup(void)
{
static const uint32_t fixup0[4] = {0x04194801, 0x01000000, 0x00000008, 0x00000000};
static const uint32_t fixup1[4] = {0xfb164801, 0x4c017d12, 0x02120e01, 0x00004000};
__IO uint32_t *OTPC_4 = (__IO uint32_t *)((uint8_t *)OTPC + 0x090);
__IO uint32_t *OTPC_5 = (__IO uint32_t *)((uint8_t *)OTPC + 0x0A0);
__IO uint32_t *OTPC_6 = (__IO uint32_t *)((uint8_t *)OTPC + 0x0B0);
uint32_t timeout;
int i;
timeout = TIMEOUT;
*OTPC_4 = OTPC_0 | OTPC_3;
while (!(OTPC->OTPC_SR & OTPC_SR_UNLOCK) && --timeout > 0);
for (i = 0; i < ARRAY_SIZE(fixup0); i++)
OTPC_5[i] = fixup0[i];
for (i = 0; i < ARRAY_SIZE(fixup1); i++)
OTPC_6[i] = fixup1[i];
timeout = TIMEOUT;
*OTPC_4 = OTPC_3;
while ((OTPC->OTPC_SR & OTPC_SR_UNLOCK) && --timeout > 0); }
Affected Silicon Revisions
A0 | A1 | ||||||
X | X |