NCS 3.1.0 vble connect error at bt_hci_cmd_send_sync()

I am using nrf54l15 with NCS v3.1.0 with the following error when i connect it(i worked in NCS v2.9.1 successfully):

Controller unresponsive, command opcode 0x2035 timeout with err -11 in bt_hci_cmd_send_sync() function;
some error log info:

for matching ncs 3.1.0 I change this code:

bt_hci_cmd_create()  was  deprecated,

So, I modified the functionality implemented with bt_hci_cmd_create to the code shown in the above image. Now it compiles successfully, but when connecting to the device and trying to reset the transmit power, the errors mentioned earlier occur.

My solution is to place set_tx_power inside a k_work_init_delayable for initialization and call it upon connection, while also stopping advertising during the connection. With this approach, the device can now connect successfully.

   

MY BT configs:

CONFIG_BT=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_LOG_LEVEL_WRN=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_CTLR_SDC_TX_PACKET_COUNT=10
CONFIG_BT_BUF_EVT_RX_COUNT=12
CONFIG_BT_BUF_ACL_TX_COUNT=10
CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_DATA_LEN_UPDATE=y
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
I would like to ask whether there is a correct solution to the aforementioned connection issue, or if my current solution is acceptable. If it is, why does modifying it in this way fix the connection problem?

Thank you very much!

Parents Reply Children
  • Hi,

    The Tx power you set for the advertising is also used for the connection that results from that advertising (though it can subsequently be chnaged for the connection if needed).

  • Now I tried disabling this config(CONFIG_BT_USER_DATA_LEN_UPDATE)and this code of picture, than the connection works normally. Could you tell me why handling it this way resolves the connection  problem?

    Thank you very much!

  • Hi,

    I do not see the code where you do length update, but likely you are calling it from teh conneted callback similar as you do with bt_conn_le_phy_update()? That should not be done and insted it shoudl be deferred to later usin gfor instance a workqueue, as we have discussed earlier in this thread.

    If this does not resolve it, can you share your code (as text, not screenshots, and showing all relevant Bluetooth parts so that I get an understanding), as well as explain in wat whay connection fails now?

  • MY BT configs:

    CONFIG_BT=y
    CONFIG_BT_GATT_CLIENT=y
    CONFIG_BT_LOG_LEVEL_WRN=y
    CONFIG_BT_USER_PHY_UPDATE=y
    CONFIG_BT_CTLR_SDC_TX_PACKET_COUNT=10
    CONFIG_BT_BUF_EVT_RX_COUNT=12
    CONFIG_BT_BUF_ACL_TX_COUNT=10
    CONFIG_BT_L2CAP_TX_MTU=247
    CONFIG_BT_BUF_ACL_RX_SIZE=251
    CONFIG_BT_BUF_ACL_TX_SIZE=251
    CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
    # CONFIG_BT_USER_DATA_LEN_UPDATE=y
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    .......................
    MY BT CON or  DISCON:
    /**
     * @brief 交换 mtu 的结果
     */
    static void exchange_func(struct bt_conn *conn, uint8_t att_err,
                              struct bt_gatt_exchange_params *params)
    {
        LOG_INF("MTU exchange %s", att_err == 0 ? "successful" : "failed");

        if (!att_err) {
            LOG_INF("New MTU: %d bytes", bt_gatt_get_mtu(conn) - 3);
        }
    }

    /**
     * @brief 连接后和主机交互确定 mtu 大小.
     *
     * @param[in] conn 指向本次连接.
     */
    static void update_mtu(struct bt_conn *conn)
    {
        __ASSERT(conn != NULL, "conn is null \n");

        int err;
        m_exchange_params.func = exchange_func;

        err = bt_gatt_exchange_mtu(conn, &m_exchange_params);
        if (err) {
            LOG_ERR("bt_gatt_exchange_mtu failed (err %d)", err);
        }
    }

    /**
     * @brief 更新连接参数 work 处理
     */
    static void update_conn_work_hdl(struct k_work *work)
    {
        update_connection_interval(m_current_conn);
        update_mtu(m_current_conn);
    }

    /**
     * @brief mtu 更新后的结果
     */
    static void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
    {
        LOG_INF("Updated MTU: TX: %d RX: %d bytes", tx, rx);
        uint8_t tmp_buf[6] = { 0 };
        tmp_buf[0] = (tx >> 8) & 0xFF;
        tmp_buf[1] = tx & 0xFF;
        tmp_buf[2] = (tx >> 8) & 0xFF;
        tmp_buf[3] = tx & 0xFF;

        cfg_evt_t evt;
        if (m_cfg_callback) {
            evt.evt_id = CFG_EVT_MTU_UPDATED;
            evt.p_data = tmp_buf;
            evt.len = 4;
            m_cfg_callback(&evt);
        }
    }

    /**
     * @brief 连接处理函数
     */
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
        int ret;
        static uint16_t hci_handle;

        if (conn_err != 0) {
            return;
        }

        m_current_conn = bt_conn_ref(conn);
        m_conn_statu = true;

        ret = bt_hci_get_conn_handle(m_current_conn, &hci_handle);
        if (ret) {
            LOG_WRN("No connection handle (err %d)\n", ret);
        } else {
            app_update_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN, hci_handle);
            LOG_INF("hci_handle=0x%x", hci_handle);
        }

        if (m_dev_role == DEV_ROLE_PER) {
            k_work_reschedule(&m_conn_param_work, K_NO_WAIT);
            app_peripheral_conn_process(m_current_conn);
        } else if (m_dev_role == DEV_ROLE_CEN) {
            database_data_t *p_dbs_realtime = app_get_realtime_pointer();
            if (p_dbs_realtime->work_phy == DEV_WORK_PHY_CODED) {
                struct bt_conn_le_phy_param param = {
                    .options = BT_CONN_LE_PHY_OPT_CODED_S8,
                    .pref_rx_phy = BT_GAP_LE_PHY_CODED,
                    .pref_tx_phy = BT_GAP_LE_PHY_CODED,
                };
                bt_conn_le_phy_update(m_current_conn, &param);
            }
            app_central_connected(m_current_conn);
        }
    }

    /**
     * @brief 断开连接处理函数
     */
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
        m_conn_statu = false;
        if (m_current_conn) {
            bt_conn_unref(m_current_conn);
            m_current_conn = NULL;
        }
        if (m_dev_role == DEV_ROLE_PER) {
            app_peripheral_disc_process();
        } else if (m_dev_role == DEV_ROLE_CEN) {
            app_clear_central_statu();
        }
        LOG_INF("disconnected reson=%d", reason);
    }

    /**
     * @brief 连接参数更新结果函数.
     *
     * @param[in] conn      连接指针
     * @param[in] interval  最小连接间隔
     * @param[in] latency   主从通信跳过的连接间隔个数
     * @param[in] timeout   主从通信超时时间
     */
    static void le_param_updated(struct bt_conn *conn, uint16_t interval,
                                 uint16_t latency, uint16_t timeout)
    {
        LOG_INF("conn int: %dms, latency: %d, timeout: %dms", (interval * 5) / 4,
                latency, timeout * 10);
        app_set_ccon_over();
    }

    static void le_phy_updated(struct bt_conn *conn,
                               struct bt_conn_le_phy_info *param)
    {
        LOG_INF("LE PHY updated: TX PHY %u, RX PHY %u\n", param->tx_phy,
                param->rx_phy);
    }

    /**
     * @brief 主机收到从机连接参数更新请求处理函数.
     *
     * @param[in] conn      连接指针
     * @param[in] param     从机请求的连接参数
     *
     * @return  true:主机接受从机连接参数
     *          false: 主机不接受从机连接参数
     */
    static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
    {
        LOG_INF("Connection parameters update request received.\n");
        LOG_INF("Minimum interval: %d, Maximum interval: %d\n", param->interval_min,
                param->interval_max);
        LOG_INF("Latency: %d, Timeout: %d\n", param->latency, param->timeout);
        return true;
    }

    /**
     * @brief 主从 data length 更新上报函数.
     *
     * @param[in] conn      连接指针
     * @param[in] info      更新后的 data length 参数
     */
    static void le_data_length_updated(struct bt_conn *conn,
                                       struct bt_conn_le_data_len_info *info)
    {
        LOG_INF("LE data len updated: TX (len: %d time: %d)"
                " RX (len: %d time: %d)\n",
                info->tx_max_len, info->tx_max_time, info->rx_max_len,
                info->rx_max_time);
    }

    BT_CONN_CB_DEFINE(conn_callbacks) = {
        .connected = connected,
        .disconnected = disconnected,
        .le_param_updated = le_param_updated,
        .le_phy_updated = le_phy_updated,
        .le_param_req = le_param_req,
        // .le_data_len_updated = le_data_length_updated,
    };

    /**
     * @brief 强制断开连接 work 处理
     */
    static void disc_work_hdl(struct k_work *work)
    {
        if (m_conn_statu) {
            bt_conn_disconnect(m_current_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
        }
    }

    /**
     * @brief 设置 BLE 发射功率.
     */
    static void set_tx_power(uint8_t handle_type, uint16_t handle,
                             int8_t tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_write_tx_power_level *cp;
        struct bt_hci_rp_vs_write_tx_power_level *rp;
        struct bt_hci_cmd_hdr *hdr;
        struct net_buf *buf, *rsp = NULL;
        int err;

        buf = bt_hci_cmd_alloc(K_FOREVER);

        hdr = net_buf_push(buf, sizeof(*hdr));
        hdr->opcode = sys_cpu_to_le16(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL);
        hdr->param_len = sizeof(*cp);

        net_buf_push_u8(buf, BT_HCI_H4_CMD);
        __ASSERT(buf, "Unable to allocate command buffer\n");

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
        cp->tx_power_level = tx_pwr_lvl;

        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL, buf, &rsp);
        if (err) {
            uint8_t reason =
                rsp ? ((struct bt_hci_rp_vs_write_tx_power_level *)rsp->data)
                          ->status :
                      0;
            LOG_ERR("Set Tx power err: %d reason 0x%02x\n", err, reason);
        }
        __ASSERT(err == 0, "bt_hci_cmd_send_sync err\n");

        rp = (void *)rsp->data;
        LOG_INF("set tx power: %d", rp->selected_tx_power);

        net_buf_unref(rsp);
    }

    void app_get_dev_addr(void)
    {
        database_data_t *p_dbs_realtime = app_get_realtime_pointer();
        uint8_t invalid_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

        if (memcmp(p_dbs_realtime->mac_addr, invalid_mac, 6) == 0) {
            read_dev_def_mac(p_dbs_realtime->mac_addr);
        }
        LOG_HEXDUMP_INF(p_dbs_realtime->mac_addr, 6, "MAC");
    }

    void app_update_tx_power(uint8_t handle_type, uint16_t handle)
    {
        database_data_t *p_dbs_realtime = app_get_realtime_pointer();
        uint8_t tx_power_arr[] = { -40, -20, -16, -12, -8, -4, 0, 4, 8 };

        LOG_INF("tx power table idx=%d", p_dbs_realtime->tx_power);
        set_tx_power(handle_type, handle, tx_power_arr[p_dbs_realtime->tx_power]);
    }
    .......................
    MY BT INIT:
    /**
     * @brief 设置模式 1 广播数据.
     *        uart 广播模式
     */
    static void app_set_adv_mod1(void)
    {
        uint8_t idx = 0;
        database_data_t *p_dbs_realtime = NULL;
        uint16_t srv_uuid = DEF_ADV_SERVICE_UUID;

        memset(m_adv_data, 0, sizeof(m_adv_data));
        memset(m_rsp_data, 0, sizeof(m_rsp_data));
        memset(&m_adv_struct, 0, sizeof(m_adv_struct));
        memset(&m_rsp_struct, 0, sizeof(m_rsp_struct));
        p_dbs_realtime = app_get_realtime_pointer();

        /**********adv data*************/
        /* 广播标志 */
        m_adv_struct.p_data[0].type = BT_DATA_FLAGS;
        m_adv_struct.p_data[0].data = &m_adv_data[idx];
        m_adv_data[idx++] = 0x06;
        m_adv_struct.p_data[0].data_len = 1;

        /* 广播名称*/
        m_adv_struct.p_data[1].type = BT_DATA_NAME_COMPLETE;
        m_adv_struct.p_data[1].data = &m_adv_data[idx];
        memcpy(&m_adv_data[idx], p_dbs_realtime->adv_name.data,
               p_dbs_realtime->adv_name.len);
        m_adv_struct.p_data[1].data_len = p_dbs_realtime->adv_name.len;
        idx += m_adv_struct.p_data[1].data_len;

        /* Service data + mac */
        m_adv_struct.p_data[2].type = BT_DATA_SVC_DATA16;
        m_adv_struct.p_data[2].data = &m_adv_data[idx];
        m_adv_data[idx++] = srv_uuid & 0xff;
        m_adv_data[idx++] = (srv_uuid >> 8) & 0xff;
        memcpy(&m_adv_data[idx], p_dbs_realtime->mac_addr, 6);
        idx += 6;
        m_adv_struct.p_data[2].data_len = 6 + 2;
        m_adv_struct.data_len = 3;
        if (p_dbs_realtime->work_phy == DEV_WORK_PHY_CODED) {
            m_adv_struct.p_data[3].type = BT_DATA_MANUFACTURER_DATA;
            m_adv_struct.p_data[3].data = &m_adv_data[idx];
            m_adv_data[idx++] = p_dbs_realtime->company_id & 0xff;
            m_adv_data[idx++] = (p_dbs_realtime->company_id >> 8) & 0xff;
            memcpy(&m_adv_data[idx], p_dbs_realtime->adv_manu_data.data,
                   p_dbs_realtime->adv_manu_data.len);
            idx += p_dbs_realtime->adv_manu_data.len;
            m_adv_struct.p_data[3].data_len = 3 + p_dbs_realtime->adv_manu_data.len;
            m_adv_struct.data_len = 4;
        } else {
            /**********rsp data*************/
            idx = 0;
            m_rsp_struct.p_data[0].type = BT_DATA_MANUFACTURER_DATA;
            m_rsp_struct.p_data[0].data = &m_rsp_data[idx];
            m_rsp_data[idx++] = p_dbs_realtime->company_id & 0xff;
            m_rsp_data[idx++] = (p_dbs_realtime->company_id >> 8) & 0xff;
            memcpy(&m_rsp_data[idx], p_dbs_realtime->adv_manu_data.data,
                   p_dbs_realtime->adv_manu_data.len);
            idx += p_dbs_realtime->adv_manu_data.len;
            m_rsp_struct.p_data[0].data_len = 3 + p_dbs_realtime->adv_manu_data.len;
            m_rsp_struct.data_len = 1;
        }
    }

    /**
     * @brief 设置模式 2 广播数据.
     *        ibeacon 广播模式
     */
    static void app_set_adv_mod2(void)
    {
        uint8_t idx = 0;
        database_data_t *p_dbs_realtime = NULL;
        uint16_t srv_uuid = DEF_ADV_SERVICE_UUID;

        memset(m_adv_data, 0, sizeof(m_adv_data));
        memset(m_rsp_data, 0, sizeof(m_rsp_data));
        memset(&m_adv_struct, 0, sizeof(m_adv_struct));
        memset(&m_rsp_struct, 0, sizeof(m_rsp_struct));
        p_dbs_realtime = app_get_realtime_pointer();

        /**********adv data*************/
        /* 广播标志 */
        m_adv_struct.p_data[0].type = BT_DATA_FLAGS;
        m_adv_struct.p_data[0].data = &m_adv_data[idx];
        m_adv_data[idx++] = 0x06;
        m_adv_struct.p_data[0].data_len = 1;
        /* ibeacon data */
        m_adv_struct.p_data[1].type = BT_DATA_MANUFACTURER_DATA;
        m_adv_struct.p_data[1].data = &m_adv_data[idx];
        m_adv_data[idx++] = 0x4c;
        m_adv_data[idx++] = 0x00;
        m_adv_data[idx++] = 0x02;
        m_adv_data[idx++] = 0x15;
        memcpy(&m_adv_data[idx], p_dbs_realtime->adv_uuid, 16);
        idx += 16;
        m_adv_data[idx++] = (p_dbs_realtime->major >> 8) & 0xff;
        m_adv_data[idx++] = p_dbs_realtime->major & 0xff;
        m_adv_data[idx++] = (p_dbs_realtime->minor >> 8) & 0xff;
        m_adv_data[idx++] = p_dbs_realtime->minor & 0xff;
        m_adv_data[idx++] = DEF_MEASURE_POWER;
        m_adv_struct.p_data[1].data_len = 0x19;
        m_adv_struct.data_len = 2;

        if (p_dbs_realtime->work_phy == DEV_WORK_PHY_CODED) {
            m_adv_struct.p_data[2].type = BT_DATA_NAME_COMPLETE;
            m_adv_struct.p_data[2].data = &m_adv_data[idx];
            memcpy(&m_adv_data[idx], p_dbs_realtime->adv_name.data,
                   p_dbs_realtime->adv_name.len);
            m_adv_struct.p_data[2].data_len = p_dbs_realtime->adv_name.len;
            idx += m_adv_struct.p_data[2].data_len;

            m_adv_struct.p_data[3].type = BT_DATA_SVC_DATA16;
            m_adv_struct.p_data[3].data = &m_adv_data[idx];
            m_adv_data[idx++] = srv_uuid & 0xff;
            m_adv_data[idx++] = (srv_uuid >> 8) & 0xff;
            memcpy(&m_adv_data[idx], p_dbs_realtime->mac_addr, 6);
            m_adv_struct.p_data[3].data_len = 9;
            idx += m_adv_struct.p_data[3].data_len;
            m_adv_struct.data_len = 4;
        } else {
            /**********rsp data*************/
            idx = 0;
            m_rsp_struct.p_data[0].type = BT_DATA_NAME_COMPLETE;
            m_rsp_struct.p_data[0].data = &m_rsp_data[idx];
            memcpy(&m_rsp_data[idx], p_dbs_realtime->adv_name.data,
                   p_dbs_realtime->adv_name.len);
            m_rsp_struct.p_data[0].data_len = p_dbs_realtime->adv_name.len;
            idx += m_rsp_struct.p_data[0].data_len;

            m_rsp_struct.p_data[1].type = BT_DATA_SVC_DATA16;
            m_rsp_struct.p_data[1].data = &m_rsp_data[idx];
            m_rsp_data[idx++] = srv_uuid & 0xff;
            m_rsp_data[idx++] = (srv_uuid >> 8) & 0xff;
            memcpy(&m_rsp_data[idx], p_dbs_realtime->mac_addr, 6);
            m_rsp_struct.p_data[1].data_len = 9;
            idx += m_rsp_struct.p_data[1].data_len;
            m_rsp_struct.data_len = 2;
        }
    }

    /**
     * @brief 广播参数配置
     */
    static void adv_params_config(void)
    {
        int err;
        uint8_t tmp_buf[32];
        struct bt_le_adv_param adv_param;
        bool adv_phy = false;

        database_data_t *p_dbs_realtime = app_get_realtime_pointer();

        adv_param.id = BT_ID_DEFAULT;
        adv_param.sid = 0;
        adv_param.secondary_max_skip = 0;
        adv_param.peer = NULL;
        adv_param.interval_min = MSEC_TO_UNITS(
            p_dbs_realtime->adv_itvl * ADV_INTERVAL_STEP, UNIT_0_625_MS);
        adv_param.interval_max = adv_param.interval_min;

        LOG_INF("adv_mode=%d", p_dbs_realtime->adv_mode);
        if (p_dbs_realtime->adv_mode == ADV_MODE1) {
            app_set_adv_mod1();
        } else {
            app_set_adv_mod2();
        }
        memset(tmp_buf, 0, sizeof(tmp_buf));
        memcpy(tmp_buf, p_dbs_realtime->adv_name.data,
               p_dbs_realtime->adv_name.len);
        err = bt_set_name(tmp_buf);
        __ASSERT(err == 0, "bt_set_name failed (err %d)\n", err);
        adv_phy = p_dbs_realtime->work_phy == DEV_WORK_PHY_NORMAL ? true : false;
        mt_set_adv(adv_param, m_adv_struct, m_rsp_struct, adv_phy);
    }

    /**
     * @brief 发送 notify 上报函数
     */
    static void sent(struct bt_conn *conn)
    {
        peri_evt_t evt;
        if (m_peri_callback) {
            evt.evt_id = PERI_EVT_SEND_NOTIFY_COMPLETE;
            m_peri_callback(&evt);
        }
    }

    /**
     * @brief 接收到 wtire 上报函数
     */
    static void recv(struct bt_conn *conn, const uint8_t *const p_data,
                     uint16_t length)
    {
        peri_evt_t evt;
        if (m_peri_callback) {
            evt.evt_id = PERI_EVT_RX_DATA;
            evt.len = length;
            evt.p_data = (uint8_t *)p_data;
            m_peri_callback(&evt);
        }
    }

    /**
     * @brief 开关 notify 上报函数
     */
    static void ccc_state(enum bt_tsp_ccc_status status)
    {
        peri_evt_t evt;
        if (m_peri_callback) {
            evt.evt_id = status == 0 ? PERI_EVT_OPEN_NOTIFY : PERI_EVT_CLOSE_NOTIFY;
            m_peri_callback(&evt);
        }
    }

    void update_connection_interval(struct bt_conn *conn)
    {
        int err;
        struct fac_data_t *p_dbs_realtime = app_get_realtime_pointer();

        struct bt_le_conn_param *params = BT_LE_CONN_PARAM(16, 32, 0, 400);

        params->interval_min =
            MSEC_TO_UNITS((p_dbs_realtime->conn_itvl * 10), UNIT_1_25_MS);

        params->interval_max = MSEC_TO_UNITS(
            (p_dbs_realtime->conn_itvl * 10 + DEF_CONN_ITVL_DIFF), UNIT_1_25_MS);

        err = bt_conn_le_param_update(conn, params);

        __ASSERT(err == 0, "update_connection_interval failed (err %d)\n", err);
    }

    void app_adv_start(void)
    {
        adv_params_config();
        mt_adv_start();
        app_update_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0);
    }

    void app_adv_stop(void)
    {
        mt_adv_stop();
    }

    void app_peripheral_conn_process(struct bt_conn *conn)
    {
        m_current_conn = conn;
    }

    void app_peripheral_disc_process(void)
    {
        m_current_conn = NULL;
        database_data_t *p_dbs_realtime = app_get_realtime_pointer();
        if (p_dbs_realtime->work_phy == DEV_WORK_PHY_CODED) {
            app_adv_start();
        }
    }

    void app_peri_hdl_register(peri_callback_t cb)
    {
        m_peri_callback = cb;
    }

    void app_service_init(void)
    {
        database_data_t *p_dbs_realtime = app_get_realtime_pointer();
        struct tsp_uuid_t uuid;
        struct bt_tsp_cb tsp_cb = {
            .sent = sent,
            .recv = recv,
            .ccc_state = ccc_state,
        };
        uuid.serv_uuid = p_dbs_realtime->tsp_uuid.serv_uuid;
        uuid.tx_uuid = p_dbs_realtime->tsp_uuid.tx_uuid;
        uuid.rx_uuid = p_dbs_realtime->tsp_uuid.rx_uuid;
        mt_tsp_change_uuid(*((struct uuid_tsp_t *)&uuid));
        mt_tsp_init(&tsp_cb);
    }

    int app_notify_send(uint8_t *p_data, uint16_t len)
    {
        __ASSERT(((p_data != NULL) && (len != 0)), "param err\n");

        int err_code = 0;
        if (m_current_conn) {
            err_code = mt_tsp_data_send(m_current_conn, p_data, len);
        }
        return err_code;
    }
    The code above is the callback part for my slave device’s connection or disconnection events and ble init. I had to disable le_data_len_updated and CONFIG_BT_USER_DATA_LEN_UPDATE for the connection to work properly; otherwise, the following error occurs.
    In addition, I found another method in the related documentation to solve the issue of bt_hci_cmd_send_sync() blocking: increasing CONFIG_BT_BUF_CMD_TX_COUNT. With this approach, there is no need to disable CONFIG_BT_USER_DATA_LEN_UPDATE and the le_data_len_updated callback; now the connection can proceed normally.
    Now,

    MY BT configs:

    CONFIG_BT=y
    CONFIG_BT_GATT_CLIENT=y
    CONFIG_BT_LOG_LEVEL_WRN=y
    CONFIG_BT_USER_PHY_UPDATE=y
    CONFIG_BT_CTLR_SDC_TX_PACKET_COUNT=10
    CONFIG_BT_BUF_EVT_RX_COUNT=12
    CONFIG_BT_BUF_ACL_TX_COUNT=10
    CONFIG_BT_L2CAP_TX_MTU=247
    CONFIG_BT_BUF_ACL_RX_SIZE=251
    CONFIG_BT_BUF_ACL_TX_SIZE=251
    CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
    CONFIG_BT_USER_DATA_LEN_UPDATE=y
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    CONFIG_BT_BUF_CMD_TX_COUNT=3
         
  • distance_test.zip

    Here is a simple Bluetooth slave example using SDK version 3.1.0 and the nrf54l15dk/cpuapp board. If CONFIG_BT_CENTRAL=y is added to prj.conf, the same issue occurs during connection; but if it is disabled, the connection works normally. Could this be a potential issue in the new SDK?

Related