Bus Fault with "bt_le_adv_stop", nrf52832

Hi Team,

I am in process of modifying our existing app to work as "just works". For doing this, I disabled the callbacks in bt_conn_auth_cb:

static struct bt_conn_auth_cb conn_auth_callbacks = {
//	.passkey_display = auth_passkey_display,
//	.passkey_confirm = auth_passkey_confirm,
	.passkey_confirm = NULL,
	.passkey_display = NULL,

	.cancel = auth_cancel,
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
};

However, with above change when I run my application it is saying BUS FAULT (Precise data bus error):

: ***** BUS FAULT *****
E:   Precise data bus error
E:   BFAR Address: 0xbf080f05
E: r0/a1:  0x00000020  r1/a2:  0xbf080f05  r2/a3:  0xbf080f05
E: r3/a4:  0x00000020 r12/ip:  0x00000000 r14/lr:  0x0003ac41
E:  xpsr:  0x01000200
E: s[ 0]:  0x00000000  s[ 1]:  0x00000000  s[ 2]:  0x00000000  s[ 3]:  0x00000000
E: s[ 4]:  0x00000000  s[ 5]:  0x00000000  s[ 6]:  0x00000000  s[ 7]:  0x00000000
E: s[ 8]:  0x00000000  s[ 9]:  0x00000000  s[10]:  0x00000000  s[11]:  0x00000000
E: s[12]:  0x00000000  s[13]:  0x00000000  s[14]:  0x00000000  s[15]:  0x00000000
E: fpscr:  0x00000000
E: Faulting instruction address (r15/pc): 0x0003abde
E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
E: Current thread: 0x20002be8 (main)

On digging, I figured out that it is happening from the bt_le_adv_stop(). In our application, we stop BLE advertisement, set Adv parameter and then start advertisement every time.

If I disable this bt_le_adv_stop() or put back the ".passkey_display = auth_passkey_display", I don't see crash or BUS Error.

Could you please let me know what might be causing this BUS Fault? And how to debug this further?

Here is the snippet of the Ozone debugger when error occurred:

Thanks!

  • Hi, 

    Could you let us know where you call bt_le_adv_stop() ? 

    I assume you are using NCS prior to v2.0.0 ? 

    I did a quick test here with a sample in NCS v1.9.1 and it worked fine for me. I attached the sample. 

    peripheral_uart_justwork.zip

  • Hi Hung,

    Sorry for missing out the ncs version. We are using ncs v1.8.0.

    Peripheral uart example works for me too. However, in our application we need to update the adv packet at run time. So, whenever we want to change adv parameters, we first stop the adv, update parameters and then start adv again.

    Thanks!

  • Hi , 
    If you have a look at my example I also did a bt_le_adv_stop before starting it again. Could you check why it work in my example but not yours ? Please check where you call the function. 

  • Hi Hung,

    Thanks for the reply. As I said example works for me too with bt_le_adv_stop, however, it's giving issue in our application. And this exactly where I seek your help.

    We have NFC interface available and whenever there is an NFC sense, we start advertising. And in every advertising, we are changing the payload of adv packet. So, on NFC field ON evet, we start a worker thread, that stops BLE adv, updates adv payload and starts the adv again.

    Here are some of the symptoms that we know so far:

    - If we comment bt_le_adv_stop(), there is no BUS fault

    - If we keep ".passkey_display = auth_passkey_display,", there is no BUS fault

    - If we uncomment bt_le_adv_stop() and keep ".passkey_display = NULL,", there is a BUS fault

    So, we really want to understand, how to debug this BUS fault? Can this be side effect of stack corruption?

    What are the ways we can debug this BUS fault?

    Thanks.

  • Hi Hung,

    I think I am able to reproduce the issue on the sample application. I am attaching main.c here for your reference.

    To summarize, in this sample, I am just trying to start the Extended BLE Advertisement every 5 seconds with some updated value in the adv data (which is kind of our usecase).

    When I run this sample on nrf52832, it is never going beyond ble_adv_stop() and board keeps rebooting.

    Could you please check and let me know what's going wrong here?

    Thanks!

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     *  @brief Nordic UART Bridge Service (NUS) sample
     */
    
    #include <zephyr/types.h>
    #include <zephyr.h>
    #include <drivers/uart.h>
    #include <usb/usb_device.h>
    
    #include <device.h>
    #include <soc.h>
    
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    #include <bluetooth/hci.h>
    
    #include <bluetooth/services/nus.h>
    
    #include <dk_buttons_and_leds.h>
    
    #include <settings/settings.h>
    
    #include <stdio.h>
    
    #include <logging/log.h>
    
    #define BLE_ADV_DATA_LEN				(10u)
    #define BLE_MANUFACTURE_ID_LENGTH		(2u)
    #define BLE_SERIAL_NUMBER_LENGTH        (8u)
    #define BLE_ADV_LEN						(BLE_ADV_DATA_LEN + BLE_MANUFACTURE_ID_LENGTH + BLE_SERIAL_NUMBER_LENGTH)
    
    #define DEVICE_NAME CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
    
    #define BLE_ADV_DURATION_SECONDS        (180)  // Bluetooth adv duration in seconds. Set 0 to keep it advertising forever.
    #define BLE_ADV_TIMEOUT                 (BLE_ADV_DURATION_SECONDS * 100)  // N * 10ms for advertiser timeout
    #define BLE_ADV_EVENTS					(3)
    
    static uint8_t app_adv_data[BLE_ADV_LEN] = {0};
    
    static uint8_t app_data[BLE_ADV_DATA_LEN] = {0};
    
    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_MANUFACTURER_DATA, app_adv_data, BLE_ADV_LEN),
    };
    
    static struct bt_le_ext_adv *adv;
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err)
    	{
    		printk("Connection failed (err %u)\n", err);
    		return;
    	}
    
    	printk("Connected\n");
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason %u)\n", reason);
    }
    
    static void security_changed(struct bt_conn *conn, bt_security_t level,
    							 enum bt_security_err err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (!err)
    	{
    		printk("Security changed: %s level %u\n", addr, level);
    	}
    	else
    	{
    		printk("Security failed: %s level %u err %d\n", addr, level, err);
    	}
    }
    
    static struct bt_conn_cb conn_callbacks = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.security_changed = security_changed,
    };
    
    int ble_update_adv_data (void) {
    	int err;
    	
    	//Update the Adv data with new value, TODO, replace actual data in app_data
    	app_data[0]++;
    
    	//Copy app data to adv array
    	memcpy(app_adv_data+BLE_SERIAL_NUMBER_LENGTH + BLE_MANUFACTURE_ID_LENGTH, app_data, BLE_ADV_DATA_LEN);
    
    	printk("Ad size=%lu\n", ARRAY_SIZE(ad));
    	err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
    	if (err) {
    		printk("Failed to set advertising data (%d)\n", err);
    		return err;
    	}
    	return 0;
    }
    
    static void auth_cancel(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing cancelled: %s\n", addr);
    }
    
    static void pairing_complete(struct bt_conn *conn, bool bonded)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing completed: %s, bonded: %d\n", addr, bonded);
    }
    
    static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing failed conn: %s, reason %d\n", addr, reason);
    }
    
    static struct bt_conn_auth_cb conn_auth_callbacks = {
    	.passkey_confirm = NULL,
    	.passkey_display = NULL,
    	.cancel = auth_cancel,
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    };
    
    static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
    {
            char addr[BT_ADDR_LE_STR_LEN] = {0};
    
            bt_addr_le_to_str(bt_conn_get_dst(conn), addr, ARRAY_SIZE(addr));
    
            printk("Received data from: %s", log_strdup(addr));
    
    				printk("Received data--> ");
    				int i;
    				for (i=0; i<len; i++) {
    					printk("[%d,%02x] ", i, data[i]);
    				}
    				printk("\n");
    		return;
    }
    
    static struct bt_nus_cb nus_cb = {
            .received = bt_receive_cb,
    };
    
    int ble_adv_stop(void) {
        int err;
    	err = bt_le_adv_stop();
    	if (err)
    	{
    		printk("Advertising failed to stop (err %d)\n", err);
    		return err;
    	}
    
    	printk("Advertising successfully stopped\n");
        return err;
    }
    
    int ble_adv_start(void) {
    	int err;
    
    	printk("Stopping BLE Adv..!!\n");
    	//Stop adv, if running to ensure we can chagne the parameters
    	ble_adv_stop();
    	printk("Stopped BLE Adv..!!\n");
    
    	ble_update_adv_data();
    
    	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_PARAM(BLE_ADV_TIMEOUT, 0));
    	if (-EALREADY == err) {
    		printk("Adv already running\n");
    		return 0;
    	} else if (err) {
    		printk("Failed to start advertising set (%d)\n", err);
    		return err;
        }
        return err;
    }
    
    
    int ble_init() {
       	int err;
    
    	bt_conn_cb_register(&conn_callbacks);
    	if (IS_ENABLED(CONFIG_BT_LBS_SECURITY_ENABLED))
    	{
    		bt_conn_auth_cb_register(&conn_auth_callbacks);
    	}
    
    	err = bt_enable(NULL);
    	if (err)
    	{
    		printk("Bluetooth init failed (err %d)\n", err);
    		return err;
    	}
    
    	if (IS_ENABLED(CONFIG_SETTINGS))
    	{
    		settings_load();
    	}
    
        err = bt_nus_init(&nus_cb);
        if (err) {
                printk("Failed to initialize UART service (err: %d)", err);
                return err;
        }
    	struct bt_le_adv_param param =
    		BT_LE_ADV_PARAM_INIT(
    				     BT_LE_ADV_OPT_USE_NAME | 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);
    
    
    	err = bt_le_ext_adv_create(&param, NULL, &adv);
    	if (err) {
    		printk("Failed to create advertiser set (%d)\n", err);
    		return err;
    	}
        
    	err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
    	if (err) {
    		printk("Failed to set advertising data (%d)\n", err);
    		return err;
    	}
    	printk("Bluetooth initialized\n");
    
        return err;
    }
    
    void main(void)
    {
    	int err;
    
    	//Set dummy manufacture ID and serial number
    	app_adv_data[0] = 0x11;
    	app_adv_data[1] = 0x22;
    	app_adv_data[2] = 0x1;
    	app_adv_data[3] = 0x2;
    	app_adv_data[4] = 0x3;
    	app_adv_data[5] = 0x4;
    	app_adv_data[6] = 0x5;
    	app_adv_data[7] = 0x6;
    	app_adv_data[8] = 0x7;
    	app_adv_data[9] = 0x8;
    
    	err = ble_init();
    	if (err)
    	{
    		printk("ble_init() failed\n");
    	}
    
    	while(1) {
    	    err = ble_adv_start();
        	if (err) {
            	printk("Can not start BLE Adv\n");
        	}
        	else {
            	printk("BLE Adv Started..!!\n\n");
        	}
    		k_sleep(K_MSEC(5000));
    	}
    
    	return;
    }

    prj.conf for reference:

    # Enable the UART driver
    CONFIG_UART_ASYNC_API=y
    CONFIG_NRFX_UARTE0=y
    CONFIG_SERIAL=y
    
    CONFIG_GPIO=y
    
    # Make sure printk is printing to the UART console
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y
    
    CONFIG_HEAP_MEM_POOL_SIZE=2048
    
    CONFIG_BT=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DEVICE_NAME="Nordic_UART_Service"
    CONFIG_BT_DEVICE_APPEARANCE=833
    CONFIG_BT_MAX_CONN=1
    CONFIG_BT_MAX_PAIRED=1
    
    # Enable the NUS service
    CONFIG_BT_NUS=y
    
    # Enable bonding
    CONFIG_BT_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    
    # Enable DK LED and Buttons library
    CONFIG_DK_LIBRARY=y
    
    # This example requires more workqueue stack
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    
    # Config logger
    CONFIG_LOG=y
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_LOG_BACKEND_RTT=y
    CONFIG_LOG_BACKEND_UART=n
    
    CONFIG_ASSERT=y
    
    CONFIG_BT_EXT_ADV=y
    

Related