nRF54L15DK: small BLE app and system stalls after phone reconnect (LED heartbeat + shell stop, no reset)

On nRF54L15 DK (CPUAPP) the app boots and advertises fine, I bound my phone using nrfconnect but when I reboot the DK and try to reconnet using nrfconnect, the device hangs. LED heartbeat stops, LED pattern stops, shell stops responding, but no reset. I need to reboot the devkit using the reset button and the device hang quickly

Board: nrf54l15dk
I tested on zehpyr master (v4.3.0-3043-ga5f56737fd0c) and with NCS 3.2.0

logs:


uart:~$ *** Booting Zephyr OS build v4.3.0-3043-ga5f56737fd0c ***
[00:00:00.012,395] <inf> app: App start
[00:00:00.016,651] <inf> app: Reset causes supported: 0x000009b3
[00:00:00.023,079] <inf> app: Reset cause: 0x00000001
[00:00:00.028,569] <inf> app: Reset cause flag: pin
[00:00:00.035,829] <inf> fs_nvs: 8 Sectors of 4096 bytes
[00:00:00.041,502] <inf> fs_nvs: alloc wra: 0, ed0
[00:00:00.046,714] <inf> fs_nvs: data wra: 0, 170
[00:00:00.053,937] <inf> bt_hci_core: HW Platform: Nordic Semiconductor (0x0002)
[00:00:00.061,696] <inf> bt_hci_core: HW Variant: nRF54Lx (0x0005)
[00:00:00.068,302] <inf> bt_hci_core: Firmware: Standard Bluetooth controller (0x00) Version 4.3 Build 99
[00:00:00.078,570] <inf> bt_hci_core: No ID address. App must call settings_load()
[00:00:00.086,500] <inf> app: Bluetooth initialized
[00:00:00.092,356] <inf> bt_hci_core: HCI transport: Controller
[00:00:00.098,666] <inf> bt_hci_core: Identity: DE:D2:4A:9A:94:A5 (random)
[00:00:00.105,949] <inf> bt_hci_core: HCI: version 5.4 (0x0d) revision 0x0000, manufacturer 0x05f1
[00:00:00.115,325] <inf> bt_hci_core: LMP: version 5.4 (0x0d) subver 0xffff
[00:00:00.123,632] <inf> app: Settings loaded
[00:00:00.128,383] <inf> app: Bonded device: AC:3E:B1:0E:21:F5 (public)
[00:00:00.135,386] <inf> app: Bond count: 1
[00:00:00.139,989] <inf> app: Starting advertising
[00:00:00.145,953] <inf> app: Advertising started
[00:00:00.151,152] <inf> app: Indicate Button attr 0x42c9c (UUID 12345678-1234-5678-1234-56789abcdef5)

prj.conf:

CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_SHELL_STACK_SIZE=4096

CONFIG_BT=y
CONFIG_LOG=y
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_DEBUG=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_PROCESS_THREAD=y
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=4096
CONFIG_LOG_BUFFER_SIZE=4096
CONFIG_HWINFO=y
CONFIG_BT_LOG_LEVEL_INF=y
CONFIG_BT_HCI_CORE_LOG_LEVEL_INF=y
CONFIG_BT_HCI_DRIVER_LOG_LEVEL_INF=y
CONFIG_BT_CONN_LOG_LEVEL_INF=y
CONFIG_BT_GATT_LOG_LEVEL_INF=y
CONFIG_BT_L2CAP_LOG_LEVEL_INF=y
CONFIG_BT_ATT_LOG_LEVEL_INF=y
CONFIG_BT_SMP_LOG_LEVEL_INF=y
CONFIG_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_UART_CONSOLE=y
CONFIG_SHELL=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_SHELL_BACKEND_RTT=n
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_REBOOT=y
CONFIG_BT_SMP=y
CONFIG_BT_SHELL=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DIS=y
CONFIG_BT_ATT_PREPARE_COUNT=5
CONFIG_BT_BAS=y
CONFIG_BT_CTS=y
CONFIG_BT_CTS_HELPER_API=y
CONFIG_BT_PRIVACY=y
CONFIG_BT_DEVICE_NAME="BLE Button"
CONFIG_BT_DEVICE_APPEARANCE=833
CONFIG_BT_DEVICE_NAME_DYNAMIC=y
CONFIG_BT_DEVICE_NAME_MAX=65
CONFIG_GPIO=y

CONFIG_BT_KEYS_OVERWRITE_OLDEST=y
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_SHELL=y

# Fixed passkey pairing
CONFIG_BT_FIXED_PASSKEY=y
CONFIG_BT_SMP_ENFORCE_MITM=y

CONFIG_ASSERT=y
CONFIG_FAULT_DUMP=2

CONFIG_BT_RX_STACK_SIZE=4096

CONFIG_STACK_SENTINEL=y
CONFIG_INIT_STACKS=y
CONFIG_THREAD_STACK_INFO=y
CONFIG_THREAD_NAME=y
CONFIG_ISR_STACK_SIZE=4096

CONFIG_TFM_LOG_LEVEL_SILENCE=y



The code:

#include <zephyr/types.h>
#include <stddef.h>
#include <errno.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/sys/util.h>

#include <zephyr/drivers/hwinfo.h>
#include <zephyr/settings/settings.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 <zephyr/bluetooth/services/bas.h>
#include <zephyr/bluetooth/services/cts.h>

LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL);

static void log_reset_cause(void)
{
#if IS_ENABLED(CONFIG_HWINFO)
static const struct {
uint32_t bit;
const char *name;
} causes[] = {
{ RESET_PIN, "pin" },
{ RESET_SOFTWARE, "software" },
{ RESET_BROWNOUT, "brownout" },
{ RESET_POR, "power-on" },
{ RESET_WATCHDOG, "watchdog" },
{ RESET_DEBUG, "debug" },
{ RESET_SECURITY, "security" },
{ RESET_LOW_POWER_WAKE, "low-power-wake" },
{ RESET_CPU_LOCKUP, "cpu-lockup" },
{ RESET_PARITY, "parity" },
{ RESET_PLL, "pll" },
{ RESET_CLOCK, "clock" },
{ RESET_HARDWARE, "hardware" },
{ RESET_USER, "user" },
{ RESET_TEMPERATURE, "temperature" },
{ RESET_BOOTLOADER, "bootloader" },
{ RESET_FLASH, "flash" },
};
uint32_t supported = 0U;
uint32_t cause = 0U;
int err;

err = hwinfo_get_supported_reset_cause(&supported);
if (err == 0) {
LOG_INF("Reset causes supported: 0x%08x", supported);
}

err = hwinfo_get_reset_cause(&cause);
if (err == 0) {
LOG_INF("Reset cause: 0x%08x", cause);
for (size_t i = 0; i < ARRAY_SIZE(causes); i++) {
if ((cause & causes[i].bit) != 0U) {
LOG_INF("Reset cause flag: %s", causes[i].name);
}
}
} else {
LOG_WRN("Reset cause unavailable (err %d)", err);
}

err = hwinfo_clear_reset_cause();
if (err) {
LOG_WRN("Reset cause clear failed (err %d)", err);
}
#else
LOG_INF("Reset cause: HWINFO disabled");
#endif
}

/* Custom Service Variables */
#define BT_UUID_CUSTOM_SERVICE_VAL \
BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef0)

static const struct bt_uuid_128 vnd_uuid = BT_UUID_INIT_128(
BT_UUID_CUSTOM_SERVICE_VAL);

static const struct bt_uuid_128 vnd_button_uuid = BT_UUID_INIT_128(
BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef5));
static uint8_t btn_press_count;

#define SW0_NODE DT_ALIAS(sw0)
#if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
#error "Unsupported board: sw0 devicetree alias is not defined"
#endif

#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
#define LED2_NODE DT_ALIAS(led2)
#define LED3_NODE DT_ALIAS(led3)
#if !DT_NODE_HAS_STATUS(LED0_NODE, okay)
#error "Unsupported board: led0 devicetree alias is not defined"
#endif
#if !DT_NODE_HAS_STATUS(LED1_NODE, okay)
#error "Unsupported board: led1 devicetree alias is not defined"
#endif
#if !DT_NODE_HAS_STATUS(LED2_NODE, okay)
#error "Unsupported board: led2 devicetree alias is not defined"
#endif

static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
static const struct gpio_dt_spec led_red = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led_green = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
static const struct gpio_dt_spec led_blue = GPIO_DT_SPEC_GET(LED2_NODE, gpios);
#if DT_NODE_HAS_STATUS(LED3_NODE, okay)
static const struct gpio_dt_spec led_hb = GPIO_DT_SPEC_GET(LED3_NODE, gpios);
#endif
static struct gpio_callback button_cb_data;
static struct k_work button_work;
static struct bt_gatt_indicate_params btn_ind_params;
static struct bt_gatt_attr *btn_ind_attr;
static uint8_t btn_indicating;
static uint8_t btn_indicate_enabled;

#define LED_BLUE_ON_MS 200U
#define LED_BLUE_OFF_MS 1800U
#define LED_GREEN_ON_MS 200U
#define LED_GREEN_OFF_MS 4800U
#define LED_RED_ON_MS 100U
#define LED_RED_OFF_MS 100U
#define LED_ALERT_DURATION_MS (60U * MSEC_PER_SEC)

enum led_color {
LED_COLOR_RED,
LED_COLOR_GREEN,
LED_COLOR_BLUE,
};

enum led_mode {
LED_MODE_UNPAIRED,
LED_MODE_PAIRED,
LED_MODE_ALERT,
};

static struct k_work_delayable led_work;
static bool led_on;
static bool leds_ready;
static enum led_mode current_led_mode;
static int64_t alert_until_ms;
static atomic_t paired_state;
#if DT_NODE_HAS_STATUS(LED3_NODE, okay)
static bool hb_ready;
static bool hb_on;
#define HB_THREAD_STACK_SIZE 512
#define HB_THREAD_PRIORITY 5
K_THREAD_STACK_DEFINE(hb_stack, HB_THREAD_STACK_SIZE);
static struct k_thread hb_thread;
#endif

struct bond_state {
bool bonded;
int count;
};

static void heartbeat_init(void)
{
#if DT_NODE_HAS_STATUS(LED3_NODE, okay)
int err;

if (!device_is_ready(led_hb.port)) {
LOG_WRN("Heartbeat LED not ready");
return;
}

err = gpio_pin_configure_dt(&led_hb, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_WRN("Failed to configure heartbeat LED (err %d)", err);
return;
}

hb_ready = true;
#else
LOG_WRN("Heartbeat LED not available");
#endif
}

static void heartbeat_thread(void *arg1, void *arg2, void *arg3)
{
#if DT_NODE_HAS_STATUS(LED3_NODE, okay)
ARG_UNUSED(arg1);
ARG_UNUSED(arg2);
ARG_UNUSED(arg3);

while (1) {
if (hb_ready) {
hb_on = !hb_on;
gpio_pin_set_dt(&led_hb, hb_on);
}

k_sleep(K_MSEC(500));
}
#endif
}

static void heartbeat_start(void)
{
#if DT_NODE_HAS_STATUS(LED3_NODE, okay)
if (!hb_ready) {
return;
}

k_thread_create(&hb_thread, hb_stack, K_THREAD_STACK_SIZEOF(hb_stack),
heartbeat_thread, NULL, NULL, NULL,
HB_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_name_set(&hb_thread, "heartbeat");
#endif
}

static int leds_init(void)
{
int err;

if (!device_is_ready(led_red.port) ||
!device_is_ready(led_green.port) ||
!device_is_ready(led_blue.port)) {
LOG_ERR("LED device not ready");
return -ENODEV;
}

err = gpio_pin_configure_dt(&led_red, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_ERR("Failed to configure red LED (err %d)", err);
return err;
}

err = gpio_pin_configure_dt(&led_green, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_ERR("Failed to configure green LED (err %d)", err);
return err;
}

err = gpio_pin_configure_dt(&led_blue, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_ERR("Failed to configure blue LED (err %d)", err);
return err;
}

return 0;
}

static void leds_all_off(void)
{
gpio_pin_set_dt(&led_red, 0);
gpio_pin_set_dt(&led_green, 0);
gpio_pin_set_dt(&led_blue, 0);
}

static void led_set_color(enum led_color color)
{
gpio_pin_set_dt(&led_red, color == LED_COLOR_RED ? 1 : 0);
gpio_pin_set_dt(&led_green, color == LED_COLOR_GREEN ? 1 : 0);
gpio_pin_set_dt(&led_blue, color == LED_COLOR_BLUE ? 1 : 0);
}

static enum led_mode led_mode_get(void)
{
if (alert_until_ms > k_uptime_get()) {
return LED_MODE_ALERT;
}

return atomic_get(&paired_state) ? LED_MODE_PAIRED : LED_MODE_UNPAIRED;
}

static void led_pattern_for_mode(enum led_mode mode, enum led_color *color,
uint32_t *on_ms, uint32_t *off_ms)
{
switch (mode) {
case LED_MODE_ALERT:
*color = LED_COLOR_RED;
*on_ms = LED_RED_ON_MS;
*off_ms = LED_RED_OFF_MS;
break;
case LED_MODE_PAIRED:
*color = LED_COLOR_GREEN;
*on_ms = LED_GREEN_ON_MS;
*off_ms = LED_GREEN_OFF_MS;
break;
case LED_MODE_UNPAIRED:
default:
*color = LED_COLOR_BLUE;
*on_ms = LED_BLUE_ON_MS;
*off_ms = LED_BLUE_OFF_MS;
break;
}
}

static void led_kick(void)
{
if (!leds_ready) {
return;
}

k_work_reschedule(&led_work, K_NO_WAIT);
}

static void led_alert_trigger(void)
{
alert_until_ms = k_uptime_get() + LED_ALERT_DURATION_MS;
led_kick();
}

static void led_work_handler(struct k_work *work)
{
enum led_mode mode = led_mode_get();
enum led_color color;
uint32_t on_ms;
uint32_t off_ms;

ARG_UNUSED(work);

if (mode != current_led_mode) {
led_on = false;
current_led_mode = mode;
}

led_pattern_for_mode(mode, &color, &on_ms, &off_ms);

if (!led_on) {
led_set_color(color);
led_on = true;
k_work_reschedule(&led_work, K_MSEC(on_ms));
} else {
leds_all_off();
led_on = false;
k_work_reschedule(&led_work, K_MSEC(off_ms));
}
}

static void led_start(void)
{
if (!leds_ready) {
return;
}

current_led_mode = led_mode_get();
led_on = false;
k_work_reschedule(&led_work, K_NO_WAIT);
}

static void bond_check(const struct bt_bond_info *info, void *user_data)
{
struct bond_state *state = user_data;
char addr[BT_ADDR_LE_STR_LEN];

bt_addr_le_to_str(&info->addr, addr, sizeof(addr));
LOG_INF("Bonded device: %s", addr);
state->bonded = true;
state->count++;
}

static void update_paired_from_bonds(void)
{
struct bond_state state = { 0 };

bt_foreach_bond(BT_ID_DEFAULT, bond_check, &state);
atomic_set(&paired_state, state.bonded ? 1 : 0);
LOG_INF("Bond count: %d", state.count);
}

static void btn_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
ARG_UNUSED(attr);
btn_indicate_enabled = (value == BT_GATT_CCC_INDICATE) ? 1U : 0U;
LOG_INF("Button indicate CCC set to 0x%04x", value);
}

static void indicate_cb(struct bt_conn *conn,
struct bt_gatt_indicate_params *params, uint8_t err)
{
ARG_UNUSED(conn);
ARG_UNUSED(params);
if (err != 0U) {
LOG_WRN("Indication failed (err 0x%02x)", err);
} else {
LOG_DBG("Indication success");
}
}

static void button_indicate_destroy(struct bt_gatt_indicate_params *params)
{
ARG_UNUSED(params);
btn_indicating = 0U;
LOG_DBG("Button indication complete");
}

static void button_work_handler(struct k_work *work)
{
ARG_UNUSED(work);

led_alert_trigger();

if (!btn_indicate_enabled || !btn_ind_attr) {
return;
}

if (btn_indicating) {
return;
}

btn_press_count++;
LOG_INF("Button pressed, count %u", btn_press_count);
btn_ind_params.attr = btn_ind_attr;
btn_ind_params.func = indicate_cb;
btn_ind_params.destroy = button_indicate_destroy;
btn_ind_params.data = &btn_press_count;
btn_ind_params.len = sizeof(btn_press_count);

int err = bt_gatt_indicate(NULL, &btn_ind_params);
if (err == 0) {
btn_indicating = 1U;
} else {
LOG_WRN("Button indicate failed (err %d)", err);
}
}

static void button_pressed_isr(const struct device *dev,
struct gpio_callback *cb, uint32_t pins)
{
ARG_UNUSED(dev);
ARG_UNUSED(cb);
ARG_UNUSED(pins);

k_work_submit(&button_work);
}

static int button_init(void)
{
int err;

if (!device_is_ready(button.port)) {
LOG_ERR("Button device not ready");
return -ENODEV;
}

k_work_init(&button_work, button_work_handler);

err = gpio_pin_configure_dt(&button, GPIO_INPUT);
if (err) {
LOG_ERR("Failed to configure button pin (err %d)", err);
return err;
}

gpio_init_callback(&button_cb_data, button_pressed_isr, BIT(button.pin));
err = gpio_add_callback(button.port, &button_cb_data);
if (err) {
LOG_ERR("Failed to add button callback (err %d)", err);
return err;
}

err = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
if (err) {
LOG_ERR("Failed to enable button interrupt (err %d)", err);
return err;
}

return 0;
}

/* Vendor Primary Service Declaration */
BT_GATT_SERVICE_DEFINE(vnd_svc,
BT_GATT_PRIMARY_SERVICE(&vnd_uuid),
BT_GATT_CHARACTERISTIC(&vnd_button_uuid.uuid,
BT_GATT_CHRC_INDICATE,
0, NULL, NULL, &btn_press_count),
BT_GATT_CCC(btn_ccc_cfg_changed,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
);

static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA_BYTES(BT_DATA_UUID16_ALL,
BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
BT_UUID_16_ENCODE(BT_UUID_CTS_VAL)),
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_CUSTOM_SERVICE_VAL),
};

static const struct bt_data sd[] = {
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
{
char addr[BT_ADDR_LE_STR_LEN];

bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("MTU updated for %s: TX %u RX %u", addr, tx, rx);
}

static struct bt_gatt_cb gatt_callbacks = {
.att_mtu_updated = mtu_updated
};

static void connected(struct bt_conn *conn, uint8_t err)
{
char addr[BT_ADDR_LE_STR_LEN];

bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (err) {
LOG_WRN("Connection failed (%s): err 0x%02x %s",
addr, err, bt_hci_err_to_str(err));
} else {
LOG_INF("Connected: %s", addr);
}
}

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));

LOG_INF("Restarting advertising");
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
if (err && err != -EALREADY) {
LOG_ERR("Advertising restart failed (err %d)", err);
} else {
LOG_INF("Advertising started");
}
}

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_WRN("Security failed (%s): level %u err %u", addr, level, err);
} else {
LOG_INF("Security changed (%s): level %u", addr, level);
}
}

static void le_param_updated(struct bt_conn *conn, uint16_t interval,
uint16_t latency, uint16_t timeout)
{
char addr[BT_ADDR_LE_STR_LEN];

bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Conn params (%s): interval %u latency %u timeout %u",
addr, interval, latency, timeout);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
.security_changed = security_changed,
.le_param_updated = le_param_updated,
};

static void bt_ready(void)
{
int err;

LOG_INF("Bluetooth initialized");

if (IS_ENABLED(CONFIG_SETTINGS)) {
err = settings_load();
if (err) {
LOG_WRN("Settings load failed (err %d)", err);
} else {
LOG_INF("Settings loaded");
}
update_paired_from_bonds();
}

LOG_INF("Starting advertising");
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
LOG_ERR("Advertising failed to start (err %d)", err);
return;
}

LOG_INF("Advertising started");
}

static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
char addr[BT_ADDR_LE_STR_LEN];

bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

LOG_INF("Passkey for %s: %06u", addr, passkey);
}

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_WRN("Pairing cancelled: %s", addr);
}

static struct bt_conn_auth_cb auth_cb_display = {
.passkey_display = auth_passkey_display,
.passkey_entry = NULL,
.cancel = auth_cancel,
};

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 complete: %s bonded=%u", addr, bonded ? 1U : 0U);

atomic_set(&paired_state, 1);
led_kick();
}

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: %s (reason %d)", addr, reason);
}

static struct bt_conn_auth_info_cb auth_info_cb = {
.pairing_complete = pairing_complete,
.pairing_failed = pairing_failed,
};

static void bas_notify(void)
{
uint8_t battery_level = bt_bas_get_battery_level();

battery_level--;

if (!battery_level) {
battery_level = 100U;
}

bt_bas_set_battery_level(battery_level);
}

/**
* variable to hold reference milliseconds to epoch when device booted
* this is only for demo purpose, for more precise synchronization please
* review clock_settime API implementation.
*/
static int64_t unix_ms_ref;
static bool cts_notification_enabled;

void bt_cts_notification_changed(bool enabled)
{
cts_notification_enabled = enabled;
LOG_INF("CTS notification %s", enabled ? "enabled" : "disabled");
}

int bt_cts_cts_time_write(struct bt_cts_time_format *cts_time)
{
int err;
int64_t unix_ms;

if (IS_ENABLED(CONFIG_BT_CTS_HELPER_API)) {
err = bt_cts_time_to_unix_ms(cts_time, &unix_ms);
if (err) {
return err;
}
} else {
return -ENOTSUP;
}

/* recalculate reference value */
unix_ms_ref = unix_ms - k_uptime_get();
LOG_INF("CTS time write ok, unix_ms=%lld", (long long)unix_ms);
return 0;
}

int bt_cts_fill_current_cts_time(struct bt_cts_time_format *cts_time)
{
int64_t unix_ms = unix_ms_ref + k_uptime_get();

if (IS_ENABLED(CONFIG_BT_CTS_HELPER_API)) {
return bt_cts_time_from_unix_ms(cts_time, unix_ms);
} else {
return -ENOTSUP;
}
}

const struct bt_cts_cb cts_cb = {
.notification_changed = bt_cts_notification_changed,
.cts_time_write = bt_cts_cts_time_write,
.fill_current_cts_time = bt_cts_fill_current_cts_time,
};

int main(void)
{
char str[BT_UUID_STR_LEN];
int err;

LOG_INF("App start");
log_reset_cause();
err = bt_enable(NULL);
if (err) {
LOG_ERR("Bluetooth init failed (err %d)", err);
return 0;
}

err = bt_passkey_set(123456);
if (err) {
LOG_WRN("Failed to set fixed passkey (err %d)", err);
}

bt_conn_auth_cb_register(&auth_cb_display);
bt_conn_auth_info_cb_register(&auth_info_cb);

bt_ready();
bt_cts_init(&cts_cb);
bt_gatt_cb_register(&gatt_callbacks);

btn_ind_attr = bt_gatt_find_by_uuid(vnd_svc.attrs, vnd_svc.attr_count,
&vnd_button_uuid.uuid);
bt_uuid_to_str(&vnd_button_uuid.uuid, str, sizeof(str));
LOG_INF("Indicate Button attr %p (UUID %s)", btn_ind_attr, str);

err = button_init();
if (err) {
LOG_ERR("Button init failed (err %d)", err);
}

err = leds_init();
if (err) {
LOG_ERR("LED init failed (err %d)", err);
} else {
leds_ready = true;
k_work_init_delayable(&led_work, led_work_handler);
led_start();
}

heartbeat_init();
heartbeat_start();

/* Implement notification. At the moment there is no suitable way
* of starting delayed work so we do it here
*/
while (1) {
k_sleep(K_SECONDS(1));

/* Current time update notification example
* For testing purposes, we send a manual update notification every second.
* In production `bt_cts_send_notification` should only be used when time is changed
*/
if (cts_notification_enabled) {
bt_cts_send_notification(BT_CTS_UPDATE_REASON_MANUAL);
}
/* Battery level simulation */
bas_notify();

}
return 0;
}



Parents
  • I simplifyied the code and it's still freezing:

    #include <zephyr/types.h>
    #include <stddef.h>
    #include <errno.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/util.h>
    
    #include <zephyr/drivers/hwinfo.h>
    #include <zephyr/settings/settings.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>
    
    LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL);
    
    static void log_reset_cause(void)
    {
    #if IS_ENABLED(CONFIG_HWINFO)
            static const struct {
                    uint32_t bit;
                    const char *name;
            } causes[] = {
                    { RESET_PIN, "pin" },
                    { RESET_SOFTWARE, "software" },
                    { RESET_BROWNOUT, "brownout" },
                    { RESET_POR, "power-on" },
                    { RESET_WATCHDOG, "watchdog" },
                    { RESET_DEBUG, "debug" },
                    { RESET_SECURITY, "security" },
                    { RESET_LOW_POWER_WAKE, "low-power-wake" },
                    { RESET_CPU_LOCKUP, "cpu-lockup" },
                    { RESET_PARITY, "parity" },
                    { RESET_PLL, "pll" },
                    { RESET_CLOCK, "clock" },
                    { RESET_HARDWARE, "hardware" },
                    { RESET_USER, "user" },
                    { RESET_TEMPERATURE, "temperature" },
                    { RESET_BOOTLOADER, "bootloader" },
                    { RESET_FLASH, "flash" },
            };
            uint32_t supported = 0U;
            uint32_t cause = 0U;
            int err;
    
            err = hwinfo_get_supported_reset_cause(&supported);
            if (err == 0) {
                    LOG_INF("Reset causes supported: 0x%08x", supported);
            }
    
            err = hwinfo_get_reset_cause(&cause);
            if (err == 0) {
                    LOG_INF("Reset cause: 0x%08x", cause);
                    for (size_t i = 0; i < ARRAY_SIZE(causes); i++) {
                            if ((cause & causes[i].bit) != 0U) {
                                    LOG_INF("Reset cause flag: %s", causes[i].name);
                            }
                    }
            } else {
                    LOG_WRN("Reset cause unavailable (err %d)", err);
            }
    
            err = hwinfo_clear_reset_cause();
            if (err) {
                    LOG_WRN("Reset cause clear failed (err %d)", err);
            }
    #else
            LOG_INF("Reset cause: HWINFO disabled");
    #endif
    }
    
    static struct bt_conn *default_conn;
    struct bond_state {
            int count;
    };
    
    static void bond_check(const struct bt_bond_info *info, void *user_data)
    {
            struct bond_state *state = user_data;
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(&info->addr, addr, sizeof(addr));
            LOG_INF("Bonded device: %s", addr);
            state->count++;
    }
    
    static void update_paired_from_bonds(void)
    {
            struct bond_state state = { 0 };
    
            bt_foreach_bond(BT_ID_DEFAULT, bond_check, &state);
            LOG_INF("Bond count: %d", state.count);
    }
    
    static const struct bt_data ad[] = {
            BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    };
    
    static const struct bt_data sd[] = {
            BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
    };
    
    void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
    {
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
            LOG_INF("MTU updated for %s: TX %u RX %u", addr, tx, rx);
    }
    
    static struct bt_gatt_cb gatt_callbacks = {
            .att_mtu_updated = mtu_updated
    };
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
            char addr[BT_ADDR_LE_STR_LEN];
            int sec_err;
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
            if (err) {
                    LOG_WRN("Connection failed (%s): err 0x%02x %s",
                            addr, err, bt_hci_err_to_str(err));
            } else {
                    LOG_INF("Connected: %s", addr);
                    if (default_conn) {
                            bt_conn_unref(default_conn);
                    }
                    default_conn = bt_conn_ref(conn);
                    sec_err = bt_conn_set_security(conn, BT_SECURITY_L2);
                    if (sec_err) {
                            LOG_WRN("Failed to set security (err %d)", sec_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));
    
            if (default_conn) {
                    bt_conn_unref(default_conn);
                    default_conn = NULL;
            }
    
            LOG_INF("Restarting advertising");
            err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad),
                                  sd, ARRAY_SIZE(sd));
            if (err && err != -EALREADY) {
                    LOG_ERR("Advertising restart failed (err %d)", err);
            } else {
                    LOG_INF("Advertising started");
            }
    }
    
    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_WRN("Security failed (%s): level %u err %u", addr, level, err);
            } else {
                    LOG_INF("Security changed (%s): level %u", addr, level);
            }
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval,
                                 uint16_t latency, uint16_t timeout)
    {
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
            LOG_INF("Conn params (%s): interval %u latency %u timeout %u",
                    addr, interval, latency, timeout);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
            .connected = connected,
            .disconnected = disconnected,
            .security_changed = security_changed,
            .le_param_updated = le_param_updated,
    };
    
    static void bt_ready(void)
    {
            int err;
    
            LOG_INF("Bluetooth initialized");
    
            if (IS_ENABLED(CONFIG_SETTINGS)) {
                    err = settings_load();
                    if (err) {
                            LOG_WRN("Settings load failed (err %d)", err);
                    } else {
                            LOG_INF("Settings loaded");
                    }
                    update_paired_from_bonds();
            }
    
            LOG_INF("Starting advertising");
            err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
            if (err) {
                    LOG_ERR("Advertising failed to start (err %d)", err);
                    return;
            }
    
            LOG_INF("Advertising started");
    }
    
    static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
    {
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
            LOG_INF("Passkey for %s: %06u", addr, passkey);
    }
    
    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_WRN("Pairing cancelled: %s", addr);
    }
    
    static struct bt_conn_auth_cb auth_cb_display = {
            .passkey_display = auth_passkey_display,
            .passkey_entry = NULL,
            .cancel = auth_cancel,
    };
    
    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 complete: %s bonded=%u", addr, bonded ? 1U : 0U);
    }
    
    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: %s (reason %d)", addr, reason);
    }
    
    static struct bt_conn_auth_info_cb auth_info_cb = {
            .pairing_complete = pairing_complete,
            .pairing_failed = pairing_failed,
    };
    
    int main(void)
    {
            int err;
    
            LOG_INF("App start");
            log_reset_cause();
            err = bt_enable(NULL);
            if (err) {
                    LOG_ERR("Bluetooth init failed (err %d)", err);
                    return 0;
            }
    
            err = bt_passkey_set(123456);
            if (err) {
                    LOG_WRN("Failed to set fixed passkey (err %d)", err);
            }
    
            bt_conn_auth_cb_register(&auth_cb_display);
            bt_conn_auth_info_cb_register(&auth_info_cb);
    
            bt_ready();
            bt_gatt_cb_register(&gatt_callbacks);
    
            /* Implement notification. At the moment there is no suitable way
             * of starting delayed work so we do it here
             */
            while (1) {
                    k_sleep(K_SECONDS(1));
    
                    if (default_conn && bt_conn_get_security(default_conn) >= BT_SECURITY_L2) {
                    }
            }
            return 0;
    }

Reply
  • I simplifyied the code and it's still freezing:

    #include <zephyr/types.h>
    #include <stddef.h>
    #include <errno.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/util.h>
    
    #include <zephyr/drivers/hwinfo.h>
    #include <zephyr/settings/settings.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>
    
    LOG_MODULE_REGISTER(app, CONFIG_LOG_DEFAULT_LEVEL);
    
    static void log_reset_cause(void)
    {
    #if IS_ENABLED(CONFIG_HWINFO)
            static const struct {
                    uint32_t bit;
                    const char *name;
            } causes[] = {
                    { RESET_PIN, "pin" },
                    { RESET_SOFTWARE, "software" },
                    { RESET_BROWNOUT, "brownout" },
                    { RESET_POR, "power-on" },
                    { RESET_WATCHDOG, "watchdog" },
                    { RESET_DEBUG, "debug" },
                    { RESET_SECURITY, "security" },
                    { RESET_LOW_POWER_WAKE, "low-power-wake" },
                    { RESET_CPU_LOCKUP, "cpu-lockup" },
                    { RESET_PARITY, "parity" },
                    { RESET_PLL, "pll" },
                    { RESET_CLOCK, "clock" },
                    { RESET_HARDWARE, "hardware" },
                    { RESET_USER, "user" },
                    { RESET_TEMPERATURE, "temperature" },
                    { RESET_BOOTLOADER, "bootloader" },
                    { RESET_FLASH, "flash" },
            };
            uint32_t supported = 0U;
            uint32_t cause = 0U;
            int err;
    
            err = hwinfo_get_supported_reset_cause(&supported);
            if (err == 0) {
                    LOG_INF("Reset causes supported: 0x%08x", supported);
            }
    
            err = hwinfo_get_reset_cause(&cause);
            if (err == 0) {
                    LOG_INF("Reset cause: 0x%08x", cause);
                    for (size_t i = 0; i < ARRAY_SIZE(causes); i++) {
                            if ((cause & causes[i].bit) != 0U) {
                                    LOG_INF("Reset cause flag: %s", causes[i].name);
                            }
                    }
            } else {
                    LOG_WRN("Reset cause unavailable (err %d)", err);
            }
    
            err = hwinfo_clear_reset_cause();
            if (err) {
                    LOG_WRN("Reset cause clear failed (err %d)", err);
            }
    #else
            LOG_INF("Reset cause: HWINFO disabled");
    #endif
    }
    
    static struct bt_conn *default_conn;
    struct bond_state {
            int count;
    };
    
    static void bond_check(const struct bt_bond_info *info, void *user_data)
    {
            struct bond_state *state = user_data;
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(&info->addr, addr, sizeof(addr));
            LOG_INF("Bonded device: %s", addr);
            state->count++;
    }
    
    static void update_paired_from_bonds(void)
    {
            struct bond_state state = { 0 };
    
            bt_foreach_bond(BT_ID_DEFAULT, bond_check, &state);
            LOG_INF("Bond count: %d", state.count);
    }
    
    static const struct bt_data ad[] = {
            BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    };
    
    static const struct bt_data sd[] = {
            BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
    };
    
    void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
    {
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
            LOG_INF("MTU updated for %s: TX %u RX %u", addr, tx, rx);
    }
    
    static struct bt_gatt_cb gatt_callbacks = {
            .att_mtu_updated = mtu_updated
    };
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
            char addr[BT_ADDR_LE_STR_LEN];
            int sec_err;
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
            if (err) {
                    LOG_WRN("Connection failed (%s): err 0x%02x %s",
                            addr, err, bt_hci_err_to_str(err));
            } else {
                    LOG_INF("Connected: %s", addr);
                    if (default_conn) {
                            bt_conn_unref(default_conn);
                    }
                    default_conn = bt_conn_ref(conn);
                    sec_err = bt_conn_set_security(conn, BT_SECURITY_L2);
                    if (sec_err) {
                            LOG_WRN("Failed to set security (err %d)", sec_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));
    
            if (default_conn) {
                    bt_conn_unref(default_conn);
                    default_conn = NULL;
            }
    
            LOG_INF("Restarting advertising");
            err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad),
                                  sd, ARRAY_SIZE(sd));
            if (err && err != -EALREADY) {
                    LOG_ERR("Advertising restart failed (err %d)", err);
            } else {
                    LOG_INF("Advertising started");
            }
    }
    
    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_WRN("Security failed (%s): level %u err %u", addr, level, err);
            } else {
                    LOG_INF("Security changed (%s): level %u", addr, level);
            }
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval,
                                 uint16_t latency, uint16_t timeout)
    {
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
            LOG_INF("Conn params (%s): interval %u latency %u timeout %u",
                    addr, interval, latency, timeout);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
            .connected = connected,
            .disconnected = disconnected,
            .security_changed = security_changed,
            .le_param_updated = le_param_updated,
    };
    
    static void bt_ready(void)
    {
            int err;
    
            LOG_INF("Bluetooth initialized");
    
            if (IS_ENABLED(CONFIG_SETTINGS)) {
                    err = settings_load();
                    if (err) {
                            LOG_WRN("Settings load failed (err %d)", err);
                    } else {
                            LOG_INF("Settings loaded");
                    }
                    update_paired_from_bonds();
            }
    
            LOG_INF("Starting advertising");
            err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
            if (err) {
                    LOG_ERR("Advertising failed to start (err %d)", err);
                    return;
            }
    
            LOG_INF("Advertising started");
    }
    
    static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
    {
            char addr[BT_ADDR_LE_STR_LEN];
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
            LOG_INF("Passkey for %s: %06u", addr, passkey);
    }
    
    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_WRN("Pairing cancelled: %s", addr);
    }
    
    static struct bt_conn_auth_cb auth_cb_display = {
            .passkey_display = auth_passkey_display,
            .passkey_entry = NULL,
            .cancel = auth_cancel,
    };
    
    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 complete: %s bonded=%u", addr, bonded ? 1U : 0U);
    }
    
    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: %s (reason %d)", addr, reason);
    }
    
    static struct bt_conn_auth_info_cb auth_info_cb = {
            .pairing_complete = pairing_complete,
            .pairing_failed = pairing_failed,
    };
    
    int main(void)
    {
            int err;
    
            LOG_INF("App start");
            log_reset_cause();
            err = bt_enable(NULL);
            if (err) {
                    LOG_ERR("Bluetooth init failed (err %d)", err);
                    return 0;
            }
    
            err = bt_passkey_set(123456);
            if (err) {
                    LOG_WRN("Failed to set fixed passkey (err %d)", err);
            }
    
            bt_conn_auth_cb_register(&auth_cb_display);
            bt_conn_auth_info_cb_register(&auth_info_cb);
    
            bt_ready();
            bt_gatt_cb_register(&gatt_callbacks);
    
            /* Implement notification. At the moment there is no suitable way
             * of starting delayed work so we do it here
             */
            while (1) {
                    k_sleep(K_SECONDS(1));
    
                    if (default_conn && bt_conn_get_security(default_conn) >= BT_SECURITY_L2) {
                    }
            }
            return 0;
    }

Children
No Data
Related