I have a Bluetooth device that has a long characteristic. On previous central device projects there is usually a function like read_long_char. I am trying to get a zephyr-based product up and going which has to make multiple calls to read at 19 bytes per transaction. I need to speed this up, I think what I want is a larger MTU.
I have been trying to update the MTU within Zephyr but I am not having much luck. I have attempted to use information from other support cases as well.
I am running Zephyr 2.6.99
Here is the relevant conf file, BT settings copied from https://github.com/nrfconnect/sdk-nrf/tree/main/samples/bluetooth/throughput
CONFIG_BT=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_CONN=2 CONFIG_BT_SCAN=y CONFIG_BT_SCAN_FILTER_ENABLE=y CONFIG_BT_SCAN_UUID_CNT=1 CONFIG_BT_THROUGHPUT=y CONFIG_BT_GATT_DM=y CONFIG_HEAP_MEM_POOL_SIZE=2048 CONFIG_BT_USER_DATA_LEN_UPDATE=y CONFIG_BT_BUF_ACL_RX_SIZE=251 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_CONN_TX_MAX=10 CONFIG_BT_L2CAP_TX_BUF_COUNT=10 CONFIG_BT_L2CAP_TX_MTU=247 CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_CTLR_PHY_2M=y CONFIG_BT_CTLR_RX_BUFFERS=2 CONFIG_BT_BUF_ACL_TX_COUNT=10 CONFIG_BT_BUF_ACL_TX_SIZE=251 CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
I attempt the MTU update after services have been discovered:
static void ebl_set_mtu_cb(struct bt_conn *conn, uint8_t att_err, struct bt_gatt_exchange_params *params) { struct bt_conn_info info = {0}; int err; if (att_err) { LOG_DBG("MTU exchange failed"); } else { LOG_DBG("MTU exchange successful"); } LOG_DBG("MTU size is: %d", bt_gatt_get_mtu(conn)); err = bt_conn_get_info(conn, &info); if (err) { LOG_ERR("Failed to get connection info %d", err); return; } LOG_DBG("MTU exchange complete"); ctx.app_state = APP_STATE_MTU_SET; } static void ebl_set_conn_mtu() { int err = bt_conn_le_data_len_update(ctx.btle_device.default_conn, BT_LE_DATA_LEN_PARAM_MAX); if (err) { LOG_DBG("LE data length update failed: %d", err); } else { LOG_DBG("LE data length set to MAX"); } ctx.btle_device.exchange_params.func = ebl_set_mtu_cb; LOG_DBG("MTU size is: %d", bt_gatt_get_mtu(ctx.btle_device.default_conn)); int ex_err = bt_gatt_exchange_mtu(ctx.btle_device.default_conn, &ctx.btle_device.exchange_params); if (ex_err) { LOG_DBG("MTU exchange failed (err %d)", ex_err); } else { LOG_DBG("MTU exchange pending"); } ctx.app_state = APP_STATE_SETTING_MTU; }
Output, MTU is never changed:
[00:06:52.830,444] <dbg> e2e_btle.scan_cb: D6:CA:73:E7:32:15 -38 v0.2 [00:06:52.916,931] <inf> e2e_btle: Attempting to connect to: D6:CA:73:E7:32:15 (random) [00:06:54.038,055] <inf> e2e_btle: Connected: D6:CA:73:E7:32:15 (random) [00:06:55.239,624] <dbg> e2e_btle.ebl_discover_func: [ATTRIBUTE] handle 14, type 2800, uuid 00000001-6f73-6e65-5364-6e4532646e45, permission 0 [00:06:56.839,660] <dbg> e2e_btle.ebl_discover_func: [ATTRIBUTE] handle 15, type 2803, uuid , permission 0 [00:06:56.839,874] <dbg> e2e_btle.ebl_discover_func: [CHARACTERISTIC] handle 16, properties 10, uuid 00000003-6f73-6e65-5364-6e4532646e45, [00:06:57.639,617] <dbg> e2e_btle.ebl_discover_func: [ATTRIBUTE] handle 17, type 2803, uuid , permission 0 [00:06:57.639,801] <dbg> e2e_btle.ebl_discover_func: [CHARACTERISTIC] handle 18, properties 18, uuid 00000002-6f73-6e65-5364-6e4532646e45, Connection parameters update request received. Minimum interval: 80, Maximum interval: 160 Latency: 0, Timeout: 500 [00:06:58.439,422] <dbg> e2e_btle.ebl_discover_func: Discover complete [00:06:58.521,789] <dbg> e2e_btle.ebl_set_conn_mtu: LE data length set to MAX [00:06:58.521,789] <dbg> e2e_btle.ebl_set_conn_mtu: MTU size is: 23 [00:06:58.521,911] <dbg> e2e_btle.ebl_set_conn_mtu: MTU exchange pending [00:06:59.239,257] <dbg> e2e_btle.ebl_set_mtu_cb: MTU exchange successful [00:06:59.239,257] <dbg> e2e_btle.ebl_set_mtu_cb: MTU size is: 23 [00:06:59.239,257] <dbg> e2e_btle.ebl_set_mtu_cb: MTU exchange complete
I am new to Zephyr, any help would be greatly appreciated. I can enable HCI debugging or any other debugging if that would help.