If I bought unique MAC address from IEEE. How can I update to nrf51822?
If I bought unique MAC address from IEEE. How can I update to nrf51822?
Hi Fiske and Jones,
This answer expands a bit on Einar's answer to give you an idea of what I do for our product.
In our factory, we program the MAC address we want to use to the UICR using our JLink script. This way it is only erased if the entire part is erased which shouldn't happen during production. If you want to use a Public Static Address, then you need to buy a block of MAC addresses from IEEE.
Next, what we do is during boot, I check the UICR to see if it contains a MAC address (essentially, check that it is not FFFFFFFFFFFF or 000000000000. I read the data out of that UICR into the ble_gap_addr_t structure and then set it as a BLE_GAP_ADDR_TYPE_PUBLIC. Here is a code snippet:
/* Get the stored MAC address, little-endian (LSB first). Returns
true if it came from the UICR, or false if it came from the
FICR. */
bool get_mac_le(uint8_t *buf)
{
bool uicr = true;
const uint8_t *mac = MAC_UICR_ADDR;
if (all_equal(mac, 0x00, 6) || all_equal(mac, 0xff, 6))
{
mac = (const uint8_t *)&(NRF_FICR->DEVICEADDR[0]);
uicr = false;
}
memcpy(buf, mac, 6);
/* If we pulled a random address from the FICR, the top
two bits must be 11 per BT spec */
if (uicr == false)
buf[5] |= 0xc0;
return uicr;
}
Then I do the following elsewhere when booting up:
//set the mac
ble_gap_addr_t addr;
if(get_mac_le(addr.addr))
{
addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
}
else
{
addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
}
err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr);
APP_ERROR_CHECK(err_code);
Note that as I said earlier, this method is not protected from having the MAC address erased. There is no way to safely store a MAC on the nRF51. Our programming script reads out this location to see if there is a current MAC and writes it back later if there is one.
Hope this helps,
Eric
Hi Fiske and Jones,
This answer expands a bit on Einar's answer to give you an idea of what I do for our product.
In our factory, we program the MAC address we want to use to the UICR using our JLink script. This way it is only erased if the entire part is erased which shouldn't happen during production. If you want to use a Public Static Address, then you need to buy a block of MAC addresses from IEEE.
Next, what we do is during boot, I check the UICR to see if it contains a MAC address (essentially, check that it is not FFFFFFFFFFFF or 000000000000. I read the data out of that UICR into the ble_gap_addr_t structure and then set it as a BLE_GAP_ADDR_TYPE_PUBLIC. Here is a code snippet:
/* Get the stored MAC address, little-endian (LSB first). Returns
true if it came from the UICR, or false if it came from the
FICR. */
bool get_mac_le(uint8_t *buf)
{
bool uicr = true;
const uint8_t *mac = MAC_UICR_ADDR;
if (all_equal(mac, 0x00, 6) || all_equal(mac, 0xff, 6))
{
mac = (const uint8_t *)&(NRF_FICR->DEVICEADDR[0]);
uicr = false;
}
memcpy(buf, mac, 6);
/* If we pulled a random address from the FICR, the top
two bits must be 11 per BT spec */
if (uicr == false)
buf[5] |= 0xc0;
return uicr;
}
Then I do the following elsewhere when booting up:
//set the mac
ble_gap_addr_t addr;
if(get_mac_le(addr.addr))
{
addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
}
else
{
addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
}
err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr);
APP_ERROR_CHECK(err_code);
Note that as I said earlier, this method is not protected from having the MAC address erased. There is no way to safely store a MAC on the nRF51. Our programming script reads out this location to see if there is a current MAC and writes it back later if there is one.
Hope this helps,
Eric
Hi Eric,
Thank you very much of your comment. I can now change the public mac address of the nrf51 chip. Since we need the chip to remember the saved mac address, I write the mac address I want the chip to have in the last page of the flash. Is it appropriate? Also, I figure out that if I call the flash write routine after initializing any softdevice or ble stack, I will get a hardfault. What is it about?
Jones
You can write it to flash, but flash could potentially be erased at any time. The reason we put it in the UICR is because it can only be erased with a full chip erase. This mean physical hardware access is needed to execute a full chip erase through the debugging interface.
I suspect the hard fault is occurring because flash operations block the CPU on the nRF51. Since the SoftDevice needs fine grained timing access, you'll need to use the sd_flash_* functions to read and write to the flash when the SoftDevice is running. These functions use callbacks to inform your application that a flash operation finished. For an example, check out the Nordic library pstorage. It's probably a bit overkill for your needs, but it will give you an example of how to use the functions.
Note that sd_flash_* functions cannot write to the UICR. You must write with the SoftDevice disabled.