Hi,
I want to get a sample that supports both BLE OTA and NUS functions, so I find the following two samples as reference and merge them together.
...\zephyr\samples\subsys\mgmt\mcumgr\smp_svr
...\nrf\samples\bluetooth\peripheral_uart
When finished, I test BLE OTA and NUS functions on nrf52840dk. Then I found a problem: NUS function is abnormal, sending over BLE failed.
I tried to debug it, and found that data sending succeeds when this section was commented:
#if defined(CONFIG_MCUMGR_SMP_BT) && defined(CONFIG_MCUMGR_CMD_IMG_MGMT) && \ defined(CONFIG_MCUMGR_CMD_OS_MGMT) os_mgmt_register_group(); img_mgmt_register_group(); img_mgmt_set_upload_cb(software_update_confirmation_handler, NULL); smp_bt_register(); #endif
But BLE OTA cannot be performed after this section is commented......
So how can I modify this project to support both BLE OTA and NUS functions?
Here are main.c and prj.conf:
man.c
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
/** @file
* @brief Nordic UART Bridge Service (NUS) sample
*/
#include "uart_async_adapter.h"
#include <zephyr/types.h>
#include <zephyr.h>
#include <drivers/uart.h>
#include <usb/usb_device.h>
#include <device.h>
#include <soc.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
#include <bluetooth/hci.h>
#include <bluetooth/services/nus.h>
#include <dk_buttons_and_leds.h>
#include <settings/settings.h>
#include <stdio.h>
#include <logging/log.h>
#include "tlv.h"
/* MCUMgr BT FOTA includes */
#ifdef CONFIG_MCUMGR_CMD_OS_MGMT
#include "os_mgmt/os_mgmt.h"
#endif
#ifdef CONFIG_MCUMGR_CMD_IMG_MGMT
#include "img_mgmt/img_mgmt.h"
#endif
#ifdef CONFIG_MCUMGR_SMP_BT
#include <mgmt/mcumgr/smp_bt.h>
#endif
#define LOG_MODULE_NAME peripheral_uart
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define STACKSIZE CONFIG_BT_NUS_THREAD_STACK_SIZE
#define PRIORITY 7
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
#define RUN_STATUS_LED DK_LED1
#define RUN_LED_BLINK_INTERVAL 1000
#define CON_STATUS_LED DK_LED2
#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
#define KEY_PASSKEY_REJECT DK_BTN2_MSK
#define UART_BUF_SIZE CONFIG_BT_NUS_UART_BUFFER_SIZE
#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
#define UART_WAIT_FOR_RX CONFIG_BT_NUS_UART_RX_WAIT_TIME
/* The default MTU size before negotiating a longer MTU */
#define BLE_GATT_ATT_MTU_DEFAULT 23
static K_SEM_DEFINE(ble_init_ok, 0, 1);
struct bt_conn *current_conn;
static struct bt_gatt_exchange_params exchange_params;
static uint16_t m_nus_max_send_len = BLE_GATT_ATT_MTU_DEFAULT - 3;
struct k_timer m_throughput_timer;
extern void sample_throughput(struct k_timer *timer_id);
static uint32_t m_total_num_bytes;
void sample_throughput(struct k_timer *timer_id)
{
static uint32_t last_recv_byte_cnt;
LOG_INF("%d kbps", (m_total_num_bytes - last_recv_byte_cnt) / 128);
last_recv_byte_cnt = m_total_num_bytes;
}
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),
};
#if CONFIG_BT_NUS_UART_ASYNC_ADAPTER
UART_ASYNC_ADAPTER_INST_DEFINE(async_adapter);
#else
static const struct device *const async_adapter;
#endif
static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
{
if (!err) {
m_nus_max_send_len = bt_nus_get_mtu(conn);
LOG_INF("ATT MTU size updated to %d bytes", m_nus_max_send_len + 3);
#if CONFIG_BT_USER_DATA_LEN_UPDATE
err = bt_conn_le_data_len_update(current_conn, BT_LE_DATA_LEN_PARAM_MAX);
if (err) {
LOG_ERR("Failed to update data length (error %u)", 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", log_strdup(addr));
current_conn = bt_conn_ref(conn);
exchange_params.func = exchange_func;
err = bt_gatt_exchange_mtu(current_conn, &exchange_params);
if (err) {
LOG_WRN("bt_gatt_exchange_mtu: %d", err);
}
dk_set_led_on(CON_STATUS_LED);
}
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)", log_strdup(addr), reason);
if (current_conn) {
bt_conn_unref(current_conn);
current_conn = NULL;
dk_set_led_off(CON_STATUS_LED);
}
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
};
static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data,
uint16_t len)
{
}
static struct bt_nus_cb nus_cb = {
.received = bt_receive_cb,
};
void error(void)
{
dk_set_leds_state(DK_ALL_LEDS_MSK, DK_NO_LEDS_MSK);
while (true) {
/* Spin for ever */
k_sleep(K_MSEC(1000));
}
}
static void configure_gpio(void)
{
int err;
err = dk_leds_init();
if (err) {
LOG_ERR("Cannot init LEDs (err: %d)", err);
}
}
#if defined(CONFIG_MCUMGR_SMP_BT)
static int software_update_confirmation_handler(uint32_t offset, uint32_t size,
void *arg)
{
/* For now just print update progress and confirm data chunk without any additional
* checks.
*/
LOG_INF("Device firmware upgrade progress %d B / %d B", offset, size);
return 0;
}
#endif
void main(void)
{
int blink_status = 0;
int err = 0;
configure_gpio();
err = bt_enable(NULL);
if (err) {
error();
}
LOG_INF("Bluetooth initialized");
k_sem_give(&ble_init_ok);
if (IS_ENABLED(CONFIG_SETTINGS)) {
settings_load();
}
#if defined(CONFIG_MCUMGR_SMP_BT) && defined(CONFIG_MCUMGR_CMD_IMG_MGMT) && \
defined(CONFIG_MCUMGR_CMD_OS_MGMT)
os_mgmt_register_group();
img_mgmt_register_group();
img_mgmt_set_upload_cb(software_update_confirmation_handler, NULL);
smp_bt_register();
#endif
err = bt_nus_init(&nus_cb);
if (err) {
LOG_ERR("Failed to initialize UART service (err: %d)", err);
return;
}
err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
ARRAY_SIZE(sd));
if (err) {
LOG_ERR("Advertising failed to start (err %d)", err);
return;
}
uint8_t test_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
uint8_t test_data_len = sizeof(test_data);
for (;;) {
if(current_conn){
if(bt_nus_send(NULL, &test_data, test_data_len)){
LOG_WRN("Failed to send data over BLE connection %d.", test_data_len);
}
}
dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
}
}
prj.conf
# # 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="Nordic_NUS_DFU" CONFIG_BT_DEVICE_APPEARANCE=833 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 CONFIG_NVS=y CONFIG_SETTINGS=y # Enable DK LED and Buttons library CONFIG_DK_LIBRARY=y # This example requires more workqueue stack CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 # Config logger CONFIG_LOG=y CONFIG_LOG2_MODE_IMMEDIATE=y CONFIG_LOG_BACKEND_UART=y CONFIG_ASSERT=y CONFIG_BT_USER_DATA_LEN_UPDATE=y CONFIG_BT_USER_PHY_UPDATE=y CONFIG_BT_BUF_ACL_RX_SIZE=251 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_L2CAP_TX_MTU=247 CONFIG_BT_BUF_ACL_TX_COUNT=10 CONFIG_BT_BUF_ACL_TX_SIZE=251 CONFIG_BT_SMP=y CONFIG_BOOTLOADER_MCUBOOT=y # MCU Manager and SMP configuration CONFIG_MCUMGR=y CONFIG_MCUMGR_CMD_IMG_MGMT=y CONFIG_MCUMGR_CMD_OS_MGMT=y CONFIG_MCUMGR_SMP_BT=y CONFIG_MCUMGR_SMP_BT_AUTHEN=n CONFIG_MCUMGR_BUF_COUNT=6 # Allow for large Bluetooth data packets. CONFIG_BT_L2CAP_TX_MTU=252 CONFIG_BT_BUF_ACL_RX_SIZE=256 # Reduce GAP event length to avoid heavy BLE traffic generated during DFU CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT=3000 # Some command handlers require a large stack. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304 CONFIG_MAIN_STACK_SIZE=2048
Platform: Windows 10
NCS version: 1.9.1
Boards: nrf52840dk_nrf52840
Looking forward to your reply.
Best wished,
Joyop