This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

change IEEE MAC address of nrf51822

If I bought unique MAC address from IEEE. How can I update to nrf51822?

  • Most customers use only a Random Device Address, as a Public Device Address usually does not provide any benifits. That said, you can set the address using the sd_ble_gap_address_set() SoftDevice call. The first parameter should be set to BLE_GAP_ADDR_CYCLE_MODE_NONE and the second parameter is a pointer to a struct containing the address and address type, ble_gap_addr_t. Here the address type shall be BLE_GAP_ADDR_TYPE_PUBLIC.

    You will have to make this call every time you enable the SoftDevice. In practice this means once every boot-up. As you will use a different address for every device, you will probably want to write the address to a specific location in flash during production, and read the address from flash and use that with the call to sd_ble_gap_address_set().

  • I want to know how to do this too. I have searched other thread that it needs to call everytime in bootup. Is it correct? And which type of addreas should choose? And what is the difference between the two options which can be passed to the api for the first argument?

  • 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.

Related