nrf52840dongle reboot when push notification to central in gpio callback

I using NCS V2.1.2 toolchain and two nrf52840_dongle and following this tutorial: https://webinars.nordicsemi.com/developing-bluetooth-low-energy-6

First dongle follow the code on tutorial and second dongle using nrf connect desktop bluetooth low energy.

Because using dongle instead of nrf52840-DK i was implement USB CDC ACM console follow example code (for debug), it work well and i can get log information on nRF Terminal .

For button pressed function i add to gpio callback, when press button variable btn_count increase then send to desktop bluetooth app

If i do not enable notification on desktop bluetooth app, i can send data by press button on first dongle then pressing read button on desktop bluetooth app, i can send data back from desktop bluetooth app to peripheral (the first dongle) like tutorial does. 

But, when i enable notification on desktop bluetooth app then press button on peripheral it will reboot immediate, i still can send data from desktop bluetooth app to peripheral normal, only reboot when press button and enable notification.

if i put  this code in while of main:

k_sleep(K_SECONDS(1));
btn_count++;
send_button_notification(current_conn, btn_count, 1);
then enable notification on desktop bluetooth app, it work normal. 
all main.c in here 
#include <zephyr/zephyr.h>
#include <zephyr/sys/printk.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/drivers/uart.h>

#include <logging/log.h>
#include <zephyr/drivers/gpio.h>

#include "remote.h"

BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart),
	     "Console device is not ACM CDC UART device");

#define LED0_NODE 	DT_ALIAS(led0)
#define SW0_NODE	DT_ALIAS(sw0)

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led1_blue = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led3), gpios, {0});

static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
// static struct gpio_dt_spec button = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); //OK 

static struct gpio_callback button_cb_data;

uint8_t btn_count=0;

#define LOG_MODULE_NAME app
LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG);

struct bt_conn *current_conn;

void on_connected(struct bt_conn *conn, uint8_t err);
void on_disconnected(struct bt_conn *conn, uint8_t reason);
void on_notif_changed(enum bt_button_notifications_enabled status);
void on_data_received(struct bt_conn *conn, const uint8_t *const data, uint16_t len);

struct bt_conn_cb bluetooth_callbacks = {
	.connected		    = on_connected,
	.disconnected   	= on_disconnected,
	// .le_param_req		= le_param_req,
	// .le_param_updated	= le_param_updated
};

struct bt_remote_service_cb remote_callbacks = {
	.notif_changed = on_notif_changed,
	.data_received = on_data_received,
};

void on_connected(struct bt_conn *conn, uint8_t err){
	struct bt_conn_info info;

	if(err){
		LOG_INF("connection err %d", err);
		return;
	}

	LOG_INF("Connected OK");
	current_conn = bt_conn_ref(conn);
	gpio_pin_set(led.port, led.pin, 1); //on led
}

void on_disconnected (struct bt_conn *conn, uint8_t reason){
	LOG_INF("On disconnected, reason %d", reason);
	if (current_conn){
		bt_conn_unref(current_conn);
		current_conn = NULL;
	}
	gpio_pin_set_dt(&led, 0); //off led 
}

void on_notif_changed(enum bt_button_notifications_enabled status){
	if (status == BT_BUTTON_NOTIFICATIONS_ENABLED){
		LOG_INF("Notification enabled");
	} else {
		LOG_INF("Notifications disable");
	}
}

void on_data_received(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
{
	uint8_t temp_str[len+1];
	memcpy(temp_str, data, len);
	temp_str[len] = 0x00;

	LOG_INF("Received data on conn %p. Len: %d", (void *)conn, len);
	LOG_INF("Data: %s", temp_str);
}

void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
	int err=0;
	uint32_t bit_to_pin = 0;
	for (int i = 0; i < 32; i++) {
		if ((pins >> i) == 1) {
			bit_to_pin = i;
			break;
		}
	}
	// printk("Button pressed at %" PRIu32 "\n", k_cycle_get_32()); //CDC ACM OK 
	
	gpio_pin_toggle(led.port, led.pin); //OK 
	btn_count++;
	LOG_INF("Button %d pressed %d", bit_to_pin, btn_count);
	set_button_value(btn_count);

	err = send_button_notification(current_conn, btn_count, 1);
	if (err){
		LOG_ERR("couldn't send notification, err: %d", err);
	}
}

void main(void)
{
	int ret, err;
	if (!device_is_ready(led.port)) return;
	if (!device_is_ready(led1_blue.port)) {
		return;
	}
	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_INACTIVE); //init low 
	if (ret < 0) return;
	gpio_pin_configure_dt(&led1_blue, GPIO_OUTPUT);

	/* USB CDC ACM */
	const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
	uint32_t dtr = 0;
	if (usb_enable(NULL)) {
		return;
	}
	/* Poll if the DTR flag was set, chỗ này sẽ đợi mở terminal mới thực hiện tiếp */
	while (!dtr) {
	 	uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
	 	/* Give CPU resources to low priority threads. */
		k_sleep(K_MSEC(100));
	}
	/*************** end CDC ACM ***************/
	
	LOG_INF("Hello CDC ACM BLE from: %s\n", CONFIG_BOARD);
	
	if (!device_is_ready(button.port)) {
		LOG_ERR("Error: button device %s is not ready\n",
		       button.port->name);
		k_sleep(K_MSEC(5000));
		return;
	}
	ret = gpio_pin_configure_dt(&button, GPIO_INPUT | GPIO_PULL_UP); 
	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_RISING); 
	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); 
	gpio_add_callback(button.port, &button_cb_data); 

	/* 
		
	 */
	err = bluetooth_init(&bluetooth_callbacks, &remote_callbacks);
	if (err){
		LOG_ERR("Bluetooth returned %d", err);
	}

	LOG_INF("RUNNING");

	while (1) {
		// printk("Hello World! %s\n", CONFIG_ARCH);
		k_sleep(K_SECONDS(1));
		// k_sleep(K_MSEC(300));
		// btn_count++;
		// send_button_notification(current_conn, btn_count, 1);

		gpio_pin_toggle_dt(&led1_blue);	
	}
}
Parents
  • Hello,

    Because using dongle instead of nrf52840-DK i was implement USB CDC ACM console follow example code (for debug),

    What does that mean? Do you get the log module output through the USB (LOG_INF(), LOG_ERR(), ...), or are you able to send custom log messages through the USB? The reason I ask is because the log module will let you know if anything is wrong, while a custom log module isn't aware of those errors. 

    Does your log every say: "couldn't send notification, err: %d", err" if the notifications are either enabled or disabled before it reboots?

    When it reboots? Does the log say anything?

    I really recommend that you get hold of a DK when developing applications. It makes things a lot easier for you, being able to step through the code to see what's going on.

    Best regards,

    Edvin

  • Hi Edvin, 

    Does your log every say: "couldn't send notification, err: %d", err" if the notifications are either enabled or disabled before it reboots?

    Yes, when notification are disable my log say that, here my log when notification disable and press button:

    [00:05:46.200,775] <inf> app: Button 6 pressed 1
    [00:05:46.200,836] <wrn> bt_gatt: Device is not subscribed to characteristic
    [00:05:46.200,866] <inf> remote: send button notification code: -22
    [00:05:46.200,866] <err> app: couldn't send notification, err: -22
    [00:05:46.201,110] <inf> app: Button 6 pressed 2
    [00:05:46.201,171] <wrn> bt_gatt: Device is not subscribed to characteristic
    [00:05:46.201,202] <inf> remote: send button notification code: -22
    [00:05:46.201,202] <err> app: couldn't send notification, err: -22

    when notification enable my log say:

    00:10:09.652,130] <inf> remote: notification enabled
    [00:10:09.652,160] <inf> app: Notification enabled

    When it reboots? Does the log say anything?

    when notification are enable and i press button, it will disconnect Bluetooth and reboot. 

    [00:10:09.652,130] <inf> remote: notification enabled
    [00:10:09.652,160] <inf> app: Notification enabled
    
    
    Disconnected
    
    Connected via Serial Port with settings /dev/tty.usbmodem141301 115200 8n1 rtscts:off

Reply
  • Hi Edvin, 

    Does your log every say: "couldn't send notification, err: %d", err" if the notifications are either enabled or disabled before it reboots?

    Yes, when notification are disable my log say that, here my log when notification disable and press button:

    [00:05:46.200,775] <inf> app: Button 6 pressed 1
    [00:05:46.200,836] <wrn> bt_gatt: Device is not subscribed to characteristic
    [00:05:46.200,866] <inf> remote: send button notification code: -22
    [00:05:46.200,866] <err> app: couldn't send notification, err: -22
    [00:05:46.201,110] <inf> app: Button 6 pressed 2
    [00:05:46.201,171] <wrn> bt_gatt: Device is not subscribed to characteristic
    [00:05:46.201,202] <inf> remote: send button notification code: -22
    [00:05:46.201,202] <err> app: couldn't send notification, err: -22

    when notification enable my log say:

    00:10:09.652,130] <inf> remote: notification enabled
    [00:10:09.652,160] <inf> app: Notification enabled

    When it reboots? Does the log say anything?

    when notification are enable and i press button, it will disconnect Bluetooth and reboot. 

    [00:10:09.652,130] <inf> remote: notification enabled
    [00:10:09.652,160] <inf> app: Notification enabled
    
    
    Disconnected
    
    Connected via Serial Port with settings /dev/tty.usbmodem141301 115200 8n1 rtscts:off

Children
  • Can you send me a copy of your project, so that I can try to reproduce it on a DK?

    So it just disconnects from the Serial Port, suggesting that the application crashed, and it is not able to print it in the log. I am afraid it is still very hard to develop without a debugger. So you should really consider getting hold of a DK. But please send me the project, and I can look at it for this issue in particular.

    BR,
    Edvin

  • Can you send me a copy of your project, so that I can try to reproduce it on a DK

    Sure, how can i send to you !?

    So you should really consider getting hold of a DK

    I dont have nrf52840DK, i have nrf5340-DK, i try implement to nrf5340-DK but not success. I struggle with multiCore on nrf5340 so maybe i will stick to nrf52840 for current project. 

  • You can upload it here. Just drag-n-drop it into where you are typing the messages.

    BR,
    Edvin

  • Ok, so I saw what you reported, and then I ripped out the USB part of your code, and replaced it with UART logging. This is the log from trying to send the notification:

    And since the USB is running as part of your application, it was not able to print the log via USB.

    These are the assert that is causing it to reset:

    	struct net_buf *buf;
    
    	/*
    	 * PDU must not be allocated from ISR as we block with 'K_FOREVER'
    	 * during the allocation
    	 */
    	__ASSERT_NO_MSG(!k_is_in_isr());

    So apparently, it has to do with the way that you have set up your button handler. 

    I either suggest that you use the button handler that is used in the webinar, or you need to schedule the work to be handled outside of a direct interrupt (which your button handler is). The problem is that if it wasn't for the assert, then your application would hang forever, because it will be waiting for an interrupt with the same or lower priority than what it already is running. 

    I guess that dk_buttons_and_leds.h/.c will do this for you.

    And again, the dongle is not a good board to write code on, exactly because of the lack of debugging and seeing the logs properly, like in this case.

    BR,

    Edvin

Related