BLE advertisement failure with error "Advertising failed to start (err -11)"

I am using NCS V3.0.2 with a custom nRF52840 board, which functions as a BLE peripheral. The application that I am working on fully depends on the BLE connection, so the crucial point is the BLE advertisement. If the BLE advertisement fails, I need to retry it. If the issue persists, I need to restart the BLE stack to reset all BLE states and have a fresh start. The device restart is not an option here for me.

I saw that Zephyr has bt_disable() and bt_enable() APIs to perform the BLE stack restart operation. I have tried to implement the approach by taking reference from one of the samples in the Zephyr as mentioned below.

K_WORK_DELAYABLE_DEFINE(adv_work, ble_adv_handler);

static void ble_adv_handler(struct k_work *work)
{
	int err = 0;
    printk("Restarting BLE Module !!!\n");

	err = bt_le_adv_stop();
    if (err && err != -EALREADY) {
        printk("bt_le_adv_stop failed (err %d)\n", err);
    } else {
        printk("Advertising stopped successfully\n");
    }
    
    k_msleep(500);
    
    /// Disable the Bluetooth Subsystem
	err = bt_disable();
	if (err) {
		printk("Bluetooth disable failed (err %d)\n", err);
        return;
	}

    k_msleep(500);

	/// Initialize the Bluetooth Subsystem
	err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
        return;
	}

    k_msleep(500);
    printk("Restarting BLE Module done!!!\n");

    err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
	if (err) {
		printk("Advertising failed to start (err %d)\n", err);
		return;
	}

    printk("Regular advertising started\n");
}

static void restart_ble_module(void)
{
    k_work_schedule(&adv_work, K_MSEC(200));
}

But when I tried this approach, from the logs it shows the BLE restart got successful, but when it starts the advertisement, it returns with the error "Advertising failed to start (err -11)".

I am not sure about the exact cause of this error because, as you see in the above code, I first stopped the ongoing advertisement for safe side, and even after disabling the BLE, it still says "-EAGAIN", which means the process is already running. 

Is it something related to the Softdevice in nRF where it did not support the BLE restart feature that Zephyr provides, or is there any configuration issue/mismatch that I missed?

Your support is really appreciated here.

Thank you,
Ankit.

Parents
  • Hi, 

    If the BLE advertisement fails, I need to retry it. If the issue persists, I need to restart the BLE stack to reset all BLE states and have a fresh start.

    I suggest you check the error message to identify what's causing the BLE advertisement to fail and try to fix it. If you want to reset all BLE states and have a fresh start, you can call sys_reboot(SYS_REBOOT_COLD).  

    May I have more details about the BLE advertisement failures? 

    If the issue happened in the first advertisement after programming, you can refer to this DevAcademy course https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/lessons/lesson-2-bluetooth-le-advertising/topic/blefund-lesson-2-exercise-3/

    If it happened after the disconnection, you can check if calling bt_conn_unref() in the disconnect call back to release the resource if using bt_conn_ref(), as in this DevAcademy course https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/lessons/lesson-3-bluetooth-le-connections/topic/blefund-lesson-3-exercise-1/

    The device restart is not an option here for me.

    May I know the reason or any concern? 

    Regards,
    Amanda H.

  • Hi Amanda,

    Thank you for the reply. Below are the details that will help you understand the scenario.

    I am dealing with the high-speed data notification with the mobile app from the device with a connection interval of 11ms that sends data chunks of 180 bytes till the data is finished. I have faced an issue when the device disconnected during the transfer; the device failed to advertise after the disconnection with the error Advertising failed to start (err -12).

    In my .disconnected callback, I do bt_conn_unref(current_conn), and after that I start the advertisement in a k_work() to unload any extra process on the disconnected callback. This method is working fine in a normal case when the system is Idle and we disconnect the device, then it starts advertising without any issue.

    But here, it failed to start advertisement during the data transfer, when I debug the issue, I found that advertisement fails with error Advertising failed to start (err -12), which means the connection handle is not yet released. When I dig deeper more I realize that the ACL TX buffers are still filled with the notification data, and the BLE stack did not get enough time to clear those before the k_work() starts the advertisement.

    To resolve this issue, I have used K_WORK_DELAYABLE() to delay the advertisement after disconnection by around 200ms. With this change, it is now working fine as the stack got enough time to clean up the pending things, as far as I understand.

    But I believe it is a workaround rather than a solution to give some time to the BLE stack to complete the pending tasks. If it fails to clean up within 200ms, then the device will never advertise again. So I took this approach where I keep restarting the advertising, and if it still fails, I will restart the BLE stack.

    Below are the logs that I am getting 

    00> I: Disconnected from 20:15:82:15:8F:2A (public) (reason 19)
    00> W: conn 0x20006690: not connected
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 0
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 1
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 2
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 3
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 4
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 5
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 6
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 7
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 8
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -12), retry 9
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-12
    00> E: Advertising restart failed after 10 retries
    00> I: Restarting BLE Module !!!
    00> W: Not connected
    00> I: SoftDevice Controller build revision: 
    00> I: 89 9a 50 8a 95 01 9c 58 |..P....X
    00> I: fc 39 d2 c1 10 04 ee 02 |.9......
    00> I: 64 ce 25 be             |d.%.    
    00> I: HW Platform: Nordic Semiconductor (0x0002)
    00> I: HW Variant: nRF52x (0x0002)
    00> I: Firmware: Standard Bluetooth controller (0x00) Version 137.20634 Build 2617349514
    00> I: No ID address. App must call settings_load()
    00> I: Restarting BLE Module done!!!
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 0
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 1
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 2
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 3
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 4
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 5
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 6
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 7
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 8
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> I: BT Name configured to XXXXX
    00> W: Advertising start failed (err -11), retry 9
    00> E: ERR [BLE] act=BLE_ADV_START_FAIL errno=-11
    00> E: Advertising restart failed after 10 retries

    If you see the logs, first after the BLE disconnection, it faced an error -12, and after the BLE reset, it fails with error -11.

    About the device reset part, the device will be used for the health vital measurements, and if the device gets reset in between without knowing, then it would be a bad experience for the user.

    I hope I covered your question with the above reply. Let me know if you require any further information.

    Thanks,
    Ankit.

  • Hi, 

    We are not able to reproduce this. 

    Some feedback from the team:

    1.  The DevAcademy course blefund-lesson-2-exercise-3/ follows a pattern where bt_conn_unref is called in disconnected callback to mirror bt_conn_ref call in connected callback. The customer can also do this, but then the customer should also follow the rest of the pattern suggested in the course to start the advertiser in the recycled callback.
    2. We don't do it in our advertiser samples where we start the advertiser in a delayable work when disconnecting:
      1. https://github.com/nrfconnect/sdk-nrf/blob/main/samples/bluetooth/peripheral_with_multiple_identiti…
      2. https://github.com/nrfconnect/sdk-nrf/blob/main/samples/bluetooth/peripheral_hids_mouse/src/main.c#…
    3. It should not be necessary to stop the advertiser after the disconnect. Setting CONFIG_LOG=y in prj.conf should make a log visible that there is no advertiser running (it did for me).

    Here is a restart I put together to try to reproduce. It's submitted in the disconnect callback:

    static void restart_ble(struct k_work *work)
    {
            int err;
            //int err = bt_le_adv_stop();
            //if (err && err != -EALREADY) {
            //      printk("bt_le_adv_stop failed (err %d)\n", err);
            //} else {
            //      printk("Advertising stopped successfully\n");
            //}
     
            err = bt_disable();
            if (err) {
                    printk("Bluetooth disable failed (err %d)\n", err);
                    return;
            } else {
                    printk("Bluetooth disabled success\n");
            }
     
            err = bt_enable(NULL);
            if (err) {
                    printk("Bluetooth init failed (err %d)\n", err);
                    return;
            } else {
                    printk("Bluetooth init success\n");
            }
     
            err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
            if (err) {
                    printk("Advertising failed to start (err %d)\n", err);
                    return;
            }
    }

    I don't see the reason why the ble module should be restarted. Why would advertising or the connection keep failing? Why would it help to restart ble module in that case?

    -Amanda H.

  • Hi Amanda,

    Thank you for taking the time to investigate this issue.

    I do not want to restart the BLE either; my only goal is to restart the advertisement after BLE disconnects, and that is not happening right now. I have been using Nordic with Zephyr for a long time, so I am quite familiar with the ecosystem and the methods for using their components. I am aware of the guide and the code you shared, but these are the ideal scenarios where the system works in a happy path, and hence, such issues cannot be observed here.

    However, this issue can easily be reproduced by continuously notifying large dummy data to any BLE characteristics and disconnecting the BLE during the transfer. This will generate the Advertisement failure issue with error code -12.

    I do not know what the next step here is, but these are the details I have right now. I hope these details may help you to investigate it further.

    Regards,
    Ankit.

Reply
  • Hi Amanda,

    Thank you for taking the time to investigate this issue.

    I do not want to restart the BLE either; my only goal is to restart the advertisement after BLE disconnects, and that is not happening right now. I have been using Nordic with Zephyr for a long time, so I am quite familiar with the ecosystem and the methods for using their components. I am aware of the guide and the code you shared, but these are the ideal scenarios where the system works in a happy path, and hence, such issues cannot be observed here.

    However, this issue can easily be reproduced by continuously notifying large dummy data to any BLE characteristics and disconnecting the BLE during the transfer. This will generate the Advertisement failure issue with error code -12.

    I do not know what the next step here is, but these are the details I have right now. I hope these details may help you to investigate it further.

    Regards,
    Ankit.

Children
Related