Hi,
I've come across several posts on this topic, but they all seem to be older than two years. Unfortunately, most of them don't provide any useful information.
Currently, I've implemented a small code example, where I start BLE advertisement upon a button press using interrupts. I then start a timer, and upon its expiration, I stop the BLE advertisement.
I found out that you can not disable BLE, as it is not implemented on the low level, link. If run my code, I get this error:
Upon examining the hci_core.c code, it becomes apparent that the k_sem_take() function yields a result of -11, corresponding to the error code EAGAIN.:
I know how to interpret it correctly, but to me it seems like the resource is not available, possibly due to timing restrictions. However, this shouldn't be the case, considering the timeout is set to 10 seconds (HCI_CMD_TIMEOUT = 10 sec). Any clarification or assistance on this matter would be greatly appreciated.
This is my code:
#include <zephyr/kernel.h> #include <zephyr/logging/log.h> #include <zephyr/bluetooth/bluetooth.h> #include <zephyr/bluetooth/gap.h> #include <dk_buttons_and_leds.h> bool is_running = false; LOG_MODULE_REGISTER(test_ble, LOG_LEVEL_INF); #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 void my_timer_handler(struct k_timer *dummy); void my_work_handler(struct k_work *work); K_TIMER_DEFINE(my_timer, my_timer_handler, NULL); K_WORK_DEFINE(my_work, my_work_handler); static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), }; // Declare the URL data to include in the scan response static unsigned char url_data[] = { 0x17, '/', '/', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.', 'n', 'o', 'r', 'd', 'i', 'c', 's', 'e', 'm', 'i', '.', 'c', 'o', 'm' }; static const struct bt_data sd[] = { BT_DATA(BT_DATA_URI, url_data, sizeof(url_data)), }; void start_ble(){ int err; /* this is currently not supported: https://devzone.nordicsemi.com/f/nordic-q-a/102668/trying-to-start-and-stop-ble-periodically err = bt_enable(NULL); if (err) { LOG_ERR("Bluetooth init failed (err %d)\n", err); return; } */ err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { LOG_ERR("Advertising failed to start (err %d)\n", err); return; } } void stop_ble(){ int err; err = bt_le_adv_stop(); if (err) { LOG_ERR("Advertising failed to stop (err %d)\n", err); return; } /* this is currently not supported: https://devzone.nordicsemi.com/f/nordic-q-a/102668/trying-to-start-and-stop-ble-periodically err = bt_disable(); if (err) { LOG_ERR("Bluetooth stop failed (err %d)\n", err); return; } */ } void my_timer_handler(struct k_timer *dummy) { LOG_INF("Timer expired\n"); stop_ble(); is_running = false; } void my_work_handler(struct k_work *work) { LOG_INF("Work started. \n"); start_ble(); k_timer_start(&my_timer, K_SECONDS(8), K_NO_WAIT); } static void button_changed(uint32_t button_state, uint32_t has_changed) { if (has_changed & DK_BTN1_MSK) { LOG_INF("Btn 1 pressed! \n"); if(!is_running){ k_work_submit(&my_work); is_running = true; } } } int main(void) { int blink_status = 0; int err; err = dk_leds_init(); if (err) { LOG_ERR("LEDs init failed (err %d)\n", err); return -1; } err = dk_buttons_init(button_changed); if (err) { printk("Buttons init failed (err %d)\n", err); return -1; } err = bt_enable(NULL); if (err) { LOG_ERR("Bluetooth init failed (err %d)\n", err); return -1; } LOG_INF("started successfully.\n"); while (true) { dk_set_led(RUN_STATUS_LED, (++blink_status) % 2); k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL)); } }
One thing that also bothers me is that the interrupt routine is triggered twice, even though I have only pressed the button once. Why is this the case?
Thanks for your help.