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.