I use nRF5340 to test Nordic UART Service. But RTT Viewer the following error messages. What is meaning and how to fix it?
<err> bt_gatt: Unable to register handle 0x0016
I use nRF5340 to test Nordic UART Service. But RTT Viewer the following error messages. What is meaning and how to fix it?
<err> bt_gatt: Unable to register handle 0x0016
Hello,
How are you testing the UART service? Are you using the original 'peripheral_uart' sample, or are you trying to integrate the service into another project?
Best regards,
Vidar
I have created a new project for testing the NUS service. I found the error is caused by calling smp_bt_register(). Should I add more configuration in prj.conf file?
00> before calling smp_bt_register 00> [00:00:00.000,915] <err> bt_gatt: Unable to register handle 0x0016 00> after calling smp_bt_register
/*
*
* SPDX-License-Identifier: Apache-2.0
*/
#if CONFIG_BT
#include <bluetooth/services/nus.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/direction.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/mgmt/mcumgr/transport/smp_bt.h>
#include <zephyr/sys/printk.h>
#include "battery_timer.h"
#include "bt_ad.h"
#include "bt_nus.h"
#include "bt_thread.h"
#include "error.h"
#include "time_cal.h"
#define BT_DEBUG_ENABLED 0
#define BLE_RX_BLOCK_SIZE (CONFIG_BT_L2CAP_TX_MTU - 3)
#define BLE_RX_BUF_COUNT 4
#define BLE_SLAB_ALIGNMENT 4
LOG_MODULE_REGISTER(bt);
K_MEM_SLAB_DEFINE(ble_rx_slab, BLE_RX_BLOCK_SIZE, BLE_RX_BUF_COUNT, BLE_SLAB_ALIGNMENT);
static struct bt_conn* _gCurrentConn;
static struct bt_conn* auth_conn;
#ifdef CONFIG_BT_USER_PHY_UPDATE
void _btUpdateDataLength(struct bt_conn *conn) {
int err;
struct bt_conn_le_data_len_param dataLen = {
.tx_max_len = BT_GAP_DATA_LEN_MAX,
.tx_max_time = BT_GAP_DATA_TIME_MAX,
};
err = bt_conn_le_data_len_update(conn, &dataLen);
if (err) {
LOG_ERR("bt_conn_le_data_len_update() failed (err %d)", err);
}
}
#endif
static void connected(struct bt_conn* conn, uint8_t err) {
char addr[BT_ADDR_LE_STR_LEN];
if (err) {
LOG_ERR("Connection failed (err %u)", err);
return;
}
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Connected %s", addr);
struct bt_conn_info btInfo;
int ret = bt_conn_get_info(conn, &btInfo);
if (ret != 0) {
LOG_ERR("Cannot get conn info %d", ret);
return;
}
#if BT_DEBUG_ENABLED
printk("btInfo.le.interval=%u\n", btInfo.le.interval);
printk("btInfo.le.latency=%u\n", btInfo.le.latency);
printk("btInfo.le.timeout=%u\n", btInfo.le.timeout);
#endif
_gCurrentConn = bt_conn_ref(conn);
#if CONFIG_BT_NUS_SECURITY_ENABLED
ret = bt_conn_set_security(conn, BT_SECURITY_L2);
if (ret != 0) {
LOG_ERR("Failed to set security (err %d)\n", ret);
}
#endif
#ifdef CONFIG_BT_USER_PHY_UPDATE
_btUpdateDataLength(conn);
#endif
const uint32_t mtu = bt_nus_get_mtu(_gCurrentConn);
btNusSetMtu(mtu);
LOG_INF("MTU=%u", mtu);
btNusSetState(BT_NUS_STATE_CONNECT);
// creating threads
btNusThreadCreate();
#if CONFIG_BOARD_AM_NRF52832
// starting timers
basTimerStart();
#endif
LOG_INF("connected");
}
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("disconnected: %s (reason %u)", addr, reason);
const bt_nus_state_t state = btNusGetState();
if (state != BT_NUS_STATE_MEASURE) {
btNusSetState(BT_NUS_STATE_DISCONNECT);
}
// aborting threads
btNusThreadAbort();
#if CONFIG_BOARD_AM_NRF52832
// stopping timers
basTimerStop();
#endif
if (auth_conn) {
bt_conn_unref(auth_conn);
auth_conn = NULL;
}
if (_gCurrentConn) {
bt_conn_unref(_gCurrentConn);
_gCurrentConn = NULL;
}
/* Start advertising */
btAdvStart();
}
#if CONFIG_BT_NUS_SECURITY_ENABLED
static void securityChanged(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));
if (!err) {
LOG_INF("Security changed: %s level %u", addr, level);
} else {
LOG_ERR("Security failed: %s level %u err %d", addr, level, err);
}
}
static void authCancel(struct bt_conn *conn) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Pairing cancelled: %s", addr);
}
static void pairingComplete(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("Pairing completed: %s, bonded: %d", addr, bonded);
}
static void pairingFailed(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));
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
LOG_ERR("Pairing failed conn: %s, reason %d", addr, reason);
}
#endif
#ifdef CONFIG_BT_USER_DATA_LEN_UPDATE
void _leDataLenUpdated(struct bt_conn *conn, struct bt_conn_le_data_len_info *info) {
#if BT_DEBUG_ENABLED
uint16_t tx_len = info->tx_max_len;
uint16_t tx_time = info->tx_max_time;
uint16_t rx_len = info->rx_max_len;
uint16_t rx_time = info->rx_max_time;
LOG_INF("Data length updated. Length %d/%d bytes, time %d/%d us", tx_len, rx_len, tx_time, rx_time);
#endif
}
#endif
#ifdef CONFIG_BT_USER_PHY_UPDATE
void _lePhyUpdated(struct bt_conn *conn, struct bt_conn_le_phy_info *param) {
if (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_1M) {
LOG_INF("PHY updated. New PHY: 1M");
} else if (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_2M) {
LOG_INF("PHY updated. New PHY: 2M");
} else if (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_CODED_S8) {
LOG_INF("PHY updated. New PHY: Long Range");
}
}
#endif
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
#if CONFIG_BT_NUS_SECURITY_ENABLED
.security_changed = securityChanged,
#endif
#ifdef CONFIG_BT_USER_DATA_LEN_UPDATE
.le_data_len_updated = _leDataLenUpdated,
#endif
#ifdef CONFIG_BT_USER_PHY_UPDATE
.le_phy_updated = _lePhyUpdated
#endif
};
#if CONFIG_BT_NUS_SECURITY_ENABLED
static struct bt_conn_auth_cb _connAuthCallbacks = {
.passkey_display = NULL,
.passkey_confirm = NULL,
.cancel = authCancel,
};
static struct bt_conn_auth_info_cb _connAuthInfoCallbacks = {
.pairing_complete = pairingComplete,
.pairing_failed = pairingFailed
};
#endif
static void _btReady(const int err) {
if (err) {
LOG_ERR("Bluetooth init failed (err %d)", err);
return;
}
LOG_INF("Bluetooth initialized");
const int ret = btNusInit();
if (ret < 0) {
LOG_ERR("btNusInit() failed, err=0x%x\n", ret);
return;
}
/* Start advertising */
btAdvStart();
}
int btInit(void) {
int ret;
#if CONFIG_BOOTLOADER_MCUBOOT
printk("before calling smp_bt_register\n");
smp_bt_register();
printk("after calling smp_bt_register\n");
#endif
#if CONFIG_BT_NUS_SECURITY_ENABLED
{
ret = bt_conn_auth_cb_register(&_connAuthCallbacks);
if (ret != 0) {
LOG_ERR("Failed to register authorization callbacks.\n");
return ERROR_BT_INITIALIZE_FAIL;
}
ret = bt_conn_auth_info_cb_register(&_connAuthInfoCallbacks);
if (ret != 0) {
LOG_ERR("Failed to register authorization info callbacks.\n");
return ERROR_BT_INITIALIZE_FAIL;
}
}
#endif
ret = bt_enable(_btReady);
if (ret != 0) {
LOG_ERR("Bluetooth init failed (err 0x%x)\n", ret);
return ERROR_BT_INITIALIZE_FAIL;
}
return 0;
}
struct bt_conn* btGetConnectHandle(void) {
return _gCurrentConn;
}
#endif
/*
*
* SPDX-License-Identifier: Apache-2.0
*/
#if CONFIG_BT
#include <bluetooth/services/nus.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/direction.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/mgmt/mcumgr/transport/smp_bt.h>
#include <zephyr/sys/printk.h>
#include "battery_timer.h"
#include "bt_ad.h"
#include "bt_nus.h"
#include "bt_thread.h"
#include "error.h"
#include "time_cal.h"
#define BT_DEBUG_ENABLED 0
#define BLE_RX_BLOCK_SIZE (CONFIG_BT_L2CAP_TX_MTU - 3)
#define BLE_RX_BUF_COUNT 4
#define BLE_SLAB_ALIGNMENT 4
LOG_MODULE_REGISTER(bt);
K_MEM_SLAB_DEFINE(ble_rx_slab, BLE_RX_BLOCK_SIZE, BLE_RX_BUF_COUNT, BLE_SLAB_ALIGNMENT);
static struct bt_conn* _gCurrentConn;
static struct bt_conn* auth_conn;
#ifdef CONFIG_BT_USER_PHY_UPDATE
void _btUpdateDataLength(struct bt_conn *conn) {
int err;
struct bt_conn_le_data_len_param dataLen = {
.tx_max_len = BT_GAP_DATA_LEN_MAX,
.tx_max_time = BT_GAP_DATA_TIME_MAX,
};
err = bt_conn_le_data_len_update(conn, &dataLen);
if (err) {
LOG_ERR("bt_conn_le_data_len_update() failed (err %d)", err);
}
}
#endif
static void connected(struct bt_conn* conn, uint8_t err) {
char addr[BT_ADDR_LE_STR_LEN];
if (err) {
LOG_ERR("Connection failed (err %u)", err);
return;
}
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Connected %s", addr);
struct bt_conn_info btInfo;
int ret = bt_conn_get_info(conn, &btInfo);
if (ret != 0) {
LOG_ERR("Cannot get conn info %d", ret);
return;
}
#if BT_DEBUG_ENABLED
printk("btInfo.le.interval=%u\n", btInfo.le.interval);
printk("btInfo.le.latency=%u\n", btInfo.le.latency);
printk("btInfo.le.timeout=%u\n", btInfo.le.timeout);
#endif
_gCurrentConn = bt_conn_ref(conn);
#if CONFIG_BT_NUS_SECURITY_ENABLED
ret = bt_conn_set_security(conn, BT_SECURITY_L2);
if (ret != 0) {
LOG_ERR("Failed to set security (err %d)\n", ret);
}
#endif
#ifdef CONFIG_BT_USER_PHY_UPDATE
_btUpdateDataLength(conn);
#endif
const uint32_t mtu = bt_nus_get_mtu(_gCurrentConn);
btNusSetMtu(mtu);
LOG_INF("MTU=%u", mtu);
btNusSetState(BT_NUS_STATE_CONNECT);
// creating threads
btNusThreadCreate();
#if CONFIG_BOARD_AM_NRF52832
// starting timers
basTimerStart();
#endif
LOG_INF("connected");
}
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("disconnected: %s (reason %u)", addr, reason);
const bt_nus_state_t state = btNusGetState();
if (state != BT_NUS_STATE_MEASURE) {
btNusSetState(BT_NUS_STATE_DISCONNECT);
}
// aborting threads
btNusThreadAbort();
#if CONFIG_BOARD_AM_NRF52832
// stopping timers
basTimerStop();
#endif
if (auth_conn) {
bt_conn_unref(auth_conn);
auth_conn = NULL;
}
if (_gCurrentConn) {
bt_conn_unref(_gCurrentConn);
_gCurrentConn = NULL;
}
/* Start advertising */
btAdvStart();
}
#if CONFIG_BT_NUS_SECURITY_ENABLED
static void securityChanged(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));
if (!err) {
LOG_INF("Security changed: %s level %u", addr, level);
} else {
LOG_ERR("Security failed: %s level %u err %d", addr, level, err);
}
}
static void authCancel(struct bt_conn *conn) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Pairing cancelled: %s", addr);
}
static void pairingComplete(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("Pairing completed: %s, bonded: %d", addr, bonded);
}
static void pairingFailed(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));
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
LOG_ERR("Pairing failed conn: %s, reason %d", addr, reason);
}
#endif
#ifdef CONFIG_BT_USER_DATA_LEN_UPDATE
void _leDataLenUpdated(struct bt_conn *conn, struct bt_conn_le_data_len_info *info) {
#if BT_DEBUG_ENABLED
uint16_t tx_len = info->tx_max_len;
uint16_t tx_time = info->tx_max_time;
uint16_t rx_len = info->rx_max_len;
uint16_t rx_time = info->rx_max_time;
LOG_INF("Data length updated. Length %d/%d bytes, time %d/%d us", tx_len, rx_len, tx_time, rx_time);
#endif
}
#endif
#ifdef CONFIG_BT_USER_PHY_UPDATE
void _lePhyUpdated(struct bt_conn *conn, struct bt_conn_le_phy_info *param) {
if (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_1M) {
LOG_INF("PHY updated. New PHY: 1M");
} else if (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_2M) {
LOG_INF("PHY updated. New PHY: 2M");
} else if (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_CODED_S8) {
LOG_INF("PHY updated. New PHY: Long Range");
}
}
#endif
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
#if CONFIG_BT_NUS_SECURITY_ENABLED
.security_changed = securityChanged,
#endif
#ifdef CONFIG_BT_USER_DATA_LEN_UPDATE
.le_data_len_updated = _leDataLenUpdated,
#endif
#ifdef CONFIG_BT_USER_PHY_UPDATE
.le_phy_updated = _lePhyUpdated
#endif
};
#if CONFIG_BT_NUS_SECURITY_ENABLED
static struct bt_conn_auth_cb _connAuthCallbacks = {
.passkey_display = NULL,
.passkey_confirm = NULL,
.cancel = authCancel,
};
static struct bt_conn_auth_info_cb _connAuthInfoCallbacks = {
.pairing_complete = pairingComplete,
.pairing_failed = pairingFailed
};
#endif
static void _btReady(const int err) {
if (err) {
LOG_ERR("Bluetooth init failed (err %d)", err);
return;
}
LOG_INF("Bluetooth initialized");
const int ret = btNusInit();
if (ret < 0) {
LOG_ERR("btNusInit() failed, err=0x%x\n", ret);
return;
}
/* Start advertising */
btAdvStart();
}
int btInit(void) {
int ret;
#if CONFIG_BOOTLOADER_MCUBOOT
printk("before calling smp_bt_register\n");
smp_bt_register();
printk("after calling smp_bt_register\n");
#endif
#if CONFIG_BT_NUS_SECURITY_ENABLED
{
ret = bt_conn_auth_cb_register(&_connAuthCallbacks);
if (ret != 0) {
LOG_ERR("Failed to register authorization callbacks.\n");
return ERROR_BT_INITIALIZE_FAIL;
}
ret = bt_conn_auth_info_cb_register(&_connAuthInfoCallbacks);
if (ret != 0) {
LOG_ERR("Failed to register authorization info callbacks.\n");
return ERROR_BT_INITIALIZE_FAIL;
}
}
#endif
ret = bt_enable(_btReady);
if (ret != 0) {
LOG_ERR("Bluetooth init failed (err 0x%x)\n", ret);
return ERROR_BT_INITIALIZE_FAIL;
}
return 0;
}
struct bt_conn* btGetConnectHandle(void) {
return _gCurrentConn;
}
#endif
The function smp_bt_register() runs automatically on startup when CONFIG_MCUMGR_TRANSPORT_BT is enabled. Therefore, you should remove your call to this function in main().
Thanks for your great support! This issue has been fixed after removing calling smp_bt_register().