BLE reconnect procedure

Hello there,

I'm designing a set of devices composed of a remote and 2 peripheral. The remote's job is to be connected to the 2 peripherals as a central and occasionnaly connect to a smartphone as a peripheral.

All of the devices are custom board, we already figured out the antenna matching which help to reduce bug. My development environment is : 

  • NCS & toolchain 3.0.1
  • nRF52833 for all 3 devices 

What is working : 

  1. The advertising and the scanning
  2. The pairing process
  3. The discovering procedure
  4. Read, write and subscribe to gatt atribute

What is not working : 

  1. Mainly the reconnect procedure 

I succeed to implement accept list for peripheral and to open it when i need to thank to the lesson from Academy, but i struggle to make the reconnect works. It is crucial because all 3 devices are battery powered and i need to save energy.

In my understanding, there is 2 steps : 

When no bond are available on the remote, i have to go though a scan with specific filtering and then connect / pair

When bond are available on the remote, i need to call bt_conn_le_create_auto at reboot and again at each connection.
However, i find some issue such as connection to the same device or hci error because no ressource are available. I need help to better understand this procedure and help me make it work.
Here's the KConfig of my remote project 
################
# Board config #
################
CONFIG_EVENTS=y
CONFIG_SMF=y
CONFIG_HWINFO=y

# Enable PWM led 
CONFIG_PWM=y
CONFIG_NRFX_PWM0=y
CONFIG_LED=y

# Enable button
CONFIG_INPUT=y
CONFIG_INPUT_GPIO_KEYS=y

# Enable ADC for battery monitoring
CONFIG_ADC=y

# Enable sensor (temperature & IMU)
CONFIG_SENSOR=y
CONFIG_FPU=y
CONFIG_I2C=y
# CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD=y

# External memory
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_SFDP_DEVICETREE=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

################
# Flash config #
################
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_HEAP_MEM_POOL_SIZE=1024

##############
# BLE config #
##############
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_COMPANY_ID=0x0ef2
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Remote"
CONFIG_BT_SMP=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DM=y
CONFIG_BT_GATT_DM_DATA_PRINT=y
CONFIG_BT_MAX_CONN=3
CONFIG_BT_MAX_PAIRED=10
CONFIG_BT_CONN_CTX=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_MANUFACTURER_DATA_CNT=1
CONFIG_BT_SCAN_CONN_ATTEMPTS_FILTER=y
CONFIG_BT_SCAN_CONN_ATTEMPTS_FILTER_LEN=10
CONFIG_BT_FILTER_ACCEPT_LIST=y
CONFIG_BT_PRIVACY=y
CONFIG_BT_SETTINGS=y

# BLE services
CONFIG_BT_BAS=y
CONFIG_BT_ZEPHYR_NUS=y
CONFIG_BT_DIS=y
CONFIG_BT_DIS_MODEL_NUMBER=n
CONFIG_BT_DIS_MANUF_NAME=n
CONFIG_BT_DIS_PNP=n
CONFIG_BT_DIS_FW_REV=y

# OTA DFU with mcumgr
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y
CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y
CONFIG_MCUMGR_GRP_IMG_STATUS_HOOKS=y

########################
# No memory optimizing #
########################
# Enable log module though RTT
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096
And there's an extract of the functions i called from end of discovering, error or pairing procedure : 
static void accept_list_add_cb(const struct bt_bond_info *info, void *user_data)
{
	int *bond_count = (void *)user_data;
	int err = 0;

	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(&info->addr, addr, sizeof(addr));

	if ((*bond_count) < 0) {
		return;
	}

	/* Check if the bond is with a blinker */
	for (uint8_t i = 0; i < MAX_BLINKER; i++) {
		if (bt_addr_le_cmp(storage_get_blinker_addr(i), &info->addr) == 0) {
			/* It is, so add it to the filter accept list */
			err = bt_le_filter_accept_list_add(&info->addr);
			if (err) {
				LOG_ERR("%s cannot add to filter accept list (err %d)", addr, err);
				(*bond_count) = -EIO;
			} else {
				// LOG_DBG("%s added to the filter accept list", addr);
				(*bond_count)++;
			}
		}
	}
}

static void accept_list_remove_cb(struct bt_conn *conn, void *data)
{
	uint8_t *conn_count = (void *)data;
	struct bt_conn_info info;
	int err = 0;

	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if ((*conn_count) < 0) {
		return;
	}

	/* Check if the connection is with a blinker */
	for (uint8_t i = 0; i < MAX_BLINKER; i++) {
		if (bt_addr_le_cmp(bt_conn_get_dst(conn), storage_get_blinker_addr(i)) == 0) {
			/* It is, is it connected tho ? */
			err = bt_conn_get_info(conn, &info);
			if (err) {
				LOG_ERR("%s failed to get conn info (err %d)", addr, err);
				return;
			}

			if (info.state == BT_CONN_STATE_CONNECTED) {
				/* Blinker is connected, we don't need to reconnect to it */
				err = bt_le_filter_accept_list_remove(bt_conn_get_dst(conn));
				if (err) {
					LOG_ERR("%s cannot remove to filter accept list (err %d)", addr, err);
					(*conn_count) = -EIO;
				} else {
					// LOG_DBG("%s removed to the filter accept list", addr);
					(*conn_count)--;
				}
			}
		}
	}
}

static int auto_conn_procedure(void)
{
	int err = 0;
	uint8_t count = 0;

	/* Check firstly if we have 2 bonded blinker in memory */
	for (uint8_t i = 0; i < MAX_BLINKER; i++) {
		if (bt_addr_le_cmp(storage_get_blinker_addr(i), BT_ADDR_LE_NONE) == 0) {
			LOG_DBG("Auto connection stopped (no address in memory)");
			return -1;
		}
	}

	err = bt_le_filter_accept_list_clear();
	if (err) {
		LOG_ERR("Failed to clear accept list (err %d)", err);
		return err;
	}

	/* Increase count by the number of matching bound */
	bt_foreach_bond(BT_ID_DEFAULT, accept_list_add_cb, &count);
	if (count < MAX_BLINKER) {
		LOG_DBG("Auto connection stopped (not enought bound count : %d)", count);
		return -1;
	}

	/* Decrease count by the number of connected connection */
	bt_conn_foreach(BT_CONN_TYPE_LE, accept_list_remove_cb, &count);
	if (count <= 0) {
		LOG_DBG("Auto connection stopped (enought connection count)");
		return -1;
	}

	err = bt_conn_le_create_auto(BT_CONN_LE_CREATE_CONN_AUTO, BT_LE_CONN_PARAM_DEFAULT);
	if (err) {
		LOG_ERR("Auto connection start failed (err %d)", err);
		return err;
	} else {
		LOG_DBG("Auto connection started");
	}

	return err;
}

static void conn_count_cb(struct bt_conn *conn, void *data)
{
	uint8_t *actual_conn_count = (void *)data;
	struct bt_conn_info info;
	int err = 0;

	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	/* Get conn info */
	err = bt_conn_get_info(conn, &info);
	if (err) {
		LOG_ERR("%s failed to get conn info (err %d)", addr, err);
		return;
	}

	/*  Verify it is active */
	if ((info.state == BT_CONN_STATE_CONNECTED) && (info.role == BT_CONN_ROLE_CENTRAL)) {
		(*actual_conn_count)++;
	}
}

static int scan_procedure(void)
{
	int err = 0;
	uint8_t conn_count = 0;

	/* Make sure we're not scanning */
	err = bt_scan_stop();
	if ((err != 0) && (err != -EALREADY)) {
		LOG_ERR("Scan stop failed (err %d)", err);
		return err;
	}

	bt_conn_foreach(BT_CONN_TYPE_LE, conn_count_cb, &conn_count);
	if (conn_count >= MAX_BLINKER) {
		LOG_DBG("Scan stopped (connection count : %d)", conn_count);
		return -1;
	}

	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	if (err) {
		LOG_ERR("Scan start failed (err %d)", err);
		return err;
	} else {
		LOG_DBG("Scan started");
	}

	return err;
}

static void conn_procedure_work_handler(struct k_work *work)
{
	/* If a discovering is happening, report the work for later */
	if (k_event_test(&event, EVENT_BLE_DISCOVERING)) {
		k_work_schedule(&conn_procedure_work, K_MSEC(CONN_PROCEDURE_RESCHEDULE_MS));
		return;
	}

	if (k_event_test(&event, EVENT_FSM_PAIR)) {
		scan_procedure();
	} else {
		auto_conn_procedure();
	}
}

static void scan_filter_match(struct bt_scan_device_info *device_info, struct bt_scan_filter_match *filter_match,
			      bool connectable)
{
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));

	LOG_INF("%s filters matched", addr);
}

static void scan_connecting_error(struct bt_scan_device_info *device_info)
{
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));

	LOG_ERR("%s connecting error", addr);

	k_work_schedule(&conn_procedure_work, K_NO_WAIT);
}

static void scan_connecting(struct bt_scan_device_info *device_info, struct bt_conn *conn)
{
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));

	LOG_INF("%s connecting", addr);

	bt_conn_ref(conn);
}

BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL, scan_connecting_error, scan_connecting);

static int scan_init(void)
{
	int err = 0;

	struct bt_scan_init_param scan_init = {
		.connect_if_match = true,
		.scan_param = BT_LE_SCAN_ACTIVE,
		.conn_param = BT_LE_CONN_PARAM_DEFAULT,
	};

	bt_scan_init(&scan_init);

	bt_scan_cb_register(&scan_cb);

	/* Filtering */
	adv_mfg_data_s adv_mfg_data = {CONFIG_BT_COMPANY_ID};
	struct bt_scan_manufacturer_data scan_manufacturer_data = {
		.data = (uint8_t *)&adv_mfg_data,
		.data_len = sizeof(adv_mfg_data_s),
	};

	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_MANUFACTURER_DATA, &scan_manufacturer_data);
	if (err) {
		LOG_ERR("Add scan filters failed (err %d)", err);
		return err;
	}

	err = bt_scan_filter_enable(BT_SCAN_MANUFACTURER_DATA_FILTER, false);
	if (err) {
		LOG_ERR("Enable scan filters failed (err %d)", err);
		return err;
	}

	return err;
}
Parents
  • Hi,

    However, i find some issue such as connection to the same device or hci error because no ressource are available. I need help to better understand this procedure and help me make it work.

    Can you please share the exact error messages that you see, as well as provide a full description of when they are happening?

    Regards,
    Terje

  • Hi Tesc,

    Here's how my software works on the central side (my peripheral works as intended) : 

    1. At boot, i submit a task for handling reconnexion - conn_procedure_work_handler (the same i will use when i disconnect or when i get error)

    2. It will check for existing bond in the ble controler and compare it to ble address i store in nvm

    3. If there is a match, the central knows it need to reconnect to peripheral and continue. If not, the procedure end there.

    4.Then, it check for existing conn and check if the address of the conn is the same as the ble address in nvm AND if it is connected (i found out that reconnect can be done on already connected device)

    5. In between, i clear, add and remove ble address to accept list

    6. Now that my accept list has only peripheral with whom i got bond information AND are not connected, i start the bt_conn_le_create_auto.


    The first reboot after bonding works well, here is the log : 

    SEGGER J-Link V8.44a - Real time terminal output
    SEGGER J-Link V9.6, SN=69657316
    Process: JLink.exe
    [00:00:00.003,540] <inf> spi_nor: ZD25WD40B: 512 kiBy flash
    *** Booting My Application v0.1.0-d622f54111fe ***
    *** Using nRF Connect SDK v3.0.1-9eb5615da66b ***
    *** Using Zephyr OS v4.0.99-77f865b8f8d0 ***
    [00:00:00.043,853] <dbg> fsm: init_entry: 
    [00:00:00.050,567] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.050,598] <inf> fs_nvs: alloc wra: 0, fe0
    [00:00:00.050,598] <inf> fs_nvs: data wra: 0, 10
    [00:00:00.050,750] <dbg> settings_storage: storage_init: EF:30:83:A9:91:DC (random) ==> Right blinker
    [00:00:00.050,872] <dbg> settings_storage: storage_init: ED:C1:3A:A4:98:53 (random) ==> Left blinker
    [00:00:00.058,898] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.058,898] <inf> fs_nvs: alloc wra: 0, fa0
    [00:00:00.058,898] <inf> fs_nvs: data wra: 0, bc
    [00:00:00.059,020] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                89 9a 50 8a 95 01 9c 58  fc 39 d2 c1 10 04 ee 02 |..P....X .9......
                                                64 ce 25 be                                      |d.%.             
    [00:00:00.062,286] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.062,316] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.062,347] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 137.20634 Build 2617349514
    [00:00:00.062,622] <inf> bt_hci_core: No ID address. App must call settings_load()
    [00:00:00.063,568] <inf> bt_hci_core: Identity: D5:A2:66:B6:4C:6D (random)
    [00:00:00.063,598] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x10f3, manufacturer 0x0059
    [00:00:00.063,629] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x10f3
    [00:00:00.066,955] <dbg> fsm: idle_entry: 
    [00:00:01.068,328] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:01.137,512] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:01.488,739] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:01.488,861] <dbg> ble: gatt_discover: Discovering started
    [00:00:06.238,555] <inf> ble: Discovery completed
    [00:00:06.239,929] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:06.357,818] <inf> ble: EF:30:83:A9:91:DC (random) connected
    [00:00:06.746,215] <inf> ble: EF:30:83:A9:91:DC security changed level 2
    [00:00:06.746,307] <dbg> ble: gatt_discover: Discovering started
    [00:00:11.746,063] <inf> ble: Discovery completed
    [00:00:11.747,314] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)

    The 1st disconnect of one peripheral is also good, i can reconnect to it without issue.

    SEGGER J-Link V8.44a - Real time terminal output
    SEGGER J-Link V9.6, SN=69657316
    Process: JLink.exe
    [00:00:00.003,540] <inf> spi_nor: ZD25WD40B: 512 kiBy flash
    *** Booting My Application v0.1.0-d622f54111fe ***
    *** Using nRF Connect SDK v3.0.1-9eb5615da66b ***
    *** Using Zephyr OS v4.0.99-77f865b8f8d0 ***
    [00:00:00.043,853] <dbg> fsm: init_entry: 
    [00:00:00.050,567] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.050,598] <inf> fs_nvs: alloc wra: 0, fe0
    [00:00:00.050,598] <inf> fs_nvs: data wra: 0, 10
    [00:00:00.050,750] <dbg> settings_storage: storage_init: EF:30:83:A9:91:DC (random) ==> Right blinker
    [00:00:00.050,872] <dbg> settings_storage: storage_init: ED:C1:3A:A4:98:53 (random) ==> Left blinker
    [00:00:00.058,898] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.058,898] <inf> fs_nvs: alloc wra: 0, fa0
    [00:00:00.058,898] <inf> fs_nvs: data wra: 0, bc
    [00:00:00.059,020] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                89 9a 50 8a 95 01 9c 58  fc 39 d2 c1 10 04 ee 02 |..P....X .9......
                                                64 ce 25 be                                      |d.%.             
    [00:00:00.062,286] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.062,316] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.062,347] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 137.20634 Build 2617349514
    [00:00:00.062,622] <inf> bt_hci_core: No ID address. App must call settings_load()
    [00:00:00.063,568] <inf> bt_hci_core: Identity: D5:A2:66:B6:4C:6D (random)
    [00:00:00.063,598] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x10f3, manufacturer 0x0059
    [00:00:00.063,629] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x10f3
    [00:00:00.066,955] <dbg> fsm: idle_entry: 
    [00:00:01.068,328] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:01.137,512] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:01.488,739] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:01.488,861] <dbg> ble: gatt_discover: Discovering started
    [00:00:06.238,555] <inf> ble: Discovery completed
    [00:00:06.239,929] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:06.357,818] <inf> ble: EF:30:83:A9:91:DC (random) connected
    [00:00:06.746,215] <inf> ble: EF:30:83:A9:91:DC security changed level 2
    [00:00:06.746,307] <dbg> ble: gatt_discover: Discovering started
    [00:00:11.746,063] <inf> ble: Discovery completed
    [00:00:11.747,314] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)
    [00:00:30.788,787] <inf> ble: ED:C1:3A:A4:98:53 (random) disconnected (reason 8)
    [00:00:30.790,283] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:43.892,791] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:44.853,698] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:44.853,790] <dbg> ble: gatt_discover: Discovering started
    [00:00:51.953,491] <inf> ble: Discovery completed
    [00:00:51.954,833] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)

    However, the 2nd disconnect don't work and i get an error when i call bt_conn_le_create_auto (error ENOMEM ==> "Not enough core."). 

    SEGGER J-Link V8.44a - Real time terminal output
    SEGGER J-Link V9.6, SN=69657316
    Process: JLink.exe
    [00:00:00.003,540] <inf> spi_nor: ZD25WD40B: 512 kiBy flash
    *** Booting My Application v0.1.0-d622f54111fe ***
    *** Using nRF Connect SDK v3.0.1-9eb5615da66b ***
    *** Using Zephyr OS v4.0.99-77f865b8f8d0 ***
    [00:00:00.043,853] <dbg> fsm: init_entry: 
    [00:00:00.050,567] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.050,598] <inf> fs_nvs: alloc wra: 0, fe0
    [00:00:00.050,598] <inf> fs_nvs: data wra: 0, 10
    [00:00:00.050,750] <dbg> settings_storage: storage_init: EF:30:83:A9:91:DC (random) ==> Right blinker
    [00:00:00.050,872] <dbg> settings_storage: storage_init: ED:C1:3A:A4:98:53 (random) ==> Left blinker
    [00:00:00.058,898] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.058,898] <inf> fs_nvs: alloc wra: 0, fa0
    [00:00:00.058,898] <inf> fs_nvs: data wra: 0, bc
    [00:00:00.059,020] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                89 9a 50 8a 95 01 9c 58  fc 39 d2 c1 10 04 ee 02 |..P....X .9......
                                                64 ce 25 be                                      |d.%.             
    [00:00:00.062,286] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.062,316] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.062,347] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 137.20634 Build 2617349514
    [00:00:00.062,622] <inf> bt_hci_core: No ID address. App must call settings_load()
    [00:00:00.063,568] <inf> bt_hci_core: Identity: D5:A2:66:B6:4C:6D (random)
    [00:00:00.063,598] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x10f3, manufacturer 0x0059
    [00:00:00.063,629] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x10f3
    [00:00:00.066,955] <dbg> fsm: idle_entry: 
    [00:00:01.068,328] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:01.137,512] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:01.488,739] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:01.488,861] <dbg> ble: gatt_discover: Discovering started
    [00:00:06.238,555] <inf> ble: Discovery completed
    [00:00:06.239,929] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:06.357,818] <inf> ble: EF:30:83:A9:91:DC (random) connected
    [00:00:06.746,215] <inf> ble: EF:30:83:A9:91:DC security changed level 2
    [00:00:06.746,307] <dbg> ble: gatt_discover: Discovering started
    [00:00:11.746,063] <inf> ble: Discovery completed
    [00:00:11.747,314] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)
    [00:00:30.788,787] <inf> ble: ED:C1:3A:A4:98:53 (random) disconnected (reason 8)
    [00:00:30.790,283] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:43.892,791] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:44.853,698] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:44.853,790] <dbg> ble: gatt_discover: Discovering started
    [00:00:51.953,491] <inf> ble: Discovery completed
    [00:00:51.954,833] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)
    [00:01:12.896,301] <inf> ble: EF:30:83:A9:91:DC (random) disconnected (reason 8)
    [00:01:12.897,521] <err> ble: Auto connection start failed (err -12)

    According to comment, this error mean that the controler BLE has not enough free connection object. In my prj.conf, i set CONFIG_BT_MAX_CONN to 3 which make sense with the 1st reconnection working and not the 2nd. What trouble me is that the ble controler should free the bt_conn object at the disconnect callback when i call bt_conn_unref and it seems it don't.


    Here's my connect and disconnect callback : 
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	int err = 0;
    	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_ERR("%s failed to connect (err %u)", addr, conn_err);
    
    		bt_conn_unref(conn);
    
    		k_work_schedule(&conn_procedure_work, K_NO_WAIT);
    		return;
    	}
    
    	LOG_INF("%s connected", addr);
    
    	/* Exit here if the remote is acting as a peripheral */
    	bt_conn_get_info(conn, &info);
    	if (info.role == BT_CONN_ROLE_PERIPHERAL) {
    		return;
    	}
    
    	/* Pairing */
    	err = bt_conn_set_security(conn, BT_SECURITY_L2);
    	if (err) {
    		LOG_ERR("%s failed to set security (err %d)", addr, err);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	int err = 0;
    
    	char addr[BT_ADDR_LE_STR_LEN];
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_INF("%s disconnected (reason %u)", addr, reason);
    	if (reason == BT_HCI_ERR_CONN_FAIL_TO_ESTAB) {
    		/* Delete all possible connection */
    		bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
    		k_work_schedule(&conn_procedure_work, K_NO_WAIT);
    		return;
    	}
    	k_event_post(&event, EVENT_BLE_DISCONNECT);
    
    	/* If there is connection context, update state and then release it */
    	struct blinker_client_s *blinker_client = bt_conn_ctx_get(&conns_ctx_lib, conn);
    	if (blinker_client) {
    		bt_si_blinker_set_state(blinker_client->blinker, STATE_DISCONNECTED);
    		bt_conn_ctx_release(&conns_ctx_lib, (void *)blinker_client);
    		err = bt_conn_ctx_free(&conns_ctx_lib, conn);
    		if (err) {
    			LOG_ERR("%s free connection context failed (err %d)", addr, err);
    		}
    	}
    
    	bt_conn_unref(conn);
    
    	k_work_schedule(&conn_procedure_work, K_NO_WAIT);
    }
Reply
  • Hi Tesc,

    Here's how my software works on the central side (my peripheral works as intended) : 

    1. At boot, i submit a task for handling reconnexion - conn_procedure_work_handler (the same i will use when i disconnect or when i get error)

    2. It will check for existing bond in the ble controler and compare it to ble address i store in nvm

    3. If there is a match, the central knows it need to reconnect to peripheral and continue. If not, the procedure end there.

    4.Then, it check for existing conn and check if the address of the conn is the same as the ble address in nvm AND if it is connected (i found out that reconnect can be done on already connected device)

    5. In between, i clear, add and remove ble address to accept list

    6. Now that my accept list has only peripheral with whom i got bond information AND are not connected, i start the bt_conn_le_create_auto.


    The first reboot after bonding works well, here is the log : 

    SEGGER J-Link V8.44a - Real time terminal output
    SEGGER J-Link V9.6, SN=69657316
    Process: JLink.exe
    [00:00:00.003,540] <inf> spi_nor: ZD25WD40B: 512 kiBy flash
    *** Booting My Application v0.1.0-d622f54111fe ***
    *** Using nRF Connect SDK v3.0.1-9eb5615da66b ***
    *** Using Zephyr OS v4.0.99-77f865b8f8d0 ***
    [00:00:00.043,853] <dbg> fsm: init_entry: 
    [00:00:00.050,567] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.050,598] <inf> fs_nvs: alloc wra: 0, fe0
    [00:00:00.050,598] <inf> fs_nvs: data wra: 0, 10
    [00:00:00.050,750] <dbg> settings_storage: storage_init: EF:30:83:A9:91:DC (random) ==> Right blinker
    [00:00:00.050,872] <dbg> settings_storage: storage_init: ED:C1:3A:A4:98:53 (random) ==> Left blinker
    [00:00:00.058,898] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.058,898] <inf> fs_nvs: alloc wra: 0, fa0
    [00:00:00.058,898] <inf> fs_nvs: data wra: 0, bc
    [00:00:00.059,020] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                89 9a 50 8a 95 01 9c 58  fc 39 d2 c1 10 04 ee 02 |..P....X .9......
                                                64 ce 25 be                                      |d.%.             
    [00:00:00.062,286] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.062,316] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.062,347] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 137.20634 Build 2617349514
    [00:00:00.062,622] <inf> bt_hci_core: No ID address. App must call settings_load()
    [00:00:00.063,568] <inf> bt_hci_core: Identity: D5:A2:66:B6:4C:6D (random)
    [00:00:00.063,598] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x10f3, manufacturer 0x0059
    [00:00:00.063,629] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x10f3
    [00:00:00.066,955] <dbg> fsm: idle_entry: 
    [00:00:01.068,328] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:01.137,512] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:01.488,739] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:01.488,861] <dbg> ble: gatt_discover: Discovering started
    [00:00:06.238,555] <inf> ble: Discovery completed
    [00:00:06.239,929] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:06.357,818] <inf> ble: EF:30:83:A9:91:DC (random) connected
    [00:00:06.746,215] <inf> ble: EF:30:83:A9:91:DC security changed level 2
    [00:00:06.746,307] <dbg> ble: gatt_discover: Discovering started
    [00:00:11.746,063] <inf> ble: Discovery completed
    [00:00:11.747,314] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)

    The 1st disconnect of one peripheral is also good, i can reconnect to it without issue.

    SEGGER J-Link V8.44a - Real time terminal output
    SEGGER J-Link V9.6, SN=69657316
    Process: JLink.exe
    [00:00:00.003,540] <inf> spi_nor: ZD25WD40B: 512 kiBy flash
    *** Booting My Application v0.1.0-d622f54111fe ***
    *** Using nRF Connect SDK v3.0.1-9eb5615da66b ***
    *** Using Zephyr OS v4.0.99-77f865b8f8d0 ***
    [00:00:00.043,853] <dbg> fsm: init_entry: 
    [00:00:00.050,567] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.050,598] <inf> fs_nvs: alloc wra: 0, fe0
    [00:00:00.050,598] <inf> fs_nvs: data wra: 0, 10
    [00:00:00.050,750] <dbg> settings_storage: storage_init: EF:30:83:A9:91:DC (random) ==> Right blinker
    [00:00:00.050,872] <dbg> settings_storage: storage_init: ED:C1:3A:A4:98:53 (random) ==> Left blinker
    [00:00:00.058,898] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.058,898] <inf> fs_nvs: alloc wra: 0, fa0
    [00:00:00.058,898] <inf> fs_nvs: data wra: 0, bc
    [00:00:00.059,020] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                89 9a 50 8a 95 01 9c 58  fc 39 d2 c1 10 04 ee 02 |..P....X .9......
                                                64 ce 25 be                                      |d.%.             
    [00:00:00.062,286] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.062,316] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.062,347] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 137.20634 Build 2617349514
    [00:00:00.062,622] <inf> bt_hci_core: No ID address. App must call settings_load()
    [00:00:00.063,568] <inf> bt_hci_core: Identity: D5:A2:66:B6:4C:6D (random)
    [00:00:00.063,598] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x10f3, manufacturer 0x0059
    [00:00:00.063,629] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x10f3
    [00:00:00.066,955] <dbg> fsm: idle_entry: 
    [00:00:01.068,328] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:01.137,512] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:01.488,739] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:01.488,861] <dbg> ble: gatt_discover: Discovering started
    [00:00:06.238,555] <inf> ble: Discovery completed
    [00:00:06.239,929] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:06.357,818] <inf> ble: EF:30:83:A9:91:DC (random) connected
    [00:00:06.746,215] <inf> ble: EF:30:83:A9:91:DC security changed level 2
    [00:00:06.746,307] <dbg> ble: gatt_discover: Discovering started
    [00:00:11.746,063] <inf> ble: Discovery completed
    [00:00:11.747,314] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)
    [00:00:30.788,787] <inf> ble: ED:C1:3A:A4:98:53 (random) disconnected (reason 8)
    [00:00:30.790,283] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:43.892,791] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:44.853,698] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:44.853,790] <dbg> ble: gatt_discover: Discovering started
    [00:00:51.953,491] <inf> ble: Discovery completed
    [00:00:51.954,833] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)

    However, the 2nd disconnect don't work and i get an error when i call bt_conn_le_create_auto (error ENOMEM ==> "Not enough core."). 

    SEGGER J-Link V8.44a - Real time terminal output
    SEGGER J-Link V9.6, SN=69657316
    Process: JLink.exe
    [00:00:00.003,540] <inf> spi_nor: ZD25WD40B: 512 kiBy flash
    *** Booting My Application v0.1.0-d622f54111fe ***
    *** Using nRF Connect SDK v3.0.1-9eb5615da66b ***
    *** Using Zephyr OS v4.0.99-77f865b8f8d0 ***
    [00:00:00.043,853] <dbg> fsm: init_entry: 
    [00:00:00.050,567] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.050,598] <inf> fs_nvs: alloc wra: 0, fe0
    [00:00:00.050,598] <inf> fs_nvs: data wra: 0, 10
    [00:00:00.050,750] <dbg> settings_storage: storage_init: EF:30:83:A9:91:DC (random) ==> Right blinker
    [00:00:00.050,872] <dbg> settings_storage: storage_init: ED:C1:3A:A4:98:53 (random) ==> Left blinker
    [00:00:00.058,898] <inf> fs_nvs: 2 Sectors of 4096 bytes
    [00:00:00.058,898] <inf> fs_nvs: alloc wra: 0, fa0
    [00:00:00.058,898] <inf> fs_nvs: data wra: 0, bc
    [00:00:00.059,020] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                                89 9a 50 8a 95 01 9c 58  fc 39 d2 c1 10 04 ee 02 |..P....X .9......
                                                64 ce 25 be                                      |d.%.             
    [00:00:00.062,286] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.062,316] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
    [00:00:00.062,347] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 137.20634 Build 2617349514
    [00:00:00.062,622] <inf> bt_hci_core: No ID address. App must call settings_load()
    [00:00:00.063,568] <inf> bt_hci_core: Identity: D5:A2:66:B6:4C:6D (random)
    [00:00:00.063,598] <inf> bt_hci_core: HCI: version 6.0 (0x0e) revision 0x10f3, manufacturer 0x0059
    [00:00:00.063,629] <inf> bt_hci_core: LMP: version 6.0 (0x0e) subver 0x10f3
    [00:00:00.066,955] <dbg> fsm: idle_entry: 
    [00:00:01.068,328] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:01.137,512] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:01.488,739] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:01.488,861] <dbg> ble: gatt_discover: Discovering started
    [00:00:06.238,555] <inf> ble: Discovery completed
    [00:00:06.239,929] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:06.357,818] <inf> ble: EF:30:83:A9:91:DC (random) connected
    [00:00:06.746,215] <inf> ble: EF:30:83:A9:91:DC security changed level 2
    [00:00:06.746,307] <dbg> ble: gatt_discover: Discovering started
    [00:00:11.746,063] <inf> ble: Discovery completed
    [00:00:11.747,314] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)
    [00:00:30.788,787] <inf> ble: ED:C1:3A:A4:98:53 (random) disconnected (reason 8)
    [00:00:30.790,283] <dbg> ble: auto_conn_procedure: Auto connection started
    [00:00:43.892,791] <inf> ble: ED:C1:3A:A4:98:53 (random) connected
    [00:00:44.853,698] <inf> ble: ED:C1:3A:A4:98:53 security changed level 2
    [00:00:44.853,790] <dbg> ble: gatt_discover: Discovering started
    [00:00:51.953,491] <inf> ble: Discovery completed
    [00:00:51.954,833] <dbg> ble: auto_conn_procedure: Auto connection stopped (enought connection count)
    [00:01:12.896,301] <inf> ble: EF:30:83:A9:91:DC (random) disconnected (reason 8)
    [00:01:12.897,521] <err> ble: Auto connection start failed (err -12)

    According to comment, this error mean that the controler BLE has not enough free connection object. In my prj.conf, i set CONFIG_BT_MAX_CONN to 3 which make sense with the 1st reconnection working and not the 2nd. What trouble me is that the ble controler should free the bt_conn object at the disconnect callback when i call bt_conn_unref and it seems it don't.


    Here's my connect and disconnect callback : 
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	int err = 0;
    	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_ERR("%s failed to connect (err %u)", addr, conn_err);
    
    		bt_conn_unref(conn);
    
    		k_work_schedule(&conn_procedure_work, K_NO_WAIT);
    		return;
    	}
    
    	LOG_INF("%s connected", addr);
    
    	/* Exit here if the remote is acting as a peripheral */
    	bt_conn_get_info(conn, &info);
    	if (info.role == BT_CONN_ROLE_PERIPHERAL) {
    		return;
    	}
    
    	/* Pairing */
    	err = bt_conn_set_security(conn, BT_SECURITY_L2);
    	if (err) {
    		LOG_ERR("%s failed to set security (err %d)", addr, err);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	int err = 0;
    
    	char addr[BT_ADDR_LE_STR_LEN];
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_INF("%s disconnected (reason %u)", addr, reason);
    	if (reason == BT_HCI_ERR_CONN_FAIL_TO_ESTAB) {
    		/* Delete all possible connection */
    		bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
    		k_work_schedule(&conn_procedure_work, K_NO_WAIT);
    		return;
    	}
    	k_event_post(&event, EVENT_BLE_DISCONNECT);
    
    	/* If there is connection context, update state and then release it */
    	struct blinker_client_s *blinker_client = bt_conn_ctx_get(&conns_ctx_lib, conn);
    	if (blinker_client) {
    		bt_si_blinker_set_state(blinker_client->blinker, STATE_DISCONNECTED);
    		bt_conn_ctx_release(&conns_ctx_lib, (void *)blinker_client);
    		err = bt_conn_ctx_free(&conns_ctx_lib, conn);
    		if (err) {
    			LOG_ERR("%s free connection context failed (err %d)", addr, err);
    		}
    	}
    
    	bt_conn_unref(conn);
    
    	k_work_schedule(&conn_procedure_work, K_NO_WAIT);
    }
Children
No Data
Related