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

alternate advertising packets with nRF52832, sdk15.0.0 , sd132 v6.0.0

I need to change, on a time basis, the advertising packet :

Let's say for X seconds it has to work as a "iBeacon"

  • BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED
  • Advertising interval 100ms

, while for other X seconds as a scannable and connecteble advertising (standard) packet:

  • Advertising interval 190 ms

i'm developing starting from the template example with  BLE_ADVERTISING_DEF(m_advertising)  structure and I'm trying to "integrate"

with the "nRF5_SDK_15.0.0_a53641a\examples\ble_peripheral\ble_app_beacon"  example but I'm getting an :

"..<error> app: Fatal error
<warning> app: System reset"

when trying with this piece of code:


static void timer_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    ret_code_t err_code;
    static int flag=1;
    timerCounter++;

    
    if( timerCounter % 3 == 0 )
    {
      if (flag ){
        //stop "standard" adv
        NRF_LOG_INFO(" stopping standard ADV");
        err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);      
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }
  
        // change advertising message
        NRF_LOG_INFO(" init iBeacon ");
        iBeacon_init();              
        NRF_LOG_INFO(" starting ibeacon");
        iBeacon_start();
  
        flag = 0;

      }

      else  
      {
        
        NRF_LOG_INFO(" restart standard ADV");
        err_code = sd_ble_gap_adv_stop(m_adv_handle);
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }
        err_code = ble_advertising_restart_without_whitelist(&m_advertising);
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }

        flag =1;
      }
      
    }

}


static void iBeacon_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;

    ble_advdata_manuf_data_t manuf_specific_data;

    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;

#if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
    // UICR instead of using the default values. The major and minor values obtained from the UICR
    // are encoded into advertising data in big endian order (MSB First).
    // To set the UICR used by this example to a desired value, write to the address 0x10001080
    // using the nrfjprog tool. The command to be used is as follows.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
    // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
    // the following command should be used.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
    uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
    uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);

    uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;

    m_beacon_info[index++] = MSB_16(major_value);
    m_beacon_info[index++] = LSB_16(major_value);

    m_beacon_info[index++] = MSB_16(minor_value);
    m_beacon_info[index++] = LSB_16(minor_value);
#endif

    manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
    manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type             = BLE_ADVDATA_NO_NAME;
    advdata.flags                 = flags;
    advdata.p_manuf_specific_data = &manuf_specific_data;

    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
    m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
    m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
    m_adv_params.duration        = APP_IBCN_DURATION;       // Never time out.

    err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
    APP_ERROR_CHECK(err_code);
}


static void iBeacon_start(void)
{
    ret_code_t err_code;

    err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
    APP_ERROR_CHECK(err_code);
}


 

the application resets on iBeacon_init() in the timer handler.

is it a problem of configuring the right parametrs to the SD API , or something else?

Thx

bye

Parents
  • Hi,

    The SoftDevice V6.0.0 can only configure one advertising set. Therefore, when starting the non-connectable advertising(iBeacon), the advertising handle should be the same as for the connectable advertising. (i.e. use m_advertising.adv_handle for both).

    In your function, IBeacon_init() should configure the adv set like this:

        err_code = sd_ble_gap_adv_set_configure(&m_advertising.adv_handle, &m_adv_data, &m_adv_params);
        APP_ERROR_CHECK(err_code);

    The function iBeacon_start() should look like this:

    static void iBeacon_start(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_start(m_advertising.adv_handle, APP_BLE_CONN_CFG_TAG);
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
        APP_ERROR_CHECK(err_code);
    }

    And in timer_timeout_handler(), restart standard ADV like this:

          else  
          {
            
            NRF_LOG_INFO(" restart standard ADV");
            err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
            err_code = ble_advertising_restart_without_whitelist(&m_advertising);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
    
            flag =1;
          }

    PS: I don't see that you set your timerCounter back to 0 anywhere, so it might overflow after awhile. You can also just adjust the timeout value for how often timer_timeout_handler is called, so you could consider removing the timerCounter.

    Best regards,

    Sigurd

Reply
  • Hi,

    The SoftDevice V6.0.0 can only configure one advertising set. Therefore, when starting the non-connectable advertising(iBeacon), the advertising handle should be the same as for the connectable advertising. (i.e. use m_advertising.adv_handle for both).

    In your function, IBeacon_init() should configure the adv set like this:

        err_code = sd_ble_gap_adv_set_configure(&m_advertising.adv_handle, &m_adv_data, &m_adv_params);
        APP_ERROR_CHECK(err_code);

    The function iBeacon_start() should look like this:

    static void iBeacon_start(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_start(m_advertising.adv_handle, APP_BLE_CONN_CFG_TAG);
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
        APP_ERROR_CHECK(err_code);
    }

    And in timer_timeout_handler(), restart standard ADV like this:

          else  
          {
            
            NRF_LOG_INFO(" restart standard ADV");
            err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
            err_code = ble_advertising_restart_without_whitelist(&m_advertising);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
    
            flag =1;
          }

    PS: I don't see that you set your timerCounter back to 0 anywhere, so it might overflow after awhile. You can also just adjust the timeout value for how often timer_timeout_handler is called, so you could consider removing the timerCounter.

    Best regards,

    Sigurd

Children
  • still I get the error:

    <info> app: FW_VER= nRF52DK_00.02.01
    <info> app: log_init
    <info> app: timers_init
    <info> app: buttons_leds_init
    <info> app: power_management_init
    <info> app: ble_stack_init
    <info> app: services_init
    <info> app: advertising_init
    <info> app: XX Demo started.
    <info> app: Fast advertising.

    ...after 3 sec...

    <info> app: stopping standard ADV
    <info> app: init iBeacon
    <error> app: Fatal error
    <warning> app: System reset

    ...

    i'm wondering if the two different configurations are "compatible" :

    the custom advertisement is  this:

    static void advertising_init(void)
    {
        ret_code_t             err_code;
        ble_advertising_init_t init;
        ble_advdata_manuf_data_t  manuf_data_res; // Variable to hold manufacturer specific data
    
    
        //manuf_data.company_identifier         = 0x0059; // Nordics company ID
        manuf_data_res.company_identifier       = 0xffff; //interoperability default value; not to be used in shipping end product
        manuf_data_res.data.p_data              = (uint8_t *)SerialNumber;
        manuf_data_res.data.size                = sizeof(SerialNumber)-1;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        //init.advdata.name_type               = BLE_ADVDATA_SHORT_NAME;
        //init.advdata.short_name_len          = 8;
        //init.advdata.include_appearance      = true;
        init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;   
        init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
    
    
        init.srdata.name_type               = BLE_ADVDATA_NO_NAME;    
        init.srdata.include_appearance      = true;  
        init.srdata.p_manuf_specific_data   = &manuf_data_res;
        //init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);//more_adv_uuids
        //init.srdata.uuids_complete.p_uuids = m_adv_uuids;
           
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    
        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);
    }
    

    while the beacon struct is written above in the first code snippet.

    any comment?

  • What is the value of your "APP_IBCN_DURATION" ? Could you try setting it to 0 ?

  • SOLVED.

    issue was a wrong initialization in the data structures passed in the

     err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);

    when changing from iBeacon to custom advertising and vice versa.

    (the m_adv_data.adv_data.p_data  and m_adv_data.adv_data.len are static, retaining a wrong data size when toggling from one another kind of packets) 

    in the end it worked, on a time slice base, alternating the 2 packets (using just the same handler).

    the only thing is that I have to call every time sd_ble_gap_adv_stop() before the ble_advdata_encode-sd_ble_gap_adv_set_configure  and sd_ble_gap_adv_start() calls.

Related