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