Bluetooth LE nRF52840 - Switch BLE Advertising Interval

Hi,

I am developing a small app for the nRF52840 using the SDK V3.1.0 and  the Visual studio Code on a PC windows 11.

What I like to do is to be able with the app to change the BLE Advertising Interval by just pressing the buttons.

I am not too familiar with the Zephyr RTOS and the sdk API but browsing on the   Nordic Academy and over the SKD examples I found the bricks for the foundation on an example.

I found out how to program the Button1 and Button2 and program the call back routine.

I found out how to configure the board with different Advertising interval.

right now the app starts properly and the device advertise as expected.

when I push on the Button1, the program is redirected to the call back function, great.

In the function, I just stop the BLE Advertising and re-start the BLE advertising with a new Advertising Interval.

Unfortunately, when the program call the bt_le_adv_stop() the program crashes with the following error:

Press the button
Stop advertising...
ASSERTION FAIL [((arch_is_in_isr() == 0) || ((timeout).ticks == (((k_timeout_t) {0})).ticks))] @ WEST_TOPDIR/zephyr/kernel/sem.c:136

I am curious to know if there is an easy way to get around this crash.

/* main.c */

#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>

#include <zephyr/logging/log.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/printk.h>

#include <zephyr/drivers/gpio.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/hci.h>

#include <dk_buttons_and_leds.h>
#include <soc.h>

#include <stdio.h>
#include <string.h>

#define DEVICE_NAME "My_BLE_Device"
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

// 100 ms Advertising Interval
#define  BT_GAP_ADV_FAST_INT_MIN_100ms 0x00A0
#define  BT_GAP_ADV_FAST_INT_MAX_100ms 0x00B0

// 150 ms Advertising Interval
#define  BT_GAP_ADV_FAST_INT_MIN_500ms 0x00320
#define  BT_GAP_ADV_FAST_INT_MAX_500ms 0x00330

#define SLEEP_TIME_MS	1

LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);


static const struct bt_data ad[] = {
    BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR))
};

// 100 ms Advertising parameters
static const struct bt_le_adv_param adv_param_fast =
                    BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONN, 
                                        BT_GAP_ADV_FAST_INT_MIN_100ms, 
                                        BT_GAP_ADV_FAST_INT_MAX_100ms, 
                                        NULL);

// 500 ms Advertising parameters
static const struct bt_le_adv_param adv_param_slow =
                    BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONN, 
                                        BT_GAP_ADV_FAST_INT_MIN_500ms, 
                                        BT_GAP_ADV_FAST_INT_MAX_500ms, 
                                        NULL);

/* Define button devices */
static const struct gpio_dt_spec button0_dev = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
static const struct gpio_dt_spec button1_dev = GPIO_DT_SPEC_GET(DT_ALIAS(sw1), gpios);

/* Define callback function */
static struct gpio_callback button0_cb_data;
static struct gpio_callback button1_cb_data;

// call back button1 for changing ADV IT to 100 ms
void button0_pressed_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{

    printk("Stop advertising...\n");
    bt_le_adv_stop();

    printk("Switching to FAST advertising...\n");
    bt_le_adv_start(&adv_param_fast, ad, ARRAY_SIZE(ad), NULL, 0);

}

// call back button1 for changing ADV IT to 500 ms
void button1_pressed_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{

    printk("Stop advertising...\n");
    bt_le_adv_stop();
    
    printk("Switching to SLOW advertising...\n");
    bt_le_adv_start(&adv_param_slow, ad, ARRAY_SIZE(ad), NULL, 0);
}

// configure the button0 and button1
static int buttons_init(void)
{
    // error
    int err = 0;

   
    /* Configure button 0 */
    if (!device_is_ready(button0_dev.port)) {
        LOG_ERR("Error: button 0 device %s is not ready", button0_dev.port->name);
        return -2;
    }

    err = gpio_pin_configure_dt(&button0_dev, GPIO_INPUT);
    if (err) {
        LOG_ERR("Error %d: failed to configure %s pin %d", err, button0_dev.port->name, button0_dev.pin);
        return -3;
    }

    err = gpio_pin_interrupt_configure_dt(&button0_dev, GPIO_INT_EDGE_TO_ACTIVE);
    if (err) {
        LOG_ERR("Error %d: failed to configure interrupt on %s pin %d", err, button0_dev.port->name, button0_dev.pin);
        return -4;
    }

    gpio_init_callback(&button0_cb_data, button0_pressed_cb, BIT(button0_dev.pin));
    gpio_add_callback(button0_dev.port, &button0_cb_data);

    /* Configure button 1 */
    if (!device_is_ready(button1_dev.port)) {
        LOG_ERR("Error: button 1 device %s is not ready", button1_dev.port->name);
        return -5;
    }

    err = gpio_pin_configure_dt(&button1_dev, GPIO_INPUT);
    if (err) {
        LOG_ERR("Error %d: failed to configure %s pin %d", err, button1_dev.port->name, button1_dev.pin);
        return -6;
    }

    err = gpio_pin_interrupt_configure_dt(&button1_dev, GPIO_INT_EDGE_TO_ACTIVE);
    if (err) {
        LOG_ERR("Error %d: failed to configure interrupt on %s pin %d", err, button1_dev.port->name, button1_dev.pin);
        return -7;
    }

    gpio_init_callback(&button1_cb_data, button1_pressed_cb, BIT(button1_dev.pin));
    gpio_add_callback(button1_dev.port, &button1_cb_data);

    LOG_INF("Press button 0 for 100ms advertising interval.");
    LOG_INF("Press button 1 for 500ms advertising interval.");

    return 0;
}


int main(void)
{
    int err = 0;

    printk("Bluetooth advertisingInterval switch example\n");

    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return -1;
    }

    buttons_init();
    
    /* start with fast advertising as default */
    bt_le_adv_start(&adv_param_fast, ad, ARRAY_SIZE(ad), NULL, 0);
    printk("Started FAST advertising (100 ms)\n");

	printk("Press the button\n");
	while (1) {
			
		k_msleep(SLEEP_TIME_MS);
	}

    return 0;
}

prj.conf


# Enable DK LED and Buttons library
CONFIG_DK_LIBRARY=y

# Make sure printk is printing to the UART console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=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

# Enable bonding
CONFIG_BT=y
CONFIG_BT_SETTINGS=y
CONFIG_BT_PERIPHERAL=y

# JMG TX Power
CONFIG_BT_CTLR_TX_PWR_PLUS_4=y

CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y

CONFIG_ASSERT=y
Regards
Rohde & Schwarz Inc
Jean-Marie Gayet
Parents Reply Children
No Data
Related