Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BLE][IDF v5.3.x/5.4.0] Unable to Keep Periodic Advertising Running After Stopping Extended Advertising / Cannot Set Large Extended Adv Intervals (IDFGH-14466) #15240

Open
iamcalledusman opened this issue Jan 20, 2025 · 3 comments
Labels
Status: In Progress Work is in progress

Comments

@iamcalledusman
Copy link

iamcalledusman commented Jan 20, 2025

Hello Espressif Team,

I am facing an issue with Extended Advertising and Periodic Advertising in ESP-IDF, specifically:

Stopping Extended Advertising Also Stops Periodic Advertising

According to the Bluetooth 5.0 spec, it should be possible to continue periodic advertising even after stopping extended advertising on the same handle. However, in my testing with ESP-IDF, once I call esp_ble_gap_ext_adv_stop(...), the periodic advertising also stops.
Large Extended Advertising Intervals Appear Clamped at ~40 s

When I set .interval_min and .interval_max to larger 24-bit values (e.g., 0x1FFFF for ~81 s), I still observe an actual advertising interval closer to 40 s. This suggests the controller might be falling back to the 16-bit legacy limit, even though I am using a non-legacy extended advertising property (NONCONN_NONSCANNABLE_UNDIRECTED).
My requirement is to have a short burst of extended advertising to establish periodic sync, and then either:

Stop extended advertising entirely while keeping periodic advertising on the same handle, or
Use a truly large extended advertising interval (e.g., ~81 s or more, up to the 24-bit limit of ~2.9 hours) to minimize power consumption.
However, neither approach seems possible in practice with the current ESP-IDF

Environment
Module or Chip: ESP32-C6
ESP-IDF Version: v5.3.2/v5.4.0(tried both)
Compiler: riscv32-esp-elf-gcc
Operating System: Windows
Power Supply: USB
Example code : https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/ble_50/periodic_adv

#define EXT_ADV_HANDLE   0

static esp_ble_gap_ext_adv_params_t ext_adv_params = {
    .type           = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED,
    .interval_min   = 0x1FFFF,  // aiming for ~81 s
    .interval_max   = 0x1FFFF,
    .channel_map    = ADV_CHNL_ALL,
    .filter_policy  = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
    .primary_phy    = ESP_BLE_GAP_PHY_1M,  // Tried with CODED as well 
    .max_skip       = 0,
    .secondary_phy  = ESP_BLE_GAP_PHY_2M, // // Tried with CODED as well 
    .sid            = 0,
    .scan_req_notif = false,
    .own_addr_type  = BLE_ADDR_TYPE_RANDOM,
    .tx_power       = EXT_ADV_TX_PWR_NO_PREFERENCE,
};

static esp_ble_gap_periodic_adv_params_t periodic_adv_params = {
    .interval_min = 24000,  // ~30 s
    .interval_max = 24000,
    .properties   = 0,
};

LOG FILE :


I (23) boot: ESP-IDF v5.4 2nd stage bootloader
I (24) boot: compile time Jan 19 2025 01:50:29
I (24) boot: chip revision: v0.0
I (24) boot: efuse block revision: v0.1
I (27) boot.esp32c6: SPI Speed      : 80MHz
I (31) boot.esp32c6: SPI Mode       : DIO
I (34) boot.esp32c6: SPI Flash Size : 2MB
I (38) boot: Enabling RNG early entropy source...
I (43) boot: Partition Table:
I (45) boot: ## Label            Usage          Type ST Offset   Length
I (52) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (58) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (65) boot:  2 factory          factory app      00 00 00010000 00100000
I (71) boot: End of partition table
I (75) esp_image: segment 0: paddr=00010020 vaddr=420b0020 size=2452ch (148780) map
I (110) esp_image: segment 1: paddr=00034554 vaddr=40800000 size=03ac4h ( 15044) load
I (113) esp_image: segment 2: paddr=00038020 vaddr=42000020 size=ae23ch (713276) map
I (246) esp_image: segment 3: paddr=000e6264 vaddr=40803ac4 size=0ede4h ( 60900) load
I (259) esp_image: segment 4: paddr=000f5050 vaddr=408128b0 size=02718h ( 10008) load
I (266) boot: Loaded app from partition at offset 0x10000
I (267) boot: Disabling RNG early entropy source...
I (277) cpu_start: Unicore app
I (285) cpu_start: Pro cpu start user code
I (286) cpu_start: cpu freq: 160000000 Hz
I (286) app_init: Application information:
I (288) app_init: Project name:     periodic_adv_demos
I (294) app_init: App version:      1
I (299) app_init: Compile time:     Jan 19 2025 01:48:45
I (305) app_init: ELF file SHA256:  26082cade...
I (310) app_init: ESP-IDF:          v5.4
I (314) efuse_init: Min chip rev:     v0.0
I (319) efuse_init: Max chip rev:     v0.99 
I (324) efuse_init: Chip rev:         v0.0
I (329) heap_init: Initializing. RAM available for dynamic allocation:
I (336) heap_init: At 408197E0 len 00062E30 (395 KiB): RAM
I (342) heap_init: At 4087C610 len 00002F54 (11 KiB): RAM
I (348) heap_init: At 50000000 len 00003FE8 (15 KiB): RTCRAM
I (356) spi_flash: detected chip: generic
I (359) spi_flash: flash io: dio
W (363) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (377) sleep_gpio: Configure to isolate all GPIO pins in sleep state
I (384) sleep_gpio: Enable automatic switching of GPIO sleep configuration
I (391) coexist: coex firmware version: 49a8cdc
I (405) coexist: coexist rom version 5b8dcfa
I (405) main_task: Started on CPU0
I (405) main_task: Calling app_main()
I (425) BLE_INIT: Using main XTAL as clock source
I (425) BLE_INIT: ble controller commit:[b623f7a]
I (425) BLE_INIT: Bluetooth MAC: 40:4c:ca:4a:a3:3a
I (425) phy_init: phy_version 320,348a293,Sep  3 2024,16:33:12
I (475) phy: libbtbb version: 04952fd, Sep  3 2024, 16:33:30
I (695) PERIODIC_ADV_DEMO: Extended advertising params set, status 0, instance 0
I (695) PERIODIC_ADV_DEMO: Extended advertising random address set, status 0, instance 0
I (695) PERIODIC_ADV_DEMO: Extended advertising data set, status 0, instance 0
I (705) PERIODIC_ADV_DEMO: Extended advertising start, status 0, instance numble 1
I (715) PERIODIC_ADV_DEMO: Periodic advertising params set, status 0, instance 0
I (725) PERIODIC_ADV_DEMO: Periodic advertising data set, status 0, instance 0
I (735) main_task: Returned from app_main()

Observed Behavior
Stopping Extended Advertising

esp_ble_gap_ext_adv_stop(1, &ext_adv[EXT_ADV_HANDLE]);
This also kills periodic advertising on the same handle. The logs confirm both advertisements stop.

Large Interval Clamped
If I do not stop extended advertising, I set .interval_min = 0x1FFFF (aiming for ~81 s). In practice, using a BLE sniffer or a scanning device, I see the device advertising at ~40 s intervals, indicating a fallback to the legacy 16-bit maximum.

Expected Behavior
According to the BLE Specification: We can keep periodic advertising running even if we stop sending extended advertising PDUs, or we can set an extended interval up to 0xFFFFFF (~2.9 hours) for truly extended advertising.

In either case, we would see either zero extended adv overhead (only periodic PDUs) or a very infrequent extended adv interval.

Question / Request
Is this a known limitation or bug in the ESP-IDF BLE controller stack?
Are there workarounds to achieve “periodic only” without extended PDUs or to set the interval larger than ~40 s?
Is there any plan to support stopping extended advertising while keeping periodic advertising active on the same handle, in line with the BLE spec?
Any guidance or solutions would be greatly appreciated.

Wireshark Logs

You can see that I set the interval of 0x1FFFF but getting PDU almost every 41 seconds, Tried with coded phy as well but still the same behavior.

Image

Thank you!

@espressif-bot espressif-bot added the Status: Opened Issue is new label Jan 20, 2025
@github-actions github-actions bot changed the title [BLE][IDF v5.3.x/5.4.0] Unable to Keep Periodic Advertising Running After Stopping Extended Advertising / Cannot Set Large Extended Adv Intervals [BLE][IDF v5.3.x/5.4.0] Unable to Keep Periodic Advertising Running After Stopping Extended Advertising / Cannot Set Large Extended Adv Intervals (IDFGH-14466) Jan 20, 2025
@espressif-bot espressif-bot assigned esp-zhp and unassigned esp-zhp Jan 21, 2025
@espressif-bot espressif-bot added Status: In Progress Work is in progress and removed Status: Opened Issue is new labels Jan 22, 2025
@ZhouXiao616
Copy link
Collaborator

Hi @iamcalledusman , thanks for you feedback!

We noticed that you mentioned two issues:

  1. Extended advertising interval could not exceed 40.95s
  2. Stopping extended adveritising also stops periodic advertising

The first one is a known issue and we're fixing it, the fix would be merged to IDF as soon as possible. :)

For the second one, we tried to reproduce the issue locally with ESP32C6 on release/v5.3 and release/v5.4. In our modification to https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/ble_50/periodic_adv, we called esp_ble_gap_ext_adv_stop function right after calling esp_ble_gap_periodic_adv_start function, but periodic advertising didn't stop. We also tried to set periodic advertising interval to around 30s, it still worked well.

Related codes (on release/v5.4):

void app_main(void)
{
    ...

    // create static random address
    esp_bd_addr_t rand_addr;
    esp_ble_gap_addr_create_static(rand_addr);

    test_sem = xSemaphoreCreateBinary();

    // 2M phy extend adv, Non-Connectable and Non-Scannable Undirected advertising
    ESP_LOG_BUFFER_HEX(LOG_TAG, rand_addr, ESP_BD_ADDR_LEN);
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_params(EXT_ADV_HANDLE, &ext_adv_params_2M), test_sem);
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_rand_addr(EXT_ADV_HANDLE, rand_addr), test_sem);
    FUNC_SEND_WAIT_SEM(esp_ble_gap_config_ext_adv_data_raw(EXT_ADV_HANDLE, sizeof(raw_ext_adv_data_2m), &raw_ext_adv_data_2m[0]), test_sem);

    // start all adv
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_start(NUM_EXT_ADV, &ext_adv[0]), test_sem);

    // set periodic adv param
    FUNC_SEND_WAIT_SEM(esp_ble_gap_periodic_adv_set_params(EXT_ADV_HANDLE, &periodic_adv_params), test_sem);

#if (CONFIG_BT_BLE_FEAT_PERIODIC_ADV_ENH)
    // set periodic adv raw data
    FUNC_SEND_WAIT_SEM(esp_ble_gap_config_periodic_adv_data_raw(EXT_ADV_HANDLE, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0], false), test_sem);
    // start periodic adv, include the ADI field in AUX_SYNC_IND PDUs
    FUNC_SEND_WAIT_SEM(esp_ble_gap_periodic_adv_start(EXT_ADV_HANDLE, true), test_sem);
    while (1) {
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        // just update the Advertising DID of the periodic advertising, unchanged data
        FUNC_SEND_WAIT_SEM(esp_ble_gap_config_periodic_adv_data_raw(EXT_ADV_HANDLE, 0, NULL, true), test_sem);
    }
#else
    // set periodic adv raw data
    FUNC_SEND_WAIT_SEM(esp_ble_gap_config_periodic_adv_data_raw(EXT_ADV_HANDLE, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0]), test_sem);
    FUNC_SEND_WAIT_SEM(esp_ble_gap_periodic_adv_start(EXT_ADV_HANDLE), test_sem);
#endif

    // Stop extended advertising right after starting periodic advertising
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_stop(NUM_EXT_ADV, &ext_adv[0].instance), test_sem);

    return;
}

Related logs:

I (528) PERIODIC_ADV_DEMO: Extended advertising params set, status 0, instance 0
I (538) PERIODIC_ADV_DEMO: Extended advertising random address set, status 0, instance 0
I (548) PERIODIC_ADV_DEMO: Extended advertising data set, status 0, instance 0
I (558) PERIODIC_ADV_DEMO: Extended advertising start, status 0, instance numble 1
I (558) PERIODIC_ADV_DEMO: Periodic advertising params set, status 0, instance 0
I (568) PERIODIC_ADV_DEMO: Periodic advertising data set, status 0, instance 0
I (578) PERIODIC_ADV_DEMO: Periodic advertising start, status 0, instance 0
I (578) PERIODIC_ADV_DEMO: Extended advertising start, status 0, instance numble 1
I (588) main_task: Returned from app_main()

Checking your log, we found that periodic advertising didn't even start, could you please share your codes so we can help you debug the issue?

PS: We noticed that you tried to stop extended advertising by calling esp_ble_gap_ext_adv_stop(1, &ext_adv[EXT_ADV_HANDLE]); and it seems to be incorrect. If you call esp_ble_gap_ext_adv_start(NUM_EXT_ADV, &ext_adv[0]); to start extended advertising, you should call esp_ble_gap_ext_adv_stop(NUM_EXT_ADV, &ext_adv[0].instance); to stop extended advertising.

We hope it would help. Looking forward to your reply.

@iamcalledusman
Copy link
Author

Hi @ZhouXiao616!

Thank you so much for your time and assistance!

  1. Extended advertising interval could not exceed 40.95s

    Thank you for fixing it in the coming esp-idf version!

  2. Stopping extended advertising also stops periodic advertising

Periodic Advertisement LOG FILE

I (406) main_task: Calling app_main()
I (416) BLE_INIT: Using main XTAL as clock source
I (426) BLE_INIT: ble controller commit:[b623f7a]
I (426) BLE_INIT: Bluetooth MAC: 40:4c:ca:51:42:da
I (426) phy_init: phy_version 320,348a293,Sep  3 2024,16:33:12
I (476) phy: libbtbb version: 04952fd, Sep  3 2024, 16:33:30
I (686) PERIODIC_ADV_DEMO: Extended advertising params set, status 0, instance 0
I (686) PERIODIC_ADV_DEMO: Extended advertising random address set, status 0, instance 0
I (686) PERIODIC_ADV_DEMO: Extended advertising data set, status 0, instance 0
I (696) PERIODIC_ADV_DEMO: Extended advertising start, status 0, instance numble 1
I (706) PERIODIC_ADV_DEMO: Periodic advertising params set, status 0, instance 0
I (716) PERIODIC_ADV_DEMO: Periodic advertising data set, status 0, instance 0
I (726) PERIODIC_ADV_DEMO: ESP_GAP_BLE_PERIODIC_ADV_START_COMPLETE_EVT, status 0, instance 0
I (726) PERIODIC_ADV_DEMO: Extended advertising stop, status 0, instance numble 1
I (736) main_task: Returned from app_main()

Periodic Sync LOG FILE

I (405) main_task: Calling app_main()
I (425) BLE_INIT: Using main XTAL as clock source
I (425) BLE_INIT: ble controller commit:[b623f7a]
I (425) BLE_INIT: Bluetooth MAC: 40:4c:ca:51:62:5e
I (425) phy_init: phy_version 320,348a293,Sep  3 2024,16:33:12
I (475) phy: libbtbb version: 04952fd, Sep  3 2024, 16:33:30
I (685) PERIODIC_SYNC: Extended scanning params set, status 0
I (685) PERIODIC_SYNC: Extended scanning start, status 0
I (685) main_task: Returned from app_main()
I (6165) extended adv data is......... : 02 01 06 02 0a eb 13 09 45 53 50 5f 4d 55 4c 54
I (6165) extended adv data is......... : 49 5f 41 44 56 5f 38 30 4d 53
I (6175) PERIODIC_SYNC: Start create sync with the peer device ESP_MULTI_ADV_80MS
I (6185) PERIODIC_SYNC: Periodic advertising create sync, status 0

periodic_adv & Sync.zip

I attached both the project periodic_adv as well as the periodic_sync

I enabled the following but still got the same response after disabling it.
#if (CONFIG_BT_BLE_FEAT_PERIODIC_ADV_ENH)

I noticed the same response, after calling esp_ble_gap_ext_adv_stop(NUM_EXT_ADV, &ext_adv[0].instance); both the periodic and ext adv pdu stopped.

Thank you again for your response!

Looking forward to your reply.

@iamcalledusman
Copy link
Author

Hi @ZhouXiao616!

Thank you so much for your time and assistance!

After a small change , now periodic adv is working fine

#if (CONFIG_BT_BLE_FEAT_PERIODIC_ADV_ENH)
    // set periodic adv raw data
    FUNC_SEND_WAIT_SEM(esp_ble_gap_config_periodic_adv_data_raw(EXT_ADV_HANDLE, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0], false), test_sem);
    // start periodic adv, include the ADI field in AUX_SYNC_IND PDUs
    FUNC_SEND_WAIT_SEM(esp_ble_gap_periodic_adv_start(EXT_ADV_HANDLE, true), test_sem);

  
    vTaskDelay(5000 / portTICK_PERIOD_MS);
    
    // Stop extended advertising right after starting periodic advertising
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_stop(NUM_EXT_ADV, &ext_adv[0].instance), test_sem);

    while (1) {
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        // just update the Advertising DID of the periodic advertising, unchanged data
        FUNC_SEND_WAIT_SEM(esp_ble_gap_config_periodic_adv_data_raw(EXT_ADV_HANDLE, 0, NULL, true), test_sem);
    }


Added the delay and stop the function


 vTaskDelay(5000 / portTICK_PERIOD_MS);
    
    // Stop extended advertising right after starting periodic advertising
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_stop(NUM_EXT_ADV, &ext_adv[0].instance), test_sem);

Again thank You!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: In Progress Work is in progress
Projects
None yet
Development

No branches or pull requests

4 participants