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

A0A1
XX