BLE advertisement stops after connection

Hi Devzone,

I am facing an issue in my application where my device is working as a BLE peripheral advertising for connection. The device stops advertising after connecting to it for the 2nd time and doesn't recover advertising even after disconnection, where advertisement is restarted again.

Here the max number of connections is 2, if I change the max connections to 3, the error also occurs after 3rd connection.

No advertisement after connection would've been expected as long as it recovered once restarted after disconnection. But that is not the case here. I get a -11 error for 

bt_le_adv_update_data function. I've tried to start advertising after stopping it, checked from the examples and implemented a retry option, nothing seems to work, can anyone share what I'm doing wrong?

 
NCS version 2.4.1
MCU: NRF52832

Attaching project conf and gap file containing connection, disconnection callbacks as well as advertisement management

Thanks

#include "gap.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#include <zephyr/kernel.h>
#include <zephyr/types.h>
#include <zephyr/sys/printk.h>
#include <zephyr/logging/log.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>

#include <zephyr/logging/log.h>
#include <zephyr/bluetooth/addr.h>
#include <zephyr/bluetooth/conn.h>


LOG_MODULE_REGISTER(GAP, LOG_LEVEL_INF);


static struct bt_conn *current_conn;
struct k_work start_advertising_worker;
uint8_t manufacturer_data[MANUFACTURER_DATA_LEN] = {0};
uint8_t tx_power = 0;
struct bt_data ad[ARRAY_SIZE_AD] = {
	BT_DATA_BYTES(BT_DATA_FLAGS,BT_LE_AD_GENERAL|BT_LE_AD_NO_BREDR),
	BT_DATA(0x77,manufacturer_data,MANUFACTURER_DATA_LEN),
	BT_DATA(BT_DATA_TX_POWER, &tx_power, sizeof(tx_power)),
};

bool adv_enabled = false;

uint8_t conn_count = 0;

struct bt_data sd[ARRAY_SIZE_SD]= {
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
// 	// BT_DATA(BT_DATA_MANUFACTURER_DATA,manufacturer_data,MANUFACTURER_DATA_LEN),
};

    // struct BT_LE_EXT_ADV_START_PARAM 
// struct bt_le_adv_param *adv_param = BT_LE_ADV_PARAM((BT_LE_ADV_OPT_CONNECTABLE|BT_LE_ADV_OPT_USE_IDENTITY), 
//                 800, /*Min Adv Interval 500ms (800*0.625ms) */
//                 801, /*Max Adv Interval 500.625ms (801*0.625ms)*/
//                 NULL);

// struct bt_le_ext_adv_param *adv_param_1; 

struct bt_le_adv_param *adv_param = BT_LE_ADV_PARAM((BT_LE_ADV_OPT_USE_IDENTITY|BT_LE_ADV_OPT_SCANNABLE|BT_LE_ADV_OPT_CONNECTABLE),
                1600, /*Min Adv Interval 1000ms (1600*0.625ms) */
                1601, /*Max Adv Interval 1000.625ms (1601*0.625ms)*/
                NULL);

    // static  struct bt_le_ext_adv_cb adv_cb = {
	// 	.sent = adv_sent,
	// };

	// static struct bt_le_ext_adv *adv; 


static struct bt_conn_cb conn_callbacks = {
	.connected = connected,
	.disconnected = disconnected,

};


/* Fuctions for handling connection and disconnection events*/

void connected(struct bt_conn *conn, uint8_t conn_err)
{
	int err;
	struct bt_conn_info info;
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (conn_err) {
		LOG_INF("Connection failed (err %d)\n", conn_err);
		return;
	}

	err = bt_conn_get_info(conn, &info);
    current_conn = bt_conn_ref(conn);
	if (err) {
		LOG_INF("Failed to get connection info\n");
	}// else {
		// const struct bt_conn_le_phy_info *phy_info;
		// phy_info = info.le.phy;

		// LOG_INF("Connected: %s, tx_phy %u, rx_phy %u\n",
		//        addr, phy_info->tx_phy, phy_info->rx_phy);
	// }
	request_mtu_exchange();
	request_data_len_update();
    printk("Connected\n");
	// k_work_submit(&start_advertising_worker);
	conn_count++;
}

void disconnected(struct bt_conn *conn, uint8_t reason)
{
	LOG_INF("Disconnected (reason 0x%02x)\n", reason);
	k_work_submit(&start_advertising_worker);
	conn_count--;
}

uint8_t get_conn_count(){
	LOG_INF("Connection count: %d", conn_count);
	return conn_count;
}

void start_advertising(void)
{
    int err = bt_le_adv_start(adv_param, ad, ARRAY_SIZE(ad), sd ,ARRAY_SIZE(sd));
    if (err) {
        printk("Adv failed to start (err %d)\n", err);
    } else {
        printk("Adv started\n");
        adv_enabled = true;
    }
}

void stop_advertising(void)
{
    int err = bt_le_adv_stop();
    if (err) {
        printk("Failed to stop adv (err %d)\n", err);
    } else {
        printk("Adv stopped\n");
        adv_enabled = false;
    }
}

void start_advertising_handler(struct k_work *item )
{
	stop_advertising();
	start_advertising();
}

void bt_ready(void)
{
	int err = 0;
	k_work_init(&start_advertising_worker, start_advertising_handler);

	err = bt_enable(NULL);
	if(err<0)
	{
		LOG_ERR("BT_INIT FAILED:%d",err);
	}
	LOG_INF("Bluetooth init\n");
    bt_conn_cb_register(&conn_callbacks);
	k_work_submit(&start_advertising_worker);
}

void adv_sent(struct bt_le_ext_adv *instance,
		     struct bt_le_ext_adv_sent_info *info)
{	
	// int err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd , ARRAY_SIZE(sd));
	// if(err<0)
	// {
	// 	LOG_ERR("ERROR IN UPDATION: %d ", err);
	// }
	// start_advertising();
	// int err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
	
	// k_work_submit(&start_advertising_worker);
    LOG_INF("Adv stopped. num_sent: %d ", info->num_sent);
}

void update_advertisement_data(uint8_t *mfg_data, uint8_t mfg_data_len){

	LOG_INF("BT status: %d", bt_is_ready());

	memcpy(manufacturer_data, mfg_data, mfg_data_len);

	tx_power = NRF_RADIO->TXPOWER;

    int retries = 0;
    int err;

	if (!adv_enabled) {
        printk("Adv not enabled\n");
        return;
    }

    do {
        err = bt_le_adv_update_data(ad,ARRAY_SIZE(ad), sd ,ARRAY_SIZE(sd));
        if (err == -EAGAIN) {
            printk("Adv busy, retrying...\n");
            k_sleep(RETRY_DELAY);
            retries++;
        } else if (err) {
            printk("Failed adv update (err %d)\n", err);
            return;
        } else {
            printk("Adv data updated\n");
            break;
        }
    } while (err == -EAGAIN && retries < MAX_RETRIES);

    if (retries == MAX_RETRIES) {
        printk("Failed adv update %d retries\n", MAX_RETRIES);
    }

}

// /* Fuctions for making the MTU exchange*/

void MTU_exchange_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
{
	LOG_INF("MTU exchange %s", err == 0 ? "successful" : "failed");
	if (!err) {
		uint16_t payload_mtu =
			bt_gatt_get_mtu(conn) - 3; // 3 bytes used for Attribute headers.
		LOG_INF("New MTU: %d bytes", payload_mtu);
	}
}

void request_mtu_exchange(void)
{	int err;
	static struct bt_gatt_exchange_params exchange_params;
	exchange_params.func = MTU_exchange_cb;
	err = bt_gatt_exchange_mtu(current_conn, &exchange_params);
	if (err) {
		LOG_WRN("MTU exchange failed (err %d)", err);
	} else {
		LOG_INF("MTU exchange pending");
	}
}

void request_data_len_update(void)
{	int err;
	err = bt_conn_le_data_len_update(current_conn, BT_LE_DATA_LEN_PARAM_MAX);
		if (err) {
			LOG_ERR("LE data length update request failed: %d",  err);
		}
}

void request_phy_update(void)
{	int err;
	err = bt_conn_le_phy_update(current_conn, BT_CONN_LE_PHY_PARAM_2M);
		if (err) {
			LOG_ERR("Phy update request failed: %d",  err);
		}
}
64438.prj.conf

Parents Reply Children
No Data
Related