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

Incomplete data advertised while changing the advertising data during advertising

Hi,

I have been trying to advertise packets with different manufacturer data and I am able to achieve that using the radio_notification_handler of the SDK. In my code, I have initialized the manufacturer data in the ble_advertising_init() function with around 10 bytes of data and if I don't change the data during advertising, I am able to receive them successfully. But, if I do change the data(the new data is also around 10 bytes) during advertising, I don't know why it gets stripped to 4 bytes of data. The data is changed using the ble_advdata_set() function call in the radio notification handler. I am working with SDK 14.2 and Softdevice 132. Can anyone tell me why this is happening? I know that we are only allowed 31 bytes of data, but the successful reception of 10 bytes initially, tells me that the size of the packet is not the issue here.

Thank You.   

  • Hi,

    Can you share the parts of code that are involved in setting up the initial advertising data, as well as the code involved in setting up the changed advertising data, for me (and others) to have a look at?

    Regards,
    Terje

  • Sure.

    Here is the advertising_init() function:-

    static void advertising_init(void)
    {
        ret_code_t             err_code;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
     
    
        ble_advdata_manuf_data_t manuf_data;
        uint8_t data[]                      = "ABCDEFGHIJ"; // Our data to advertise
        manuf_data.company_identifier       = 0xFFFF; // Unregistered company
        manuf_data.data.p_data              = data;     
        manuf_data.data.size                = sizeof(data);
    
        
    
        init.advdata.name_type               = BLE_ADVDATA_SHORT_NAME;
        init.advdata.short_name_len          = 6;
        init.advdata.include_appearance      = false;
        init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        init.advdata.p_manuf_specific_data   = &manuf_data;
        
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_TIMEOUT_IN_SECONDS;
    
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    

    and Interrupt handler function which changes the advertisement data using ble_advdata_set():-

    void SWI1_IRQHandler(bool radio_evt)
    {
        uint32_t err_code;
        ble_advertising_init_t init2;
    
        if (radio_evt)
        {
            nrf_gpio_pin_toggle(BSP_LED_2); //Toggle the status of the LED on each radio notification event
            
            memset(&init2, 0, sizeof(init2));
            ble_advdata_manuf_data_t manuf_data;
            static int i = 0;
            uint8_t* data[5];
            data[0] = putter("fghitrf");
            data[1] = putter("avbwifq");
            data[2] = putter("oiqhjdc");
            data[3] = putter("anoirdf");
            data[4] = putter("ujhqvnm");
    
            manuf_data.company_identifier       = 0xFFFF; // Unregistered company
            i = i%5;
            manuf_data.data.p_data = data[i];
    
    
            manuf_data.data.size                = sizeof(data[i]);
            i++;
            
            init2.advdata.name_type               = BLE_ADVDATA_SHORT_NAME;
            init2.advdata.short_name_len          = 6;
            init2.advdata.include_appearance      = false;
            init2.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
            init2.advdata.p_manuf_specific_data   = &manuf_data;
    
            err_code = ble_advdata_set(&(init2.advdata), NULL);
            APP_ERROR_CHECK(err_code);
        
          
        }
    }

    The putter() is just a function used to store random strings in the data[] array. Here are the outputs which I got:-

    This is the output which I get when I don't change the advertisement data. And the images below are the outputs when I change the advertisement data.

        

    As you can see, the Manufacturer data is changing but, I am only getting 4 bytes of data as compared to 11 bytes of the data which I was getting previously.  

    Here is the radio_notification_init() function call from the main if it maybe of any help to you.

    radio_notification_init(7, NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE, NRF_RADIO_NOTIFICATION_DISTANCE_5500US);
        

  • That code is just random. First of all you are setting (in the function) data to be an array of 5 byte pointers (uint8_t*), then you are assigning each of them to the result of putter() with an 8 byte null terminated string. It rather depends on what putter() does/returns what happens but I assume you just end up with the address of the fixed string in data[]. 

    Then you set the manufacturer data pointer to the one pointer in your data array, which possibly contains something pointing to one of the character strings you tried to store with putter(); depending on what putter() actually does. 

    You then tell it the size of the manufacturer data is sizeof( data[i] ) and the size of a uint8_t * on Cortex M0/4 is 4, so you've set the manufacturer data to 4 bytes at whatever data[i] points to. So that's why you're getting 4 bytes. Indeed in your first example the data is 0x66676869 which is "fghi" and in the second example it's 0x61766277 which is 'avbw' which are actually the first 4 characters of the first two strings so your code is sort of doing exactly what it says. 

    The function is wildly inefficient as you set up the whole data[] array, fill it up calling putter() on it and then toss 4/5 of it away each time through the loop; where all you actually wanted to do is put the address of one of your fixed strings in the manufacturer data  pointer and set the length to 7. 

  • Thank you for your help! It completely solved my problem. I can't believe I missed such a small bug.

    The putter() function is something like this:- 

    uint8_t * putter(char str[])
    {
    	int l = strlen(str);
    	uint8_t * u = (uint8_t *) malloc(l+1);
    	strcpy (u, str);
    	return u;
    }

    Regarding efficiency, I know it's inefficient. I was just trying to recreate an example similar to what I am doing so that I can convey my problem easily to the people here. Anyway, thanks for the help!

Related