Programming and reading OTP

I want to store some board info (serial number etc.) in OTP during board production. I managed to program OTP[189] trough J-Link commander. Now I want to read it back in the application.

My first attempt was to read the address:

reg = *((uint32_t *)0x00FF83FC);

This results in a bus fault. Reading trough earlier topics on this subject I suspect the OTP can only be read by secure code? All earlier topics mention the secure partition manager, which is now deprecated (using SDK 2.1.0).

I tried to convert to TF-M, using the following code:

static uint32_t secure_read_word(intptr_t ptr)
{
	uint32_t err = 0;
	uint32_t val;
	enum tfm_platform_err_t plt_err;

	plt_err = tfm_platform_mem_read(&val, ptr, 4, &err);
	if (plt_err != TFM_PLATFORM_ERR_SUCCESS || err != 0) {
		printk("tfm_..._mem_read failed: plt_err: 0x%x, err: 0x%x\n",
			plt_err, err);
		return -1;
	}

	return val;
}

uint32_t read_otp(void)
{
    uint32_t val = secure_read_word((intptr_t)&NRF_UICR_S->OTP[189]);// *((uint32_t *)0x00FF83FC);
    if(val == 0xFFFFFFFF)
    {
        return SERIAL_NUMBER_DEFAULT;
    }
    return val;
}

But this always gives the default serial, and the following line in the console:

tfm_..._mem_read failed: plt_err: 0x2, err: 0xffffffff

I guess I need to add the address to some whitelisted addresses that the non-secure code can read?

Parents Reply
  • I am using this method, still without success (result is same as from original post, error code = 2).

    The configuration file complains about prerequisites to  CONFIG_TFM_PARTITION_PLATFORM

    I have a system with nrf91, the modem core running modem stuff, mcuboot on the application core, and then the application image.  I need to access OTP in the application (for read only), but I don't know how to set it up so that it works.

    Alternate possibility is to create a separate block of flash that is reserved for configuration constants.  This would normally take 5 minutes to edit linker script, but with Zephyr everything is harder -- do you have a help page for how to get a reserved flash block in zephyr that gets into the linker script as a section?  For example, in order to do something like:

     const uint8_t serial_number[] __attribute__((section(".my_serial_number")))

Children
No Data
Related