Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Advertisement parameter max_adv_evts has no effect

Base BLE structure ble_advertising_t contains a member structure ble_adv_mode_config_t. This structure contains two parameters that are meant to limit number of advertisements sent by the beacon : duration and max_adv_evts. Both, when set, are supposed to trigger BLE flag  BLE_GAP_EVT_ADV_SET_TERMINATED.

In practise:

  • setting duration parameter to valid value works as expected - after specified amount of time an event is registered in ble_event.c (seen in sd module debug log);
    in ble_evt_handler, BLE_GAP_EVT_ADV_SET_TERMINATED flag is triggered correctly

  • setting max_adv_evts parameter to valid value does not have any effect - advertisements continue to occur after number specified, no events are registered in ble_event.c log and BLE_GAP_EVT_ADV_SET_TERMINATED flag is not raised

This behavior was observed in:

  • SDK 15.2.0., s132, using ble_app_hrs_freertos example
  • SDK 15.2.0., s140, using ble_app_hrs_freertos example
  • SDK 16.0.0, s132, using ble_app_hrs_freertos example
  • SDK 16.0.0, s140, using ble_app_hrs_freertos example

Only modification to the ble_app_hrs_freertos example was to set adv interval to 1 second, timeout to 20 seconds, max_adv_evts to 10; no other functionality was altered; proper SDK functions and tokens were used for converting milliseconds to SDK units.

Is this a known bug?
If not, would appreciate for another pair of eyes to take a look and try to replicate the issue.

  • Hello,

    I have not confirmed this with the freertos version, but I tested with the non-freertos version, and I suspect you may be seeing the same thing.

    Where do you set the max_adv_evts parameter? I suspect it is before you call 

    ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);

    Is that correct?

    The reason I ask is that inside ble_advertising start(), the line:

    memset(&p_advertising->adv_params, 0, sizeof(p_advertising->adv_params));

    is called. So anything you have stored in adv_params will be erased, and set according to the parameters that you used in advertising_init(). I can't see that max_adv_evts is included in advertising_init(), so I assume this is what you are seeing.

    If you try to add the line:

    p_advertising->adv_params.max_adv_evts = 5;

    before the line:

    switch (p_advertising->adv_mode_current)

    in ble_advertising_start(), you should see that it times out after 5 advertisements. At least it did in my case.

    Best regards,

    Edvin

  • Hi Edvin, thank you for your answer!

    I can indeed verify that your suggestion works.

    I have previously tried to add the line 

    p_advertising->adv_params.max_adv_evts = 1;

    inside ble_advertising_init(), where the other adv_params are set, just before

    ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, NULL, &p_advertising->adv_params);

    is called, but to no avail. Any idea why this does not work? Shouldn't the max_adv_evts parameter then be set inside sd configuration and not get erased by that memset just like duration, interval and the rest of adv_params ?
  • Look in the ble_advertising start. The max_adv_evts is not fetched before

    ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, p_advertising->p_adv_data, &p_advertising->adv_params);

    So you need to modify the library to use the max_adv_evts if you need to use it.

    Is there a particular reason for why you need to use this? I believe it is not much used. Is it possible to use the timeout instead, so that you don't need to modify the ble_advertising.c file?

  • Indeed.

    Modifying the SDK code to use one of its documented features is not the way to go, in my opinion.

    Any reason why this feature is not properly integrated? I have seen Nordic staff members recommend it to users with particular use cases here on devzone.

    Yes, I need to send a single advertisement at a time and get informed when its sent. Therefore max_adv_evts would perfectly suit my use case.

    Unfortunately, timeout is not viable for me, as the only way to send a single advertisement and then timeout at the moment is to use minimal interval value of 20 together with timeout value of 40 ms (lower timeout values either result in nrf error or an advertisement is not sent at all). Wasting 20 ms is also not viable for me at this moment.

  • I see. 

    As you say, it is not ideal to modify SDK modules, but it is possible. How about creating a modified ble_advertising_start function, that will be equivalent to the original, except adding that max_adv_evts()? 

    Why it is not properly integrated I don't know. As I said, it isn't much used, I believe. Remember that advertisements are not a reliable way for data transfer. You can not be sure that the receiver will pick up that exact advertisement, so changing the advertisement packet on every advertisement does not mean that this data will be received on the other side without packet loss.

Related