Issue of NUS example to set PHY, data length, and connection parameters

Hello!

I am programming BLE with the nRF52840-DK. [Toolchain Manager: v1.3.0, IDE: Visual Studio Code (VSCode), SDK: ncs v2.6.0, window11 pro]

I am using two nRF52840-DK devices to communicate via Bluetooth(NUS).

I am adding modifications to the NUS example to adjust PHY, data length, and connection parameters (connection interval, timeout, delay).

Since my search didn't resolve my questions, I decided to create a ticket. 

<my questions>

1. Can you explain the conditions and situations under which the Discovery completed callback in the struct bt_gatt_dm_cb (in 'gatt_dm.h') is triggered?

2. In my central debugging, the le_param_updated callback was triggered even though I didn't use 'bt_conn_le_param_update'. Additionally, I observed that the connection parameters were set to 'interval: 40, latency: 0, timeout: 42' despite setting them to 'BT_LE_CONN_PARAM(80, 80, 0, 400)'. I suspect this is due to 'connection interval negotiation'. Can you provide the cause and a solution for this issue?

[00:00:13.889,343] <inf> cho: CALLBACK - LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
[00:00:14.289,794] <inf> cho: CALLBACK - Service discovery completed
[00:00:14.296,752] <inf> cho: discovery_complete - MTU exchange pending
[00:00:14.689,788] <inf> cho: CALLBACK - MTU exchange done
[00:00:17.889,770] <inf> cho: CALLBACK - Connection parameters updated. >> interval: 40, latency: 0, timeout: 42

additional materials >

- Blow is 'main.c' of central_uart

#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include <bluetooth/scan.h>
#include <bluetooth/gatt_dm.h>
#include <bluetooth/services/nus.h>
#include <bluetooth/services/nus_client.h>
#include <zephyr/settings/settings.h>
#include <zephyr/logging/log.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/printk.h>
#define LOG_MODULE_NAME cho
LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG);
static struct bt_conn *default_conn;
static struct bt_nus_client nus_client;
static struct bt_gatt_exchange_params exchange_params;
#define INTERVAL_MIN	0x50
#define INTERVAL_MAX	0x50
static struct bt_le_conn_param *conn_param = BT_LE_CONN_PARAM(INTERVAL_MIN, INTERVAL_MAX, 0, 400);
uint8_t data_from_central[16384];
int data_received_count = 0;
uint64_t stamp;
int64_t delta; 

static const char *phy2str(uint8_t phy){
	switch (phy) {
	case 0: return "No packets";
	case BT_GAP_LE_PHY_1M: return "LE 1M";
	case BT_GAP_LE_PHY_2M: return "LE 2M";
	case BT_GAP_LE_PHY_CODED: return "LE Coded";
	default: return "Unknown";
	}
}

///////////////////////////////////////////////////////////////////////////

static void ble_data_sent(struct bt_nus_client *nus, uint8_t err, const uint8_t *const data, uint16_t len){
	LOG_INF("ble_data_sent");
}

static uint8_t ble_data_received(struct bt_nus_client *nus, const uint8_t *data, uint16_t len){
	ARG_UNUSED(nus);
	if(data_received_count == 0){
		stamp = k_uptime_get_32();
	}
    memcpy(&data_from_central[data_received_count * len], data, len);
    data_received_count++;
    if (data_received_count >= 60) {	
		delta = k_uptime_delta(&stamp);	
		LOG_INF("time: %llu ms", delta);
        bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
         /*  for (int i = 0; i < data_received_count * len; i++) {
            LOG_INF("data_from_central[%d]:  %d ",i,data_from_central[i]);
        }   */
	   LOG_INF("[local] sent %u bytes (%u KB) in %lld ms at %llu kbps", 244*60, 244 * 60 / 1024, delta, ((uint64_t)244 * 60 * 8 / delta));
		data_received_count = 0;
        LOG_INF("\n");
    }
	return BT_GATT_ITER_CONTINUE;

}

static int nus_client_init(void){
	int err;
	struct bt_nus_client_init_param init = {
		.cb = {
			.received = ble_data_received,
			.sent = ble_data_sent,
		}
	};
	err = bt_nus_client_init(&nus_client, &init);
	LOG_INF("bt_nus_client_init >>> err:%d", err);
	return err;
}

///////////////////////////////////////////////////////////////////////////

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("Filters matched. Address: %s connectable: %d ", addr, connectable);
}

static void scan_connecting_error(struct bt_scan_device_info *device_info){
	LOG_INF("Connecting failed");
}

void scan_filter_no_match(struct bt_scan_device_info *device_info, bool connectable){
	//char addr[BT_ADDR_LE_STR_LEN];
	//bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));
	//LOG_INF("Filter not match. Address: %s connectable: %d", addr, connectable);
}

static void scan_connecting(struct bt_scan_device_info *device_info, struct bt_conn *conn){
	default_conn = bt_conn_ref(conn);
	LOG_INF("<<< scan_connecting >>>>");
}

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

static int scan_init(void){
	int err;
	struct bt_le_scan_param scan_param = { 
		.type = 0x01, //  1: active,  0: passive
		.options = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
		.interval = 0x0010, // 10ms
		.window = 0x0010, // 10ms
	};
	struct bt_scan_init_param scan_init = {
		.connect_if_match = 1,		
		.scan_param = &scan_param,    		//type,  options, interval, window, timeout, interval_coded, window_coded;	
		.conn_param = conn_param  		// interval_min, interval_max, latency, timeout
	};

	bt_scan_init(&scan_init);
	bt_scan_cb_register(&scan_cb);
 	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE);
	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
	return err;
}

//////////////////////////////////////////////////////////////////////////
static void le_param_updated(struct bt_conn *conn, uint16_t interval,  uint16_t latency, uint16_t timeout){
	LOG_INF("CALLBACK - Connection parameters updated. >> interval: %d, latency: %d, timeout: %d", interval, latency, timeout);						
}

static void le_data_length_updated(struct bt_conn *conn, struct bt_conn_le_data_len_info *info){
	LOG_INF("CALLBACK - LE data len updated: TX (len: %d time: %d) RX (len: %d time: %d)", info->tx_max_len, info->tx_max_time, info->rx_max_len, info->rx_max_time);
	default_conn = bt_conn_ref(conn);
}

static void le_phy_updated(struct bt_conn *conn, struct bt_conn_le_phy_info *param){
	LOG_INF("CALLBACK - LE PHY updated: TX PHY %s, RX PHY %s", phy2str(param->tx_phy), phy2str(param->rx_phy));
	default_conn = bt_conn_ref(conn);
}

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

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	if(conn_err){
		LOG_INF("Failed to connect to %s (%d)", addr, conn_err);
		if (default_conn == conn) {
			bt_conn_unref(default_conn);
			default_conn = NULL;
			err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
			LOG_INF("Scanning failed to start (err %d)",err);
		}
		return;
	}
	default_conn = bt_conn_ref(conn);
	err = bt_conn_get_info(conn, &info);
	LOG_INF("connected - GET_INFO >>> err:%d", err);
	LOG_INF("connected - Connected as %s", info.role == BT_CONN_ROLE_CENTRAL ? "central" : "peripheral");
	LOG_INF("connected - Conn. interval is %u units", info.le.interval);

	err = bt_conn_set_security(conn, BT_SECURITY_L2);
	LOG_INF("connected - Set_Security >>> err:%d", err);

	err = bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
	LOG_INF("connected - PHY >>> err:%d", err);

	err = bt_conn_le_data_len_update(conn, BT_LE_DATA_LEN_PARAM_MAX);
	LOG_INF("connected - data_length >>> err:%d", err); 
	
	err = bt_scan_stop(); // success: 0 or -120
	LOG_INF("connected - SCAN_STOP (err %d)", err);
	
	err = bt_conn_get_info(conn, &info);
	LOG_INF("connected - GET_INFO >>> err:%d", err);
	LOG_INF("connected - Conn. interval is %u units", info.le.interval);

}

static void disconnected(struct bt_conn *conn, uint8_t reason){
	char addr[BT_ADDR_LE_STR_LEN];
	int err;
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("disconnected");
	if (default_conn != conn) {
		return;
	}
	bt_conn_unref(default_conn);
	default_conn = NULL;
	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	LOG_INF("bt_scan_restart: %d",err);
}

static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params){
	if (!err) {
		LOG_INF("CALLBACK - MTU exchange done");
	} else {
		LOG_INF("CALLBACK - MTU exchange failed >>> err : PRIu8 ", err);
	}
}

static void discovery_complete(struct bt_gatt_dm *dm, void *context){
	int err;
	struct bt_nus_client *nus = context;
	LOG_INF("CALLBACK - Service discovery completed");
	bt_gatt_dm_data_print(dm);
	bt_nus_handles_assign(dm, nus);
	bt_nus_subscribe_receive(nus);
	bt_gatt_dm_data_release(dm);
	exchange_params.func = exchange_func;
	err = bt_gatt_exchange_mtu(default_conn, &exchange_params);
	if (err) { LOG_INF("discovery_complete - MTU exchange failed (err %d)", err);
	} else { LOG_INF("discovery_complete - MTU exchange pending");}
}

static void discovery_service_not_found(struct bt_conn *conn, void *context){
	LOG_INF("CALLBACK - Service not found");
}

static void discovery_error(struct bt_conn *conn, int err, void *context){
	LOG_INF("CALLBACK - Error while discovering GATT database: (%d)", err);
}

struct bt_gatt_dm_cb discovery_cb = {
	.completed         = discovery_complete,
	.service_not_found = discovery_service_not_found,
	.error_found       = discovery_error,
};

static void gatt_discover(struct bt_conn *conn){
	int err;
	if (conn != default_conn) {
		return;
	}
	err = bt_gatt_dm_start(conn, BT_UUID_NUS_SERVICE, &discovery_cb, &nus_client);
	LOG_INF("gatt_discover - GATT_dm_start: %d", err);
}

static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err){
	 if (!err) {
        LOG_INF("CALLBACK - Security level changed: %u", level);
    } else {
        LOG_INF("CALLBACK - Security change failed: %d", err);
    }
	gatt_discover(conn);
}

static struct bt_conn_cb conn_callbacks = {
	.connected    = connected,
	.disconnected = disconnected,
	.security_changed = security_changed,
	.le_param_updated = le_param_updated,
	.le_data_len_updated = le_data_length_updated,
	.le_phy_updated =  le_phy_updated,
};

 static void pairing_complete(struct bt_conn *conn, bool bonded){
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("CALLBACK - Pairing completed: %s, bonded: %d", addr, bonded);
}

static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason){
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("CALLBACK - Pairing failed conn: %s, reason %d", addr, reason);
}

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
}; 



int main(void){
	int main_err;
	LOG_INF("cho >> 240711_central          //////////////////////////////////////////////////////");
	bt_conn_cb_register(&conn_callbacks);
	main_err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
	main_err = bt_enable(NULL); //LOG_INF("bt_enable: %d",main_err);
	if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}
	scan_init();
	nus_client_init();
	bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	for (;;) {
		k_sleep(K_MSEC(1000));
	}

	return 0;
}

- Blow is 'prj.conf' of central_uart

# UART and Console Settings
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# System and Memory Settings
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=1536

# Bluetooth Settings Storage
CONFIG_BT_SETTINGS=y

# Flash and Non-Volatile Storage (NVS) Settings
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y

# Logging Settings
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=n
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_PRINTK=y
CONFIG_LOG_MODE_IMMEDIATE=y
#CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n


CONFIG_ASSERT=y

# Bluetooth Basic Settings
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
    # Pre-connection settings
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_SCAN_NAME_CNT=5
CONFIG_BT_SCAN_NAME_MAX_LEN=20
    # Post-connection settings
CONFIG_BT_SMP=y
CONFIG_BT_GATT_DM=y
CONFIG_BT_NUS_CLIENT=y
CONFIG_BT_GATT_CLIENT=y


# Bluetooth Memory and Buffer Settings
CONFIG_HEAP_MEM_POOL_SIZE=2048
CONFIG_BT_ATT_PREPARE_COUNT=2
CONFIG_BT_CONN_TX_MAX=10
CONFIG_BT_L2CAP_TX_BUF_COUNT=10
CONFIG_BT_BUF_ACL_TX_COUNT=10

# Bluetooth Physical Layer (PHY) Settings
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_CTLR_PHY_2M=y

# Bluetooth Data Length Settings
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_BUF_ACL_RX_SIZE=251

# Bluetooth Maximum Transmission Unit (MTU) Settings
CONFIG_BT_L2CAP_TX_MTU=247

- Blow is 'debugging' of central_uart

*** Booting nRF Connect SDK v3.5.99-ncs1 ***
[00:00:00.004,486] <inf> cho: cho >> 240711_central          //////////////////////////////////////////////////////
[00:00:00.022,277] <inf> fs_nvs: 8 Sectors of 4096 bytes
[00:00:00.027,954] <inf> fs_nvs: alloc wra: 0, f90
[00:00:00.033,142] <inf> fs_nvs: data wra: 0, 9c
[00:00:00.038,360] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                            36 f0 e5 0e 87 68 48 fb  02 fd 9f 82 cc 32 e5 7b |6....hH. .....2.{
                                            91 b1 5c ed                                      |..\.             
[00:00:00.068,756] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
[00:00:00.076,538] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
[00:00:00.083,038] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 54.58864 Build 1214809870
[00:00:00.094,818] <inf> bt_hci_core: No ID address. App must call settings_load()
[00:00:00.103,424] <inf> bt_hci_core: Identity: C2:82:F6:94:03:85 (random)
[00:00:00.110,687] <inf> bt_hci_core: HCI: version 5.4 (0x0d) revision 0x118f, manufacturer 0x0059
[00:00:00.120,056] <inf> bt_hci_core: LMP: version 5.4 (0x0d) subver 0x118f
[00:00:00.128,570] <inf> cho: bt_nus_client_init >>> err:0
[00:00:12.078,948] <inf> cho: Filters matched. Address: EE:3E:4D:30:14:7D (random) connectable: 0 
[00:00:12.089,385] <inf> cho: <<< scan_connecting >>>>
[00:00:12.188,415] <inf> cho: connected - GET_INFO >>> err:0
[00:00:12.194,580] <inf> cho: connected - Connected as central
[00:00:12.200,805] <inf> cho: connected - Conn. interval is 80 units
[00:00:12.207,824] <inf> cho: connected - Set_Security >>> err:0
[00:00:12.214,508] <inf> cho: connected - PHY >>> err:0
[00:00:12.220,397] <inf> cho: connected - data_length >>> err:0
[00:00:12.226,684] <inf> cho: connected - SCAN_STOP (err -120)
[00:00:12.232,940] <inf> cho: connected - GET_INFO >>> err:0
[00:00:12.239,013] <inf> cho: connected - Conn. interval is 80 units
[00:00:12.489,959] <err> bt_smp: pairing failed (peer reason 0x3)
[00:00:12.496,826] <inf> cho: CALLBACK - Security change failed: 4
[00:00:12.503,448] <inf> cho: gatt_discover - GATT_dm_start: 0
[00:00:12.509,735] <inf> cho: CALLBACK - Pairing failed conn: EE:3E:4D:30:14:7D (random), reason 4
[00:00:12.889,923] <inf> cho: CALLBACK - LE data len updated: TX (len: 251 time: 2120) RX (len: 251 time: 2120)
[00:00:13.889,343] <inf> cho: CALLBACK - LE PHY updated: TX PHY LE 2M, RX PHY LE 2M
[00:00:14.289,794] <inf> cho: CALLBACK - Service discovery completed
[00:00:14.296,752] <inf> cho: discovery_complete - MTU exchange pending
[00:00:14.689,788] <inf> cho: CALLBACK - MTU exchange done
[00:00:17.889,770] <inf> cho: CALLBACK - Connection parameters updated. >> interval: 40, latency: 0, timeout: 42
[00:00:19.025,604] <inf> cho: time: 85 ms
[00:00:19.030,639] <inf> cho: [local] sent 14640 bytes (14 KB) in 85 ms at 1377 kbps
[00:00:19.038,757] <inf> cho: 

[00:00:19.091,156] <inf> cho: disconnected
[00:00:19.096,618] <inf> cho: bt_scan_restart: 0

- Blow is 'main.c' of peripheral_uart

#include <bluetooth/services/nus.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/settings/settings.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/printk.h>
#define STACKSIZE CONFIG_BT_NUS_THREAD_STACK_SIZE
#define PRIORITY 7
#define LOG_MODULE_NAME cho
LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG);
#define DEVICE_NAME "SEONGMIN"
#define DEVICE_NAME_LEN	(sizeof(DEVICE_NAME) - 1)
#define MTU_SIZE 244
uint8_t data_to_central[MTU_SIZE][2];
static struct bt_conn *current_conn;
//static K_SEM_DEFINE(ble_init_ok, 0, 1);
static K_SEM_DEFINE(disconnect_sem, 0, 1);
static K_SEM_DEFINE(param_ok, 0, 1);
static K_SEM_DEFINE(data_length_ok, 0, 1);
static K_SEM_DEFINE(phy_ok, 0, 1);

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};

static const struct bt_data sd[] = {
	BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
};

static const char *phy2str(uint8_t phy){
	switch (phy) {
	case 0: return "No packets";
	case BT_GAP_LE_PHY_1M: return "LE 1M";
	case BT_GAP_LE_PHY_2M: return "LE 2M";
	case BT_GAP_LE_PHY_CODED: return "LE Coded";
	default: return "Unknown";
	}
}


static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
{
	char addr[BT_ADDR_LE_STR_LEN] = {0};
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, ARRAY_SIZE(addr));
	LOG_INF("Received data from: %s", addr);
	/* 
		DATA PROCESS STEP
	 */

}

static void bt_sent_cb(struct bt_conn *conn){
	LOG_INF("bt_sent_cb");
}

static struct bt_nus_cb nus_cb = {
	.received = bt_receive_cb,
	//.sent = bt_sent_cb,
};

///////////////////////////////////////////////////////////////////////////////////

static void pairing_complete(struct bt_conn *conn, bool bonded){
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("CALLBACK - Pairing completed: %s, bonded: %d", addr, bonded);
}

static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason){
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("CALLBACK - Pairing failed conn: %s, reason %d", addr, reason);
}

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
};

//////////////////////////////////////////////////////////////////////////////////

static void le_param_updated(struct bt_conn *conn, uint16_t interval,  uint16_t latency, uint16_t timeout){
	LOG_INF("CALLBACK - Connection parameters updated. >> interval: %d, latency: %d, timeout: %d", interval, latency, timeout);
	k_sem_give(&param_ok);
}

static void le_data_length_updated(struct bt_conn *conn, struct bt_conn_le_data_len_info *info){
	LOG_INF("CALLBACK - len updated: TX (len: %d time: %d) RX (len: %d time: %d)", info->tx_max_len, info->tx_max_time, info->rx_max_len, info->rx_max_time);
	k_sem_give(&data_length_ok);
}

static void le_phy_updated(struct bt_conn *conn, struct bt_conn_le_phy_info *param){
	LOG_INF("CALLBACK - TX PHY %s, RX PHY %s", phy2str(param->tx_phy), phy2str(param->rx_phy));
	k_sem_give(&phy_ok);
}

static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err){
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("CALLBACK - security_changed: %s, level: %u,  err: %d", addr, level, err);
}

static void disconnected(struct bt_conn *conn, uint8_t reason){
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("CALLBACK - Disconnected: %s (reason %u)", addr, reason);	
	k_sem_give(&disconnect_sem);
}

static void connected(struct bt_conn *conn, uint8_t err){
	char addr[BT_ADDR_LE_STR_LEN];
	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	if (err) {
		LOG_INF("connected - connected: Connection failed (err %u)", err);
		return;
	}
	LOG_INF("connected - Connected %s", addr);
	current_conn = bt_conn_ref(conn);
	struct bt_conn_info info = {0};
	err = bt_conn_get_info(conn, &info);
	LOG_INF("connected - bt_conn_get_info >>> err:%d", err);
	LOG_INF("connected - Connected as %s", info.role == BT_CONN_ROLE_CENTRAL ? "central" : "peripheral");
	LOG_INF("connected - Conn. interval is %u units", info.le.interval);
}

static struct bt_conn_cb conn_callbacks = {
	.connected    = connected,
	.disconnected = disconnected,
	.security_changed = security_changed,
	.le_param_updated = le_param_updated,
	.le_data_len_updated = le_data_length_updated,
	.le_phy_updated =  le_phy_updated,
};


int main(void){
	int err;
	for(int x=0; x<MTU_SIZE; x++){
		data_to_central[x][0] = x;
		data_to_central[x][1] = x;
	}
	LOG_INF("cho >> 240712_peripheral     //////////////////////////////////////////////////////");
	bt_conn_cb_register(&conn_callbacks); 
	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); 
	err = bt_enable(NULL);
	LOG_INF("bt_enable: %d",err);
	if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}		
	err = bt_nus_init(&nus_cb); //LOG_INF("bt_nus_init: %d",err);
	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
	LOG_INF("bt_le_adv_start: %d",err);	
	while(1){ k_sleep(K_MSEC(1000)); }
	return 0;
}

void ble_write_thread(void){
	int ret;
	k_sem_take(&param_ok, K_FOREVER);
	k_sem_take(&data_length_ok, K_FOREVER);
	k_sem_take(&phy_ok, K_FOREVER);
	k_sleep(K_MSEC(1000)); 
	LOG_INF("Starting BLE Write Thread");
	while (1) {
        ret = bt_nus_send(current_conn, data_to_central, MTU_SIZE);
		if (k_sem_take(&disconnect_sem, K_NO_WAIT) == 0) {
            LOG_INF("Disconnected, exiting BLE Write Thread");
            return;
        }
	}
}

K_THREAD_DEFINE(ble_write_thread_id, 1024, ble_write_thread, NULL, NULL, NULL, PRIORITY, 0, 0);

- Blow is 'prj.conf' of peripheral_uart

# UART and Console Settings
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# Flash and Non-Volatile Storage (NVS) Settings
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y

# System and Memory Settings
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=1536

# Logging Settings
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=n
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_PRINTK=y
CONFIG_LOG_MODE_IMMEDIATE=y

CONFIG_ASSERT=y

# Bluetooth Settings Storage
CONFIG_BT_SETTINGS=y

# Bluetooth Basic Settings
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="SEONGMIN"
CONFIG_BT_NUS=y
CONFIG_BT_SMP=y

CONFIG_BT_MAX_CONN=1
CONFIG_BT_MAX_PAIRED=1
#CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n

# Bluetooth Memory and Buffer Settings
CONFIG_HEAP_MEM_POOL_SIZE=2048
CONFIG_BT_ATT_PREPARE_COUNT=2
CONFIG_BT_CONN_TX_MAX=10
CONFIG_BT_L2CAP_TX_BUF_COUNT=10
CONFIG_BT_BUF_ACL_TX_COUNT=10

# Bluetooth Physical Layer (PHY) Settings
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_CTLR_PHY_2M=y

# Bluetooth Data Length Settings
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_BUF_ACL_RX_SIZE=251

# Bluetooth Maximum Transmission Unit (MTU) Settings
CONFIG_BT_L2CAP_TX_MTU=247

- Blow is 'debugging' of peripheral_uart

*** Booting nRF Connect SDK v3.5.99-ncs1 ***
[00:00:00.004,486] <inf> cho: cho >> 240712_peripheral     //////////////////////////////////////////////////////
[00:00:00.021,362] <inf> fs_nvs: 8 Sectors of 4096 bytes
[00:00:00.027,008] <inf> fs_nvs: alloc wra: 0, f30
[00:00:00.032,196] <inf> fs_nvs: data wra: 0, 184
[00:00:00.037,475] <inf> bt_sdc_hci_driver: SoftDevice Controller build revision: 
                                            36 f0 e5 0e 87 68 48 fb  02 fd 9f 82 cc 32 e5 7b |6....hH. .....2.{
                                            91 b1 5c ed                                      |..\.             
[00:00:00.067,687] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
[00:00:00.075,408] <inf> bt_hci_core: HW Variant: nRF52x (0x0002)
[00:00:00.081,909] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 54.58864 Build 1214809870
[00:00:00.093,597] <inf> bt_hci_core: No ID address. App must call settings_load()
[00:00:00.101,501] <inf> cho: bt_enable: 0
[00:00:00.107,208] <inf> bt_hci_core: Identity: EE:3E:4D:30:14:7D (random)
[00:00:00.114,440] <inf> bt_hci_core: HCI: version 5.4 (0x0d) revision 0x118f, manufacturer 0x0059
[00:00:00.123,748] <inf> bt_hci_core: LMP: version 5.4 (0x0d) subver 0x118f
[00:00:00.134,613] <inf> cho: bt_le_adv_start: 0
[00:00:00.257,202] <inf> cho: connected - Connected C2:82:F6:94:03:85 (random)
[00:00:00.264,831] <inf> cho: connected - bt_conn_get_info >>> err:0
[00:00:00.271,545] <inf> cho: connected - Connected as peripheral
[00:00:00.278,045] <inf> cho: connected - Conn. interval is 80 units
[00:00:00.357,788] <inf> cho: CALLBACK - security_changed: C2:82:F6:94:03:85 (random), level: 1,  err: 4
[00:00:00.367,645] <inf> cho: CALLBACK - Pairing failed conn: C2:82:F6:94:03:85 (random), reason 4
[00:00:00.857,940] <inf> cho: CALLBACK - len updated: TX (len: 251 time: 2120) RX (len: 251 time: 2120)
[00:00:01.957,092] <inf> cho: CALLBACK - TX PHY LE 2M, RX PHY LE 2M
[00:00:05.957,550] <inf> cho: CALLBACK - Connection parameters updated. >> interval: 40, latency: 0, timeout: 42
[00:00:06.968,170] <inf> cho: Starting BLE Write Thread
[00:00:07.159,149] <inf> cho: CALLBACK - Disconnected: C2:82:F6:94:03:85 (random) (reason 19)

Parents
  • Cho,

    1. Can you explain the conditions and situations under which the Discovery completed callback in the struct bt_gatt_dm_cb (in 'gatt_dm.h') is triggered?

    The Discovery completed callback in the struct bt_gatt_dm_cb is triggered when the discovery procedure has completed successfully. This callback function is part of the struct bt_gatt_dm_cb structure, which is used for tracking the result of a discovery.When you trigger the process of service discovert by calling the bt_gatt_dm_start() function. If the service discovery is performed and the service is found, the Discovery completed callback is triggered. After the service discovery is performed and if the service is found, you will receive the callback to the completed's callback.

    2. In my central debugging, the le_param_updated callback was triggered even though I didn't use 'bt_conn_le_param_update'. Additionally, I observed that the connection parameters were set to 'interval: 40, latency: 0, timeout: 42' despite setting them to 'BT_LE_CONN_PARAM(80, 80, 0, 400)'. I suspect this is due to 'connection interval negotiation'. Can you provide the cause and a solution for this issue?
    We might get a lot of answers if you capture the air sniffer logs of the whole update process in question and we could analyze packet by packet of what is happening between the central and peripheral. But we can try to have some theories below,
    The le_param_updated callback is triggered when the connection parameters for a Bluetooth Low Energy (BLE) connection have been updated. This can happen automatically even if you didn't manually call bt_conn_le_param_update.
    The automatic update could be due to the CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS in your prj. conf option in the Nordic SDK. When this option is enabled, the peripheral device will automatically request changes to the connection parameters to try to get the preferred values if the initial parameters given by the central don't match the peripheral's preferred parameters. This is why you see the le_param_updated callback being triggered.
    As for the connection parameters being set to 'interval: 40, latency: 0, timeout: 42' despite setting them to 'BT_LE_CONN_PARAM(80, 80, 0, 400)', this could be due to the central device not accepting the requested parameters. The central device has the final say in the connection parameters, and it may not accept the requested parameters if they don't meet its own constraints or preferences.
    To solve this issue, you can try the following:
    1. Disable the automatic update of connection parameters by setting CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n in your prj.conf file. This will prevent the peripheral from automatically requesting changes to the connection parameters.
    2. Make sure the connection parameters you're requesting are within the acceptable range for the central device. Some devices may not accept certain values, such as a very short connection interval.
    3. If you want to manually request a connection parameter update, you can use the bt_conn_le_param_update function. However, keep in mind that this is only a request, and the central device may still not accept the requested parameters.
  • Thanks to your advice

    I was able to think about the issues from a broader perspective. I also studied carefully by looking at the GATT, Service, and Discovery parts of the code.

    In the 'central - main.c' code, I did not define the desired conn_interval for the '.conn_param' variable in the 'struct bt_scan_init_param'. Then, I updated the desired conn interval in the connected callback( via bt_conn_le_param_update function), and the issue was resolved.

    I have some questions.

    1. I'm not sure why this resolved the issue. Does the .conn_param of struct bt_scan_init_param affect the bt_conn_le_param_update function?
    2. I'm getting an error "[00:02:45.506,134] <err> bt_smp: pairing failed (peer reason 0x3)" between two nRF52840-DKs. However, there is no pairing issue between an nRF52840 and an nRF52840-DK. What can I do to resolve this issue? Can you help me?
Reply
  • Thanks to your advice

    I was able to think about the issues from a broader perspective. I also studied carefully by looking at the GATT, Service, and Discovery parts of the code.

    In the 'central - main.c' code, I did not define the desired conn_interval for the '.conn_param' variable in the 'struct bt_scan_init_param'. Then, I updated the desired conn interval in the connected callback( via bt_conn_le_param_update function), and the issue was resolved.

    I have some questions.

    1. I'm not sure why this resolved the issue. Does the .conn_param of struct bt_scan_init_param affect the bt_conn_le_param_update function?
    2. I'm getting an error "[00:02:45.506,134] <err> bt_smp: pairing failed (peer reason 0x3)" between two nRF52840-DKs. However, there is no pairing issue between an nRF52840 and an nRF52840-DK. What can I do to resolve this issue? Can you help me?
Children
No Data
Related