How can I read the UICR register of 9160?

The current project needs to save the ID in the programmable register and use the ID in the application image.

So I save the ID number in the URCI->OTP[0] register. When I read the ID in URCI->OTP[0] in the main function of the application image, a fatal error occurred.

uint32_t get_id_from_uicr(){
        uint32_t id;
        id = (NRF_UICR_S->OTP[0]);
        return id;
}

As far as I know, UICR can only be read in secure code.

So I execute this code in the main function of spm and get the ID normally. How can I pass the ID to the application image(not via flash)?

Or is there any other better way to store this ID?

spm.c:

uint32_t get_id_from_uicr(){
        uint32_t id;
        id = (NRF_UICR_S->OTP[0]);
        return id;
}

void main(void)
{
    uint32_t id;
    id = get_imei_from_uicr();
	spm_config();
	spm_jump();
}

  • There was a read function in the code I linked to as well.

    The current project needs to save the ID in the programmable register and use the ID in the application image.

    I'm not sure what kind of use-case this ID has, but a potential alterative would be to use the IMEI number instead. You can read it from the modem using a AT command: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/general/cgsn_set.html

  • Hi - the problem is that OTP memory must be read in 32 bit words. Simply adding the OTP memory to the `ranges` in spm_request_read_nse isn't enough - I used code like this:

    __TZ_NONSECURE_ENTRY_FUNC
    int spm_request_read_nse(void *destination, uint32_t addr, size_t len)
    {
    	static const struct read_range ranges[] = {
    
    #ifdef PM_MCUBOOT_ADDRESS
    		/* Allow reads of mcuboot metadata */
    		{.start = PM_MCUBOOT_PAD_ADDRESS,
    		 .size = PM_MCUBOOT_PAD_SIZE},
    #endif
    		{.start = FICR_INFO_ADDR,
    		 .size = FICR_INFO_SIZE},
    #if defined(FICR_NFC_TAGHEADER0_MFGID_Msk)
    		{.start = FICR_NFC_ADDR,
    		 .size = FICR_NFC_SIZE},
    #endif
    		{.start = FICR_RESTRICTED_ADDR,
    		 .size = FICR_RESTRICTED_SIZE},
    
            // Allow reading UICR
            {.start = NRF_UICR_S_BASE,
             .size = 4096},
    	};
    
    	if (destination == NULL || len <= 0) {
    		return -EINVAL;
    	}
    
    	if (ptr_in_secure_area((intptr_t)destination)) {
    		return -EINVAL;
    	}
    
    	for (size_t i = 0; i < ARRAY_SIZE(ranges); i++) {
    		uint32_t start = ranges[i].start;
    		uint32_t size = ranges[i].size;
    
    		if (addr >= start && addr + len <= start + size)
            {
                if ((addr & 3) == 0 && (len & 3) == 0)
                {
                    // use 32 bit copy
                    uint32_t *d = destination;
                    uint32_t *s = (uint32_t)addr;
                    while (len)
                    {
                        *d++ = *s++;
                        len -= 4;
                    }
                }
                else
                {
    			    memcpy(destination, (const void *)addr, len);
                }
    			return 0;
    		}
    	}
    
    	return -EPERM;
    }

Related