nRF5340 - Cannot read UICR.OTP in relase mode

Hi,
in order to reuse the original factory public Bluetooth MAC of nRF5340 based radio module, I had introduced a function that reads the MAC address out of UICR.OTP area of the Flash, and sends it to the network core after a quick validation.

int ble_init(void)
{
    bt_addr_t addr;

    bt_enable(NULL);

    if (ble_uicr_btaddr_is_public(&addr)) {
        LOG_INF("setting public address");
        ble_set_mac(&addr);
    } else {
        LOG_INF("setting random static address");
    }
..
}

where

/**@brief Check out Bluetooth address stored in UICR is valid public
* This function reads the 3 MSB out of UICR stored address and, if a valid OUI,
* send it to the network core, otherwise a static random address is used.
* @param addr MAC address object
* @retval 1(0) if the address is (is not) valid public
*/
static int ble_uicr_btaddr_is_public(bt_addr_t* addr)
{
    /* this list can grow over time */
    uint32_t OUI[9] = {0xf31200, 0x36ba20, 0xde6454, 0x2af854, \
        0xc30960, 0xeb1d6c, 0x4ff4b8, 0x57f9cc, 0x6ecad4};

    for (int i=0; i < 9; i++) {
        /* check for public address in UICR.OPT area */
        if ((NRF_UICR->OTP[0] & 0x00ffffff) == OUI[i]) {
            uint8_t tmp[BT_ADDR_SIZE];
            memcpy(&tmp[0], (uint8_t *)&NRF_UICR->OTP[0], BT_ADDR_SIZE);
            for (int k=0; k < BT_ADDR_SIZE; k++) {
                addr->val[k] = tmp[BT_ADDR_SIZE - k -1];
                printk("addr->val[%d] = 0x%02x\n", k, addr->val[k]);
            }
            return 1;
        }
    }
    return 0;
}


This solution works fine only if I build in debug mode, whereas in release mode (with secure boot features and the like), it always returns the address AD:DE:AD:DE:AD:DE.
For some reason I cannot read UICR.OTP programmatically at runtime in release mode.
I'm working with NCS v2.6.1.

Parents
  • Hi Gabriele,

    The Nordic Secure Immutable Bootloader uses the Hardware unique key library, which in turn uses the nRF5340's KMU — Key management unit to limit the access to a part of the UICR. The OTP registers that you want to use is one of the registers with access restricted.

    To read the OTP, you need to use the Hardware Unique Key library's API. You can refer to its sample: https://docs.nordicsemi.com/bundle/ncs-2.6.1/page/nrf/samples/keys/hw_unique_key/README.html.

    Hieu

  • It seems very complicated stuff. Can you guide me with some concrete coding sample ? Alternatively, can I remove the access restriction to UICR ? Or, is there a non-protected register where I can copy the bluetooth address, in such a way I can read it at runtime without any restriction ?

    I have a bash script on host, used for the first device programming.
    It does the following

    1) Retrieve and save in a local variable the factory MAC from device, using
        uicrotp="$(nrfjprog -f nrf53 --memrd 0x00FF8100 --n 8)"
    2) Erase and program device with application
    3) Restore the original bluetooth address into device from the local variable, using
        nrfjprog -f nrf53 --memwr 0x00FF8104 --${uicrotp:21:8} 0x
        nrfjprog -f nrf53 --memwr 0x00FF8100 --${uicrotp:12:8} 0x

    Is there any 8-bytes flash area, other than 0x00FF8100, where I can copy the MAC address, which is easily readable at runtime, without any restriction ? Maybe a different UICR register ?

Reply
  • It seems very complicated stuff. Can you guide me with some concrete coding sample ? Alternatively, can I remove the access restriction to UICR ? Or, is there a non-protected register where I can copy the bluetooth address, in such a way I can read it at runtime without any restriction ?

    I have a bash script on host, used for the first device programming.
    It does the following

    1) Retrieve and save in a local variable the factory MAC from device, using
        uicrotp="$(nrfjprog -f nrf53 --memrd 0x00FF8100 --n 8)"
    2) Erase and program device with application
    3) Restore the original bluetooth address into device from the local variable, using
        nrfjprog -f nrf53 --memwr 0x00FF8104 --${uicrotp:21:8} 0x
        nrfjprog -f nrf53 --memwr 0x00FF8100 --${uicrotp:12:8} 0x

    Is there any 8-bytes flash area, other than 0x00FF8100, where I can copy the MAC address, which is easily readable at runtime, without any restriction ? Maybe a different UICR register ?

Children
Related