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

Change mac address before advertising (in on_ble_radio_active_evt call)

I am trying to change the mac address of my device every time I advertise a packet.  I have a callback on_ble_radio_active_evt where I update the address like this:

static void on_ble_radio_active_evt(bool radio_active)
{
    if (radio_active) {
        bd_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
        bd_addr.addr[0] = (uint8_t)NRF_FICR->DEVICEADDR[0];
        bd_addr.addr[1] = (uint8_t)(NRF_FICR->DEVICEADDR[0] >> 8);
        bd_addr.addr[2] = (uint8_t)(NRF_FICR->DEVICEADDR[0] >> 16) + count;
        bd_addr.addr[3] = (uint8_t)(NRF_FICR->DEVICEADDR[0] >> 24);
        bd_addr.addr[4] = (uint8_t)(NRF_FICR->DEVICEADDR[1]);
        bd_addr.addr[5] = (uint8_t)(NRF_FICR->DEVICEADDR[1] >> 8) | 0xc0;
        err_code = sd_ble_gap_addr_set(&bd_addr);
        
        // some custom data 
        append_advertisement_data(&advdata);
        
        err_code = ble_advdata_set(&advdata, NULL);
    }
}

but I get an error 8 ie NRF_ERROR_INVALID_STATE, which says Im not allowed to change the mac address in this state. How can I get around this error?

Parents
  • Hi!

    Do you know which funtion is returning the NRF_INVALID_STATE?
    Is it the sd_ble_gap_addr_set(&bd_addr)?

    If yes, I believe this root cause of this is the device is currently advertising, and you would need to stop the advertisement first.

    sd_ble_gap_addr_set():

    NRF_ERROR_INVALID_STATE - The identity address cannot be changed while advertising, scanning, or creating a connection.

    Best regards,
    Joakim

  • Hi Joakim,

    Should I call sd_ble_gap_adv_stop() in the radio notification event, update my bd address and advertising packet and then start advertising with sd_ble_gap_adv_start? If I use the stop api, it throws off my advertisement interval. I am using a non connectable advertisement interval of 3 seconds, but if I stop the advertisement, I think it starts defaulting to the smallest interval possible. I was able to get around this by using a timer of 3 seconds and the following logic.

    static void on_ble_radio_active_evt(bool radio_active)
        if (radio_active && adv_update) {
            adv_update = false;
            ret_code_t err_code;
            err_code = sd_ble_gap_adv_stop();
            APP_ERROR_CHECK(err_code);
            advertising_data_update(active);
            err_code = sd_ble_gap_adv_start(&m_adv_params, APP_BLE_CONN_CFG_TAG);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    static void adv_timeout_handler(void * p_context)
    {
        // every 3 seconds
        adv_update = true;
    
    }
    

    However I also have an initialization non connectable advert like this, whose timer value is actually not used:

    static void non_connectable_adv_init(void)
    {
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;
        m_adv_params.p_peer_addr = NULL;                               // Undirected advertisement
        m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval    = NON_CONNECTABLE_ADV_INTERVAL; // also 3 seconds
        m_adv_params.timeout     = 0;
    }
    

    So this implementation seems unclean, though it works. Is there a better way to do this?

  • That sounds strange.
    The sd_ble_gap_adv_start() function should start the advertisement using the defined advertising parameters. I don't see how using the timer should change that. 

    Which SDK/Softdevice are you using?

     

Reply Children
No Data
Related