BLE stops advertising after a connection, even with CONFIG_BT_MAX_CONN=6

It seems BLE stops advertising after the first connection. Is this expected behavior? Should I restart advertising in my "connected" connection callback?

prj.conf:

# Enable logging system to USB
CONFIG_LOG=y

# <BLE>
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="bale module"
# Allow multiple devices to connect at once
CONFIG_BT_MAX_CONN=6
CONFIG_BT_BUF_ACL_RX_COUNT=7
# Enable Security Management Protocol
# CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
# CONFIG_BT_GATT_DYNAMIC_DB=y
# </BLE>

# Needed for LEDs
CONFIG_DK_LIBRARY=y
CONFIG_BT_HCI_ERR_TO_STR=y

# <CRYPTO>
# Enable nordic security backend and PSA APIs
CONFIG_NRF_SECURITY=y
CONFIG_MBEDTLS_PSA_CRYPTO_C=y

CONFIG_PSA_WANT_ALG_ECDH=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT=y
CONFIG_PSA_WANT_ECC_SECP_R1_256=y

# For key generation
CONFIG_PSA_WANT_GENERATE_RANDOM=y

CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=8192

CONFIG_MAIN_STACK_SIZE=4096
CONFIG_HEAP_MEM_POOL_SIZE=4096
# </CRYPTO>

main.c:

#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/reboot.h>
#include <zephyr/kernel.h>
#include <soc.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/dis.h>

#include <zephyr/settings/settings.h>

#include <dk_buttons_and_leds.h>
#include <zephyr/logging/log.h>
#include <app_version.h>
#include "rcs.h"

LOG_MODULE_REGISTER(main);

#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

#define RUN_STATUS_LED DK_LED1
#define CON_STATUS_LED DK_LED2
#define RPC_LED DK_LED3
#define RUN_LED_BLINK_INTERVAL 200

// Bonding: Define advertising parameter for no Accept List
#define BT_LE_ADV_CONN_NO_ACCEPT_LIST                                   \
    BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, \
                    BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL)

// Data to be used in advertisement packets.
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),
};

// Data to be used in scan response packets.
static const struct bt_data sd[] = {
    // BT_DATA_UUID128_SOME indicates that some but not all services are listed in the scan response
    BT_DATA_BYTES(BT_DATA_UUID128_SOME, BT_UUID_RCS_VAL),
};

void bt_advertise(struct k_work* work)
{
    int err = 0;
    // int err = bt_le_filter_accept_list_clear();
    LOG_INF("BLE: Advertising\n");
    err = bt_le_adv_start(BT_LE_ADV_CONN_NO_ACCEPT_LIST, ad, ARRAY_SIZE(ad), sd,
        ARRAY_SIZE(sd));
    if (err)
    {
        LOG_ERR("BLE: Advertising failed to start (err %d)\n", err);
        return;
    }
}
K_WORK_DEFINE(bt_advertise_work, bt_advertise);

static void on_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_ERR("BLE[%s]: on_connected failed, err 0x%02x %s", addr, err, bt_hci_err_to_str(err));
        return;
    }

    LOG_INF("BLE[%s]: on_connected", addr);
    dk_set_led_on(CON_STATUS_LED);
}

static void on_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));

    remove_conn_secret(conn);
    LOG_INF("BLE[%s]: on_disconnected, reason 0x%02x %s", addr, reason, bt_hci_err_to_str(reason));
    dk_set_led_off(CON_STATUS_LED);
}

struct bt_conn_cb connection_callbacks = {
    .connected = on_connected,
    .disconnected = on_disconnected,
};

static void rcs_received_cb(struct bt_conn* conn, const uint8_t* const data, uint16_t len)
{
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    LOG_INF("RCS: %s: received data: %.*s", addr, len, data);

    // echo back the data
    bt_rcs_send(conn, data, len);
}

static void rcs_sent_cb(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("RCS: %s: data sent", addr);
}

struct bt_rcs_cb rcs_callbacks = {
    .received = rcs_received_cb,
    .sent = rcs_sent_cb
};

int main(void) {
    int err;
    LOG_INF("Starting BALE firmware");
    LOG_INF("Firmware version: %s", APP_VERSION_STRING);

    err = dk_leds_init();
    if (err)
    {
        LOG_ERR("LEDs init failed (err %d)", err);
        return 1;
    }

    err = bt_conn_cb_register(&connection_callbacks);
    if (err)
    {
        LOG_INF("Failed to register connection callbacks.\n");
        return -1;
    }

    err = bt_enable(NULL);
    if (err)
    {
        LOG_ERR("BLE init failed (err %d)", err);
        return -1;
    }

    LOG_INF("Bluetooth initialized");

    // Initialize bluetooth services
    LOG_INF("Initializing Bluetooth services");
    err = bt_rcs_init(&rcs_callbacks);
    if (err)
    {
        LOG_ERR("bt_rcs_init failed (err %d)", err);
        return -1;
    }

    k_work_submit(&bt_advertise_work);

    int blink_status = 0; // Declare and initialize blink_status

    for (;;)
    {
        dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
        k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
    }
}

Related