OCOTP Support on IMX Processors — Details


#include <cyg/hal/hal_io.h>

cyg_bool success = cyg_imx_ocotp_timing( );

cyg_bool success = cyg_imx_ocotp_read( addr , p_value );

cyg_bool success = cyg_imx_ocotp_write( addr , value , key );

cyg_imx_ocotp_reload( );


The IMX HAL provides a number of functions to support interaction with the OCOTP (On-Chip One-Time-Programmable) fuses.

OCOTP Initialisation

Prior to accessing the OCOTP the function cyg_imx_ocotp_timing() should be used to configure the required timing setup. If the function returns false then an error has occurred and the OCOTP API should not be used.

OCOTP Reading

The addr is constructed using the CYGHWR_HAL_IMX_HW_OCOTP_ADDR(bank, word) macro to convert a bank# and word# into a register offset.

The passed p_value parameter is then filled with the OCOTP fuse value corresponding to the passed addr.

OCOTP Writing


Due to the fact that OCOTP updates can affect how the CPU operates from boot, the writing of fuses (setting from 0 to 1) is disabled by default.

If OCOTP write support is required then the CDL option CYGHWR_HAL_CORTEXM_IMX_OCOTP_WRITE should be explicitly enabled.

When the OCOTP write support is configured then the function cyg_imx_ocotp_write() can be used to set a specific value for the specified fuse location. The key parameter is an extra safety measure since the write will only be performed if key is CYGHWR_HAL_IMX_HW_OCOTP_WRITE_KEY. This is to minimise the chance for errant execution of the write function due to some application flaw resulting in erroneous OCOTP updates. The source code is constructed so that the 32-bit key value does not appear in the binary. Application users of the OCOTP write support should ideally implement similar functionality. e.g.

static const cyg_uint32 keyth = (0xDEAD0000 | (CYGHWR_HAL_IMX_HW_OCOTP_WRITE_KEY >> 16));
static const cyg_uint32 keybh = (0xC0DE0000 | (CYGHWR_HAL_IMX_HW_OCOTP_WRITE_KEY & 0xFFFF));

cyg_uint32 bitshigh;
cyg_uint32 bitslow;

HAL_READ_UINT32(&keyth, bitshigh);
HAL_READ_UINT32(&keybh, bitslow);

cyg_uint32 writekey = (((bitshigh & 0xFFFF) << 16) | (bitslow & 0xFFFF));

if (cyg_imx_ocotp_write(CYGHWR_HAL_IMX_HW_OCOTP_ADDR(bank, word), bitmask, writekey)) {
  // success // OCOTP updated
} else {
  // failure

After updating the fuses the cyg_imx_ocotp_reload() should be called to reload the shadow registers. This ensures other code, that may directly access the shadow state, will see the updated fuse state.