BLE central_uart cannot work with nRF21540 EK

I have two nRF52833 development boards: one is connected to the nRF21540 EK as TX (using BLE peripheral_uart), and the other is used as RX (BLE central_uart). My issue is that, with the TX setup being completely identical, when I use ble_app_uart_c from the nRF5 SDK, it correctly receives the signal and prints the RSSI (as shown in Figure 1). However, when I use central_uart from NCS, an error occurs (as shown in Figure 2). If I comment out the following configurations:

CONFIG_MPSL_FEM=y
CONFIG_MPSL=y
CONFIG_MPSL_FEM_NRF21540_GPIO=y
CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20
CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=13

it works correctly and displays the results, as shown in Figure 3.

What is happening here. I am looking forwart to hearing from you :)
Parents
  • Hi,

    I have some questions to better understand this and attempt to reproduce:

    1. this issue depends on the firwmare runnign on the central, and that the central_uart build for the nRF52833 DK with nRF21540 shield is needed to trigger this. Is it correct?
    2. Can you show exactly how you build the central project so that I can replicate the configuration on my end?
    3. Which nRF Connect SDK version are you using?
    4. Which SDK version are you using on the peripheral side? (and if you have tested others, does it matter?)
  • Thank you for your reply!

    1. The issue depends on the firmware running on the peripheral and central. If I delete the FEM config for the peripheral or I change the central from NCS to nRF5 SDK firmware this issue will not happen.

    2. For NCS, I have build the central project like this

    #
    # Copyright (c) 2018 Nordic Semiconductor
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    
    # Enable the UART driver
    CONFIG_UART_ASYNC_API=y
    CONFIG_NRFX_UARTE0=y
    CONFIG_SERIAL=y
    
    CONFIG_GPIO=y
    
    # Make sure printk is printing to the UART console
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y
    
    CONFIG_HEAP_MEM_POOL_SIZE=2048
    
    CONFIG_BT=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DEVICE_NAME="DARE"
    CONFIG_BT_MAX_CONN=1
    CONFIG_BT_MAX_PAIRED=1
    
    # Enable the NUS service
    CONFIG_BT_NUS=y
    
    # Enable bonding
    CONFIG_BT_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    
    # Enable DK LED and Buttons library
    CONFIG_DK_LIBRARY=y
    
    # This example requires more stack
    CONFIG_MAIN_STACK_SIZE=1152
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    
    # Config logger
    CONFIG_LOG=y
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_LOG_BACKEND_RTT=y
    CONFIG_LOG_BACKEND_UART=n
    CONFIG_LOG_PRINTK=n
    
    CONFIG_ASSERT=y
    
    
    # #FEM
    # CONFIG_MPSL_FEM=y
    # CONFIG_MPSL=y
    # # CONFIG_MPSL_FEM_NRF21540_GPIO=y
    # # CONFIG_MPSL_FEM_NRF21540_GPIO_SPI=y EK用不上
    # CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    # CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20
    # CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=13
    # CONFIG_BT_CTLR_TX_PWR_ANTENNA=-20
    

    3 and 4. I have tried 2.8 and 2.9 for both peripheral and central ang both of them have this issue. And most of the time the central can have the connedtion and then give me these errors. For 10% time it can receive the data and print out RSSI.

    My central code shows below:

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     *  @brief Nordic UART Service Client sample
     */
    
    #include <errno.h>
    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/sys/printk.h>
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    
    #include <bluetooth/services/nus.h>
    #include <bluetooth/services/nus_client.h>
    #include <bluetooth/gatt_dm.h>
    #include <bluetooth/scan.h>
    
    #include <zephyr/settings/settings.h>
    
    #include <zephyr/drivers/uart.h>
    
    #include <zephyr/logging/log.h>
    
    #include <zephyr/bluetooth/hci.h>
    
    
    #define LOG_MODULE_NAME central_uart
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    /* UART payload buffer element size. */
    #define UART_BUF_SIZE 45
    
    #define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
    #define KEY_PASSKEY_REJECT DK_BTN2_MSK
    
    #define NUS_WRITE_TIMEOUT K_MSEC(150)
    #define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
    #define UART_RX_TIMEOUT 50000 /* Wait for RX complete event time in microseconds. */
    
    static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));
    static struct k_work_delayable uart_work;
    
    K_SEM_DEFINE(nus_write_sem, 0, 1);
    
    struct uart_data_t {
    	void *fifo_reserved;
    	uint8_t  data[UART_BUF_SIZE];
    	uint16_t len;
    };
    
    static K_FIFO_DEFINE(fifo_uart_tx_data);
    static K_FIFO_DEFINE(fifo_uart_rx_data);
    
    static struct bt_conn *default_conn;
    static struct bt_nus_client nus_client;
    
    
    
    
    
    
    
    static char last_received_data[UART_BUF_SIZE] = {0};
    static uint16_t last_received_data_len = 0;
    static struct k_work_delayable rssi_work;
    
    static void rssi_work_handler(struct k_work *work)
    {
        if (default_conn) {
            struct bt_conn_info info;
            int err;
    
            // 获取当前连接信息
            err = bt_conn_get_info(default_conn, &info);
            if (err) {
                LOG_ERR("Failed to get connection info (err %d)", err);
                return;
            }
    
            // 创建HCI命令缓冲区以读取RSSI
            struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(uint16_t));
            if (!buf) {
                LOG_ERR("Failed to create HCI command buffer");
                return;
            }
    
            // 填充HCI命令
            struct bt_hci_cp_read_rssi *cp = net_buf_add(buf, sizeof(*cp));
            cp->handle = sys_cpu_to_le16(info.id);
    
            // 发送命令并解析响应
            struct net_buf *rsp;
            err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_RSSI, buf, &rsp);
            if (err) {
                LOG_ERR("Failed to read RSSI (err %d)", err);
                return;
            }
    
            struct bt_hci_rp_read_rssi *rp = (void *)rsp->data;
            LOG_INF("RSSI: %d dBm", rp->rssi);
    		LOG_INF("Data received: %.*s", last_received_data_len, last_received_data);
    
            net_buf_unref(rsp);
        }
    
        // 调度下一次任务
        k_work_reschedule(&rssi_work, K_SECONDS(1));  // 每秒读取一次RSSI
    }
    
    
    
    static void init_rssi_monitoring(void)
    {
        // 初始化延时工作
        k_work_init_delayable(&rssi_work, rssi_work_handler);
    
        // 启动任务
        k_work_schedule(&rssi_work, K_NO_WAIT);
    }
    
    
    
    
    
    
    
    
    static void ble_data_sent(struct bt_nus_client *nus, uint8_t err,
    					const uint8_t *const data, uint16_t len)
    {
    	ARG_UNUSED(nus);
    	ARG_UNUSED(data);
    	ARG_UNUSED(len);
    
    	k_sem_give(&nus_write_sem);
    
    	if (err) {
    		LOG_WRN("ATT error code: 0x%02X", err);
    	}
    }
    
    // static uint8_t ble_data_received(struct bt_nus_client *nus,
    // 						const uint8_t *data, uint16_t len)
    // {
    // 	ARG_UNUSED(nus);
    
    // 	int err;
    
    // 	for (uint16_t pos = 0; pos != len;) {
    // 		struct uart_data_t *tx = k_malloc(sizeof(*tx));
    
    // 		if (!tx) {
    // 			LOG_WRN("Not able to allocate UART send data buffer");
    // 			return BT_GATT_ITER_CONTINUE;
    // 		}
    
    // 		/* Keep the last byte of TX buffer for potential LF char. */
    // 		size_t tx_data_size = sizeof(tx->data) - 1;
    
    // 		if ((len - pos) > tx_data_size) {
    // 			tx->len = tx_data_size;
    // 		} else {
    // 			tx->len = (len - pos);
    // 		}
    
    // 		memcpy(tx->data, &data[pos], tx->len);
    
    // 		pos += tx->len;
    
    // 		/* Append the LF character when the CR character triggered
    // 		 * transmission from the peer.
    // 		 */
    // 		if ((pos == len) && (data[len - 1] == '\r')) {
    // 			tx->data[tx->len] = '\n';
    // 			tx->len++;
    // 		}
    
    // 		err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
    // 		if (err) {
    // 			k_fifo_put(&fifo_uart_tx_data, tx);
    // 		}
    // 	}
    
    // 	return BT_GATT_ITER_CONTINUE;
    // }
    
    
    
    
    
    
    static uint8_t ble_data_received(struct bt_nus_client *nus,
                                     const uint8_t *data, uint16_t len)
    {
        ARG_UNUSED(nus);
    
        // 保存接收到的数据
        memset(last_received_data, 0, sizeof(last_received_data));
        last_received_data_len = len < UART_BUF_SIZE ? len : UART_BUF_SIZE - 1;
        memcpy(last_received_data, data, last_received_data_len);
    
        //LOG_INF("Data received: %.*s", last_received_data_len, last_received_data);
    
        return BT_GATT_ITER_CONTINUE;
    }
    
    
    
    
    
    
    
    
    
    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	ARG_UNUSED(dev);
    
    	static size_t aborted_len;
    	struct uart_data_t *buf;
    	static uint8_t *aborted_buf;
    	static bool disable_req;
    
    	switch (evt->type) {
    	case UART_TX_DONE:
    		LOG_DBG("UART_TX_DONE");
    		if ((evt->data.tx.len == 0) ||
    		    (!evt->data.tx.buf)) {
    			return;
    		}
    
    		if (aborted_buf) {
    			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    					   data[0]);
    			aborted_buf = NULL;
    			aborted_len = 0;
    		} else {
    			buf = CONTAINER_OF(evt->data.tx.buf,
    					   struct uart_data_t,
    					   data[0]);
    		}
    
    		k_free(buf);
    
    		buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
    		if (!buf) {
    			return;
    		}
    
    		if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
    			LOG_WRN("Failed to send data over UART");
    		}
    
    		break;
    
    	case UART_RX_RDY:
    		LOG_DBG("UART_RX_RDY");
    		buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data[0]);
    		buf->len += evt->data.rx.len;
    
    		if (disable_req) {
    			return;
    		}
    
    		if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
    		    (evt->data.rx.buf[buf->len - 1] == '\r')) {
    			disable_req = true;
    			uart_rx_disable(uart);
    		}
    
    		break;
    
    	case UART_RX_DISABLED:
    		LOG_DBG("UART_RX_DISABLED");
    		disable_req = false;
    
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    			k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    			return;
    		}
    
    		uart_rx_enable(uart, buf->data, sizeof(buf->data),
    			       UART_RX_TIMEOUT);
    
    		break;
    
    	case UART_RX_BUF_REQUEST:
    		LOG_DBG("UART_RX_BUF_REQUEST");
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    			uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    		}
    
    		break;
    
    	case UART_RX_BUF_RELEASED:
    		LOG_DBG("UART_RX_BUF_RELEASED");
    		buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
    				   data[0]);
    
    		if (buf->len > 0) {
    			k_fifo_put(&fifo_uart_rx_data, buf);
    		} else {
    			k_free(buf);
    		}
    
    		break;
    
    	case UART_TX_ABORTED:
    		LOG_DBG("UART_TX_ABORTED");
    		if (!aborted_buf) {
    			aborted_buf = (uint8_t *)evt->data.tx.buf;
    		}
    
    		aborted_len += evt->data.tx.len;
    		buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    				   data[0]);
    
    		uart_tx(uart, &buf->data[aborted_len],
    			buf->len - aborted_len, SYS_FOREVER_MS);
    
    		break;
    
    	default:
    		break;
    	}
    }
    
    static void uart_work_handler(struct k_work *item)
    {
    	struct uart_data_t *buf;
    
    	buf = k_malloc(sizeof(*buf));
    	if (buf) {
    		buf->len = 0;
    	} else {
    		LOG_WRN("Not able to allocate UART receive buffer");
    		k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    		return;
    	}
    
    	uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT);
    }
    
    static int uart_init(void)
    {
    	int err;
    	struct uart_data_t *rx;
    
    	if (!device_is_ready(uart)) {
    		LOG_ERR("UART device not ready");
    		return -ENODEV;
    	}
    
    	rx = k_malloc(sizeof(*rx));
    	if (rx) {
    		rx->len = 0;
    	} else {
    		return -ENOMEM;
    	}
    
    	k_work_init_delayable(&uart_work, uart_work_handler);
    
    	err = uart_callback_set(uart, uart_cb, NULL);
    	if (err) {
    		return err;
    	}
    
    	return uart_rx_enable(uart, rx->data, sizeof(rx->data),
    			      UART_RX_TIMEOUT);
    }
    
    static void discovery_complete(struct bt_gatt_dm *dm,
    			       void *context)
    {
    	struct bt_nus_client *nus = context;
    	LOG_INF("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);
    }
    
    static void discovery_service_not_found(struct bt_conn *conn,
    					void *context)
    {
    	LOG_INF("Service not found");
    }
    
    static void discovery_error(struct bt_conn *conn,
    			    int err,
    			    void *context)
    {
    	LOG_WRN("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);
    	if (err) {
    		LOG_ERR("could not start the discovery procedure, error "
    			"code: %d", err);
    	}
    }
    
    static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
    {
    	if (!err) {
    		LOG_INF("MTU exchange done");
    	} else {
    		LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err);
    	}
    }
    
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (conn_err) {
    		LOG_INF("Failed to connect to %s, 0x%02x %s", addr, conn_err,
    			bt_hci_err_to_str(conn_err));
    
    		if (default_conn == conn) {
    			bt_conn_unref(default_conn);
    			default_conn = NULL;
    
    			err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    			if (err) {
    				LOG_ERR("Scanning failed to start (err %d)",
    					err);
    			}
    		}
    
    		return;
    	}
    
    	LOG_INF("Connected: %s", addr);
    
    	init_rssi_monitoring();
    
    
    	static struct bt_gatt_exchange_params exchange_params;
    
    	exchange_params.func = exchange_func;
    	err = bt_gatt_exchange_mtu(conn, &exchange_params);
    	if (err) {
    		LOG_WRN("MTU exchange failed (err %d)", err);
    	}
    
    	err = bt_conn_set_security(conn, BT_SECURITY_L2);
    	if (err) {
    		LOG_WRN("Failed to set security: %d", err);
    
    		gatt_discover(conn);
    	}
    
    	err = bt_scan_stop();
    	if ((!err) && (err != -EALREADY)) {
    		LOG_ERR("Stop LE scan failed (err %d)", err);
    	}
    }
    
    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: %s, reason 0x%02x %s", addr, reason, bt_hci_err_to_str(reason));
    	k_work_cancel_delayable(&rssi_work);  // 取消RSSI任务
    
    
    	if (default_conn != conn) {
    		return;
    	}
    
    	bt_conn_unref(default_conn);
    	default_conn = NULL;
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		LOG_ERR("Scanning failed to start (err %d)",
    			err);
    	}
    }
    
    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));
    
    	if (!err) {
    		LOG_INF("Security changed: %s level %u", addr, level);
    	} else {
    		LOG_WRN("Security failed: %s level %u err %d %s", addr, level, err,
    			bt_security_err_to_str(err));
    	}
    
    	gatt_discover(conn);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.security_changed = security_changed
    };
    
    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_WRN("Connecting failed");
    }
    
    static void scan_connecting(struct bt_scan_device_info *device_info,
    			    struct bt_conn *conn)
    {
    	default_conn = bt_conn_ref(conn);
    }
    
    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);
    	if (err) {
    		LOG_ERR("NUS Client initialization failed (err %d)", err);
    		return err;
    	}
    
    	LOG_INF("NUS Client module initialized");
    	return err;
    }
    
    BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,
    		scan_connecting_error, scan_connecting);
    
    static int scan_init(void)
    {
    	int err;
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 1,
    	};
    
    	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);
    	if (err) {
    		LOG_ERR("Scanning filters cannot be set (err %d)", err);
    		return err;
    	}
    
    	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME, "DARE"); // 替换为目标设备的名称
        if (err) {
            LOG_ERR("Failed to set name filter (err %d)", err);
            return err;
        }
    
    	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER|BT_SCAN_NAME_FILTER, false);
    	if (err) {
    		LOG_ERR("Filters cannot be turned on (err %d)", err);
    		return err;
    	}
    
    	LOG_INF("Scan module initialized");
    	return err;
    }
    
    
    static void auth_cancel(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 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("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_WRN("Pairing failed conn: %s, reason %d %s", addr, reason,
    		bt_security_err_to_str(reason));
    }
    
    static struct bt_conn_auth_cb conn_auth_callbacks = {
    	.cancel = auth_cancel,
    };
    
    static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    };
    
    int main(void)
    {
    	int err;
    
    	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
    	if (err) {
    		LOG_ERR("Failed to register authorization callbacks.");
    		return 0;
    	}
    
    	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
    	if (err) {
    		printk("Failed to register authorization info callbacks.\n");
    		return 0;
    	}
    
    	err = bt_enable(NULL);
    	if (err) {
    		LOG_ERR("Bluetooth init failed (err %d)", err);
    		return 0;
    	}
    	LOG_INF("Bluetooth initialized");
    
    
    
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	err = uart_init();
    	if (err != 0) {
    		LOG_ERR("uart_init failed (err %d)", err);
    		return 0;
    	}
    
    	err = scan_init();
    	if (err != 0) {
    		LOG_ERR("scan_init failed (err %d)", err);
    		return 0;
    	}
    
    	err = nus_client_init();
    	if (err != 0) {
    		LOG_ERR("nus_client_init failed (err %d)", err);
    		return 0;
    	}
    
    	printk("Starting Bluetooth Central UART example\n");
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		LOG_ERR("Scanning failed to start (err %d)", err);
    		return 0;
    	}
    
    	LOG_INF("Scanning successfully started");
    
    	struct uart_data_t nus_data = {
    		.len = 0,
    	};
    
    	for (;;) {
    		/* Wait indefinitely for data to be sent over Bluetooth */
    		struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
    						     K_FOREVER);
    
    		int plen = MIN(sizeof(nus_data.data) - nus_data.len, buf->len);
    		int loc = 0;
    
    		while (plen > 0) {
    			memcpy(&nus_data.data[nus_data.len], &buf->data[loc], plen);
    			nus_data.len += plen;
    			loc += plen;
    			if (nus_data.len >= sizeof(nus_data.data) ||
    			   (nus_data.data[nus_data.len - 1] == '\n') ||
    			   (nus_data.data[nus_data.len - 1] == '\r')) {
    				err = bt_nus_client_send(&nus_client, nus_data.data, nus_data.len);
    				if (err) {
    					LOG_WRN("Failed to send data over BLE connection"
    						"(err %d)", err);
    				}
    
    				err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
    				if (err) {
    					LOG_WRN("NUS send timeout");
    				}
    
    				nus_data.len = 0;
    			}
    
    			plen = MIN(sizeof(nus_data.data), buf->len - loc);
    		}
    
    		k_free(buf);
    	}
    }
    

    Thank you so much for your time and patience!

  • Thank you for your reply! Yes, I encountered the problems on the central divice and have no clue about that. As there is no issue if I use the NRF5 SDK.

  • Today I noticed if the central device cannot connect, every time I press reset button it start to work well. What happen for this situation. Is there any issue in my code? Could you please help me find out the problems?Grinning

  • Hi,

    I have not been able to test now, but I see a few things worth checking out. In your init_rssi_monitoring() function which you call every time a new connection is made, you also call k_work_init_delayable(). This should be OK, but only when nothign is scheduled, so dependign on priorities and timing, this could potentially cause problems. So I would take the k_work_init_delayable() call out so that you only call it once.

    Also, I wonder if there is an issue with the work queue? I suggest checking the return value from k_work_schedule() to verify that it succeeds. And if it does not, what is the error code? Other than that, it makes sense to debug to see if somethign that should have happened does not, and track that down with the debugger to see why.

  • Hi

    Today I have modify my code, and I think the problem is nor about the schedule, as now I will have "bt_hci_core: opcode 0x1405 status 0x02" after reconnection.

    main.c

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     *  @brief Nordic UART Service Client sample
     */
    
    #include <errno.h>
    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/sys/printk.h>
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    
    #include <bluetooth/services/nus.h>
    #include <bluetooth/services/nus_client.h>
    #include <bluetooth/gatt_dm.h>
    #include <bluetooth/scan.h>
    
    #include <zephyr/settings/settings.h>
    
    #include <zephyr/drivers/uart.h>
    
    #include <zephyr/logging/log.h>
    
    #include <zephyr/bluetooth/hci.h>
    
    
    #define LOG_MODULE_NAME central_uart
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    /* UART payload buffer element size. */
    #define UART_BUF_SIZE 45
    
    #define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
    #define KEY_PASSKEY_REJECT DK_BTN2_MSK
    
    #define NUS_WRITE_TIMEOUT K_MSEC(150)
    #define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
    #define UART_RX_TIMEOUT 50000 /* Wait for RX complete event time in microseconds. */
    
    static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));
    static struct k_work_delayable uart_work;
    
    K_SEM_DEFINE(nus_write_sem, 0, 1);
    
    struct uart_data_t {
    	void *fifo_reserved;
    	uint8_t  data[UART_BUF_SIZE];
    	uint16_t len;
    };
    
    static K_FIFO_DEFINE(fifo_uart_tx_data);
    static K_FIFO_DEFINE(fifo_uart_rx_data);
    
    static struct bt_conn *default_conn;
    static struct bt_nus_client nus_client;
    
    
    
    
    
    
    
    static char last_received_data[UART_BUF_SIZE] = {0};
    static uint16_t last_received_data_len = 0;
    static struct k_work_delayable rssi_work;
    
    // static void rssi_work_handler(struct k_work *work)
    // {
    //     struct bt_conn_info info;
    //     struct net_buf *buf = NULL, *rsp = NULL;
    //     struct bt_hci_cp_read_rssi *cp;
    //     struct bt_hci_rp_read_rssi *rp;
    //     int err;
    	
    // 	if (default_conn) {
    //         struct bt_conn_info info;
    //         int err;
    
    //         // 获取当前连接信息
    //         err = bt_conn_get_info(default_conn, &info);
    //         if (err) {
    //             LOG_ERR("Failed to get connection info (err %d)", err);
    //             return;
    //         }
    
    //         // 创建HCI命令缓冲区以读取RSSI
    //         struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(uint16_t));
    //         if (!buf) {
    //             LOG_ERR("Failed to create HCI command buffer");
    //             return;
    //         }
    
    //         // 填充HCI命令
    //         struct bt_hci_cp_read_rssi *cp = net_buf_add(buf, sizeof(*cp));
    //         cp->handle = sys_cpu_to_le16(info.id);
    
    //         // 发送命令并解析响应
    //         struct net_buf *rsp;
    //         err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_RSSI, buf, &rsp);
    //         if (err) {
    //             LOG_ERR("Failed to read RSSI (err %d)", err);
    //             return;
    //         }
    
    //         struct bt_hci_rp_read_rssi *rp = (void *)rsp->data;
    //         LOG_INF("RSSI: %d dBm", rp->rssi);
    // 		LOG_INF("Data received: %.*s", last_received_data_len, last_received_data);
    
    //         net_buf_unref(rsp);
    //     }
    
    //     // 调度下一次任务
    //     k_work_reschedule(&rssi_work, K_SECONDS(1));  // 每秒读取一次RSSI
    // }
    static void rssi_work_handler(struct k_work *work)
    {
        struct bt_conn_info info;
        struct net_buf *buf = NULL, *rsp = NULL;
        struct bt_hci_cp_read_rssi *cp;
        struct bt_hci_rp_read_rssi *rp;
        int err;
    
        if (!default_conn) {
            LOG_ERR("No default connection available");
            goto schedule;
        }
    
        /* 获取当前连接信息 */
        err = bt_conn_get_info(default_conn, &info);
        if (err) {
            LOG_ERR("Failed to get connection info (err %d)", err);
            goto schedule;
        }
    
        /* 创建 HCI 命令缓冲区以读取 RSSI */
        buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(*cp));
        if (!buf) {
            LOG_ERR("Unable to allocate HCI command buffer");
            goto schedule;
        }
    
        /* 填充 HCI 命令数据(使用连接标识 info.id 作为句柄) */
        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(info.id);
    
        /* 发送 HCI 命令并等待同步响应 */
        err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_RSSI, buf, &rsp);
        if (err) {
            LOG_ERR("Read RSSI error: %d", err);
            goto schedule;
        }
    
        /* 解析并打印 RSSI 数据 */
        rp = (void *)rsp->data;
        LOG_INF("RSSI: %d dBm", rp->rssi);
    	LOG_INF("Data received: %.*s", last_received_data_len, last_received_data);
    
        net_buf_unref(rsp);
    
    schedule:
        /* 调度下一次任务:每秒读取一次 RSSI */
        k_work_reschedule(&rssi_work, K_SECONDS(1));
    }
    
    
    
    
    
    
    
    
    
    
    static void ble_data_sent(struct bt_nus_client *nus, uint8_t err,
    					const uint8_t *const data, uint16_t len)
    {
    	ARG_UNUSED(nus);
    	ARG_UNUSED(data);
    	ARG_UNUSED(len);
    
    	k_sem_give(&nus_write_sem);
    
    	if (err) {
    		LOG_WRN("ATT error code: 0x%02X", err);
    	}
    }
    
    // static uint8_t ble_data_received(struct bt_nus_client *nus,
    // 						const uint8_t *data, uint16_t len)
    // {
    // 	ARG_UNUSED(nus);
    
    // 	int err;
    
    // 	for (uint16_t pos = 0; pos != len;) {
    // 		struct uart_data_t *tx = k_malloc(sizeof(*tx));
    
    // 		if (!tx) {
    // 			LOG_WRN("Not able to allocate UART send data buffer");
    // 			return BT_GATT_ITER_CONTINUE;
    // 		}
    
    // 		/* Keep the last byte of TX buffer for potential LF char. */
    // 		size_t tx_data_size = sizeof(tx->data) - 1;
    
    // 		if ((len - pos) > tx_data_size) {
    // 			tx->len = tx_data_size;
    // 		} else {
    // 			tx->len = (len - pos);
    // 		}
    
    // 		memcpy(tx->data, &data[pos], tx->len);
    
    // 		pos += tx->len;
    
    // 		/* Append the LF character when the CR character triggered
    // 		 * transmission from the peer.
    // 		 */
    // 		if ((pos == len) && (data[len - 1] == '\r')) {
    // 			tx->data[tx->len] = '\n';
    // 			tx->len++;
    // 		}
    
    // 		err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
    // 		if (err) {
    // 			k_fifo_put(&fifo_uart_tx_data, tx);
    // 		}
    // 	}
    
    // 	return BT_GATT_ITER_CONTINUE;
    // }
    
    
    
    
    
    
    static uint8_t ble_data_received(struct bt_nus_client *nus,
                                     const uint8_t *data, uint16_t len)
    {
        ARG_UNUSED(nus);
    
        // 保存接收到的数据
        memset(last_received_data, 0, sizeof(last_received_data));
        last_received_data_len = len < UART_BUF_SIZE ? len : UART_BUF_SIZE - 1;
        memcpy(last_received_data, data, last_received_data_len);
    
        //LOG_INF("Data received: %.*s", last_received_data_len, last_received_data);
    
        return BT_GATT_ITER_CONTINUE;
    }
    
    
    
    
    
    
    
    
    
    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	ARG_UNUSED(dev);
    
    	static size_t aborted_len;
    	struct uart_data_t *buf;
    	static uint8_t *aborted_buf;
    	static bool disable_req;
    
    	switch (evt->type) {
    	case UART_TX_DONE:
    		LOG_DBG("UART_TX_DONE");
    		if ((evt->data.tx.len == 0) ||
    		    (!evt->data.tx.buf)) {
    			return;
    		}
    
    		if (aborted_buf) {
    			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    					   data[0]);
    			aborted_buf = NULL;
    			aborted_len = 0;
    		} else {
    			buf = CONTAINER_OF(evt->data.tx.buf,
    					   struct uart_data_t,
    					   data[0]);
    		}
    
    		k_free(buf);
    
    		buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
    		if (!buf) {
    			return;
    		}
    
    		if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
    			LOG_WRN("Failed to send data over UART");
    		}
    
    		break;
    
    	case UART_RX_RDY:
    		LOG_DBG("UART_RX_RDY");
    		buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data[0]);
    		buf->len += evt->data.rx.len;
    
    		if (disable_req) {
    			return;
    		}
    
    		if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
    		    (evt->data.rx.buf[buf->len - 1] == '\r')) {
    			disable_req = true;
    			uart_rx_disable(uart);
    		}
    
    		break;
    
    	case UART_RX_DISABLED:
    		LOG_DBG("UART_RX_DISABLED");
    		disable_req = false;
    
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    			k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    			return;
    		}
    
    		uart_rx_enable(uart, buf->data, sizeof(buf->data),
    			       UART_RX_TIMEOUT);
    
    		break;
    
    	case UART_RX_BUF_REQUEST:
    		LOG_DBG("UART_RX_BUF_REQUEST");
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    			uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    		}
    
    		break;
    
    	case UART_RX_BUF_RELEASED:
    		LOG_DBG("UART_RX_BUF_RELEASED");
    		buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
    				   data[0]);
    
    		if (buf->len > 0) {
    			k_fifo_put(&fifo_uart_rx_data, buf);
    		} else {
    			k_free(buf);
    		}
    
    		break;
    
    	case UART_TX_ABORTED:
    		LOG_DBG("UART_TX_ABORTED");
    		if (!aborted_buf) {
    			aborted_buf = (uint8_t *)evt->data.tx.buf;
    		}
    
    		aborted_len += evt->data.tx.len;
    		buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    				   data[0]);
    
    		uart_tx(uart, &buf->data[aborted_len],
    			buf->len - aborted_len, SYS_FOREVER_MS);
    
    		break;
    
    	default:
    		break;
    	}
    }
    
    static void uart_work_handler(struct k_work *item)
    {
    	struct uart_data_t *buf;
    
    	buf = k_malloc(sizeof(*buf));
    	if (buf) {
    		buf->len = 0;
    	} else {
    		LOG_WRN("Not able to allocate UART receive buffer");
    		k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    		return;
    	}
    
    	uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT);
    }
    
    static int uart_init(void)
    {
    	int err;
    	struct uart_data_t *rx;
    
    	if (!device_is_ready(uart)) {
    		LOG_ERR("UART device not ready");
    		return -ENODEV;
    	}
    
    	rx = k_malloc(sizeof(*rx));
    	if (rx) {
    		rx->len = 0;
    	} else {
    		return -ENOMEM;
    	}
    
    	k_work_init_delayable(&uart_work, uart_work_handler);
    
    	err = uart_callback_set(uart, uart_cb, NULL);
    	if (err) {
    		return err;
    	}
    
    	return uart_rx_enable(uart, rx->data, sizeof(rx->data),
    			      UART_RX_TIMEOUT);
    }
    
    static void discovery_complete(struct bt_gatt_dm *dm,
    			       void *context)
    {
    	struct bt_nus_client *nus = context;
    	LOG_INF("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);
    }
    
    static void discovery_service_not_found(struct bt_conn *conn,
    					void *context)
    {
    	LOG_INF("Service not found");
    }
    
    static void discovery_error(struct bt_conn *conn,
    			    int err,
    			    void *context)
    {
    	LOG_WRN("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);
    	if (err) {
    		LOG_ERR("could not start the discovery procedure, error "
    			"code: %d", err);
    	}
    }
    
    static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
    {
    	if (!err) {
    		LOG_INF("MTU exchange done");
    	} else {
    		LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err);
    	}
    }
    
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (conn_err) {
    		LOG_INF("Failed to connect to %s, 0x%02x %s", addr, conn_err,
    			bt_hci_err_to_str(conn_err));
    
    		if (default_conn == conn) {
    			bt_conn_unref(default_conn);
    			default_conn = NULL;
    
    			err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    			if (err) {
    				LOG_ERR("Scanning failed to start (err %d)",
    					err);
    			}
    		}
    
    		return;
    	}
    
    	LOG_INF("Connected: %s", addr);
    
    	static struct bt_gatt_exchange_params exchange_params;
    
    	exchange_params.func = exchange_func;
    	err = bt_gatt_exchange_mtu(conn, &exchange_params);
    	if (err) {
    		LOG_WRN("MTU exchange failed (err %d)", err);
    	}
    
    	err = bt_conn_set_security(conn, BT_SECURITY_L2);
    	if (err) {
    		LOG_WRN("Failed to set security: %d", err);
    
    		gatt_discover(conn);
    	}
    
    	err = bt_scan_stop();
    	if ((!err) && (err != -EALREADY)) {
    		LOG_ERR("Stop LE scan failed (err %d)", err);
    	}
    
    	// 启动任务
        k_work_schedule(&rssi_work, K_NO_WAIT);
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	k_work_cancel_delayable(&rssi_work);  // 取消RSSI任务
    
    	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: %s, reason 0x%02x %s", addr, reason, bt_hci_err_to_str(reason));
    	
    
    
    	if (default_conn != conn) {
    		return;
    	}
    
    	bt_conn_unref(default_conn);
    	default_conn = NULL;
    
    
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		LOG_ERR("Scanning failed to start (err %d)",
    			err);
    	}
    
    }
    
    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));
    
    	if (!err) {
    		LOG_INF("Security changed: %s level %u", addr, level);
    	} else {
    		LOG_WRN("Security failed: %s level %u err %d %s", addr, level, err,
    			bt_security_err_to_str(err));
    			
    	}
    
    	gatt_discover(conn);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.security_changed = security_changed
    };
    
    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_WRN("Connecting failed");
    }
    
    static void scan_connecting(struct bt_scan_device_info *device_info,
    			    struct bt_conn *conn)
    {
    	default_conn = bt_conn_ref(conn);
    }
    
    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);
    	if (err) {
    		LOG_ERR("NUS Client initialization failed (err %d)", err);
    		return err;
    	}
    
    	LOG_INF("NUS Client module initialized");
    	return err;
    }
    
    BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,
    		scan_connecting_error, scan_connecting);
    
    static int scan_init(void)
    {
    	int err;
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 1,
    	};
    
    	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);
    	if (err) {
    		LOG_ERR("Scanning filters cannot be set (err %d)", err);
    		return err;
    	}
    
    	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME, "Mesh Sensor Observer"); // 替换为目标设备的名称
        if (err) {
            LOG_ERR("Failed to set name filter (err %d)", err);
            return err;
        }
    
    	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER|BT_SCAN_NAME_FILTER, false);
    	if (err) {
    		LOG_ERR("Filters cannot be turned on (err %d)", err);
    		return err;
    	}
    
    	LOG_INF("Scan module initialized");
    	return err;
    }
    
    
    static void auth_cancel(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 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("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_WRN("Pairing failed conn: %s, reason %d %s", addr, reason,
    		bt_security_err_to_str(reason));
    }
    
    static struct bt_conn_auth_cb conn_auth_callbacks = {
    	.cancel = auth_cancel,
    };
    
    static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    };
    
    int main(void)
    {
    	int err;
    
    	 k_work_init_delayable(&rssi_work, rssi_work_handler);
    
    	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
    	if (err) {
    		LOG_ERR("Failed to register authorization callbacks.");
    		return 0;
    	}
    
    	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
    	if (err) {
    		printk("Failed to register authorization info callbacks.\n");
    		return 0;
    	}
    
    	err = bt_enable(NULL);
    	if (err) {
    		LOG_ERR("Bluetooth init failed (err %d)", err);
    		return 0;
    	}
    	LOG_INF("Bluetooth initialized");
    
    
    
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	err = uart_init();
    	if (err != 0) {
    		LOG_ERR("uart_init failed (err %d)", err);
    		return 0;
    	}
    
    	err = scan_init();
    	if (err != 0) {
    		LOG_ERR("scan_init failed (err %d)", err);
    		return 0;
    	}
    
    	err = nus_client_init();
    	if (err != 0) {
    		LOG_ERR("nus_client_init failed (err %d)", err);
    		return 0;
    	}
    
    	printk("Starting Bluetooth Central UART example\n");
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		LOG_ERR("Scanning failed to start (err %d)", err);
    		return 0;
    	}
    
    	LOG_INF("Scanning successfully started");
    
    	struct uart_data_t nus_data = {
    		.len = 0,
    	};
    
    	for (;;) {
    		/* Wait indefinitely for data to be sent over Bluetooth */
    		struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
    						     K_FOREVER);
    
    		int plen = MIN(sizeof(nus_data.data) - nus_data.len, buf->len);
    		int loc = 0;
    
    		while (plen > 0) {
    			memcpy(&nus_data.data[nus_data.len], &buf->data[loc], plen);
    			nus_data.len += plen;
    			loc += plen;
    			if (nus_data.len >= sizeof(nus_data.data) ||
    			   (nus_data.data[nus_data.len - 1] == '\n') ||
    			   (nus_data.data[nus_data.len - 1] == '\r')) {
    				err = bt_nus_client_send(&nus_client, nus_data.data, nus_data.len);
    				if (err) {
    					LOG_WRN("Failed to send data over BLE connection"
    						"(err %d)", err);
    				}
    
    				err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
    				if (err) {
    					LOG_WRN("NUS send timeout");
    				}
    
    				nus_data.len = 0;
    			}
    
    			plen = MIN(sizeof(nus_data.data), buf->len - loc);
    		}
    
    		k_free(buf);
    	}
    }
    

    proj.config

    #
    # Copyright (c) 2018 Nordic Semiconductor
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    
    # Enable the UART driver
    CONFIG_UART_ASYNC_API=y
    CONFIG_NRFX_UARTE0=y
    CONFIG_SERIAL=y
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y
    
    # Enable the BLE stack with GATT Client configuration
    CONFIG_BT=y
    CONFIG_BT_CENTRAL=y
    CONFIG_BT_SMP=y
    CONFIG_BT_GATT_CLIENT=y
    
    # Enable the BLE modules from NCS
    CONFIG_BT_NUS_CLIENT=y
    CONFIG_BT_SCAN=y
    CONFIG_BT_SCAN_FILTER_ENABLE=y
    CONFIG_BT_SCAN_UUID_CNT=1
    CONFIG_BT_SCAN_NAME_CNT=1
    CONFIG_BT_GATT_DM=y
    CONFIG_HEAP_MEM_POOL_SIZE=2048
    
    # This example requires more stack
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    CONFIG_MAIN_STACK_SIZE=1536
    
    # Enable bonding
    CONFIG_BT_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    
    # Config logger
    CONFIG_LOG=y
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_LOG_BACKEND_RTT=y
    CONFIG_LOG_BACKEND_UART=n
    CONFIG_LOG_PRINTK=n
    
    CONFIG_ASSERT=y
    
    # RSSI
    CONFIG_BT_CTLR_ADVANCED_FEATURES=y
    CONFIG_BT_CTLR_CONN_RSSI=y
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    
    # #FEM
    # CONFIG_MPSL_FEM=y
    # CONFIG_MPSL=y
    # # CONFIG_MPSL_FEM_NRF21540_GPIO=y 不需要
    # CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    # CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20
    # CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=13
    
    

    I have tried CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y and CONFIG_BT_HCI_VS_EXT=y. As this ticket has similar issue https://devzone.nordicsemi.com/f/nordic-q-a/91339/error-with-bluetooth-hci-function-bt_hci_cmd_send_sync

    I hope you can help me figure it out

  • Hi,

    I am sorry for the delay. I am looking into this but have not got to the bottom of this yet (though this seems similar to what was dicussed in this thread). I suggest we continue in your new thread.

Reply Children
No Data
Related