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.