Zephyr crashing when I connect to a device

  has been helping me connect to a device and I am finally able to do that, but as soon as I do, Zephyr crashes.

This is with a lightly modified central_uart project

[00:00:00.024,810] <0x1b>[0m<inf> central_uart: Scan module initialized<0x1b>[0m␍␊

[00:00:00.024,810] <0x1b>[0m<inf> central_uart: NUS Client module initialized<0x1b>[0m␍␊

[00:00:00.029,846] <0x1b>[0m<inf> central_uart: Scanning successfully started<0x1b>[0m␍␊

[00:00:00.093,719] <0x1b>[0m<inf> central_uart: Filters matched. Address: E8:A0:DB:24:21:62 (random) connectable: 1<0x1b>[0m␍␊

[00:00:00.289,886] <0x1b>[0m<inf> central_uart: Connected: E8:A0:DB:24:21:62 (random)<0x1b>[0m␍␊

[00:00:00.290,039] <0x1b>[1;33m<wrn> central_uart: Failed to set security: -12<0x1b>[0m␍␊

[00:00:00.290,100] <0x1b>[1;31m<err> central_uart: Stop LE scan failed (err 0)<0x1b>[0m␍␊

[00:00:00.441,497] <0x1b>[0m<inf> central_uart: MTU exchange done<0x1b>[0m␍␊

ASSERTION FAIL [conn] @ WEST_TOPDIR/zephyr/subsys/bluetooth/host/gatt.c:5433␍␊

⇥ invalid parameters␍␊

␍␊

[00:00:01.791,351] <0x1b>[0m<inf> central_uart: Service discovery completed<0x1b>[0m␍␊

[00:00:01.800,994] <0x1b>[1;31m<err> os: r0/a1: 0x00000004 r1/a2: 0x00001539 r2/a3: 0x20000b60<0x1b>[0m␍␊

[00:00:01.800,994] <0x1b>[1;31m<err> os: r3/a4: 0x00000004 r12/ip: 0x00000000 r14/lr: 0x000217df<0x1b>[0m␍␊

[00:00:01.801,025] <0x1b>[1;31m<err> os: xpsr: 0x21000000<0x1b>[0m␍␊

[00:00:01.801,025] <0x1b>[1;31m<err> os: Faulting instruction address (r15/pc): 0x00031072<0x1b>[0m␍␊

[00:00:01.801,086] <0x1b>[1;31m<err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0<0x1b>[0m␍␊

[00:00:01.801,116] <0x1b>[1;31m<err> os: Current thread: 0x20002568 (BT RX WQ)<0x1b>[0m␍␊

[00:00:01.869,415] <0x1b>[1;31m<err> os: Halting system<0x1b>[0m␍␊

The program crashes here:

 

return snprintk(str, len, "%02X:%02X:%02X:%02X:%02X:%02X (%s)",
addr->a.val[5], addr->a.val[4], addr->a.val[3],
addr->a.val[2], addr->a.val[1], addr->a.val[0], type);

Which is in
addr.h (sic) Quite what code is doing in a header file is beyond me.

The prototype for the function is this:

int bt_addr_le_to_str(const bt_addr_le_t *addr, char *str, size_t len);

The values passed look reasonable to me.
addr->a.val[0]-[5] have the correct MAC address in it
str has (in decimal) 23 0 ... in it so that looks like it's just got a single character and anyway,
it shouldn't make a difference because, surely, that's being written into.

len = 30

type ends up with "random" in it.

I am assuming
snprintk is based on
snprint and so shouldn't copy more than len bytes anyway.

The string being used is that is passed into bt_addr_le_to_str is:
char addr[BT_ADDR_LE_STR_LEN];
and BT_ADDR_LE_STR_LEN is set to 30 so that all stacks up nicely.
Can anyone give me some pointers as to what might be wrong here?
BTW   that little project you sent me does not crash like this, but I can't
see where you set up the characteristics for that project, there is no reference to
BT_GATT_SERVICE_DEFINE anywhere in it. I would happily just mod that if I could work out how you've set up
its service and characteristics.
Thanks


Parents
  • Hello,

    ASSERTION FAIL [conn] @ WEST_TOPDIR/zephyr/subsys/bluetooth/host/gatt.c:5433

    This error message shows that an assertion is raised in gatt.c at this line: https://github.com/nrfconnect/sdk-zephyr/blob/0bc3393fb112ec80ebeab48cd023d69b1e9db757/subsys/bluetooth/host/gatt.c#L5433 which suggests that the 'conn' pointer passed to your bt_gatt_subscribe() call is set to NULL. 

    hat little project you sent me does not crash like this, but I can't
    see where you set up the characteristics for that project, there is no reference to

    I copied the NUS service and NUS client source files and placed them in the project's source directory (I also renamed every occurrence of 'nus' to 'custom').

    Best regards,

    Vidar

  • Morning,

    I did look with the debugger at that pointer and that's not the issue.

    The crash doesn't come until snprintk in bt_addr_le_to_str

    and as I say, in the first post, The values in passed to:

    return snprintk(str, len, "%02X:%02X:%02X:%02X:%02X:%02X (%s)",
    addr->a.val[5], addr->a.val[4], addr->a.val[3],
    addr->a.val[2], addr->a.val[1], addr->a.val[0], type);

    Look fine:



    This smacks more of a stack overflow to me,
    but I've massively increased the main stack size in prj.conf
    to no or little avail.

    The message on crash changes slightly:

    [00:00:07.404,510] <0x1b>[1;31m<err> os: Fault during interrupt handling␊

    <0x1b>[0m␍␊

    [00:00:07.404,571] <0x1b>[1;31m<err> os: Current thread:

    0x20002568 (BT RX WQ)<0x1b>[0m␍␊

    This looks like it;s some sort bluetooth receive issue? However, all I'm doing is

    connecting, no actual data is being sent as yet.

    On the subject of your code, it's not the peripheral_uart I'm trying, it's the

    central_uart which doesn't have those definitions in it. .

     

  • It seems you are encountering the same assertion as before:

    DiBosco said:

    ASSERTION FAIL [conn] @ WEST_TOPDIR/zephyr/subsys/bluetooth/host/gatt.c:5433␍␊

    ⇥ invalid parameters␍␊

    Can you place a breakpoint at this line to confirm that the conn pointer is not set? Also, were you able to reproduce this with the central project I uploaded?

  • OK, in gatt.c the pointer looks like it is NULL.

    That function really should have:

    if ((NULL != conn) && (NULL != params))

    at the start of that function to stop that issue.

    I think we should forget about this particular project though, because...

    ----------------------------------------------------------------------------------

    Your program does not do this, but although I can get comms in over the UART, write it to

    the characteristic

    in the remote node and I get notification it's been read by  the remote node

    becauswe the ble_data_sent function is called.


    However,  I never get the
    ble_data_received callback function being called, so

    either the data isn't being quite sent to the write characteristic properly in your app

    or something's wrong

    with the setup fior the read characteristic in your app. We know the remote node works correctly

    because it's been working with a Raspberry Pi just fine.

    I'm assuming that, somehow, when you set up the syatem to be able to write to

    BT_UUID_CUSTOM_TX

    That you are setting up some area of memoryt that is
    automatically the same size as the characteristic in our custom
    remote node?

    I did put this:

    CONFIG_BT_L2CAP_TX_MTU=247
    CONFIG_BT_BUF_ACL_RX_SIZE=251
    CONFIG_BT_BUF_ACL_TX_SIZE=251

    in prj.conf
    and changed:

    #define UART_BUF_SIZE 240

    from it being just 20 bytes long to allow
    for our larger characteristics.

    ----------------------------------------------------------------------------------

    In your program I am guessing via
    custom_client_init you somehow tell the system

    that if it finds the the service you are telling it to call ble_data_received. I'm again

    guessing that

    bt_custom_handles_assign does the magic of knitting them together
    in one of those
    memset lines somewhere? Or maybe:

    custom_c->handles.rx = gatt_desc->handle;

    But I could be wrong, I can't follow that
    code I'm afraid. What should be looking for here in
    an attempt to ascertain whether that is all set up correctly?
     

  • The NUS service only supports notifications on the TX characteristic (Nordic UART service). However, from the screenshot you posted earlier of the nRF Connect app, it seems that both of your characteristics support notifications. This means the GATT client must be modified to subscribe to both characteristics (i.e. custom_client.c if you're using my project).

  • So are you saying the central_uart project needs to be modified (in this case  the one you supplied) so that the Rx characteristic in central subscribes to the Tx characteristic in the remote node?

    When I use your peripheral_uart to talk to your central with my UUIDs in, I don't need to do anything else other than send data into the UART on the peripheral and it appears on the central_uart project's UART output.

    If I look with nrf connect on my Android  phone, the Tx  on the remote node - whether it be the Nordic DK running peripheral_uart, or our custom device, (which is the RX on the central_uart project) it is notify only, so why would it work on peripheral_uart and not our custom device. What am I  not understanding here?

  • I thought you were using the Nordic UART service with custom UUIDs. However, after looking at the the nRF Connect screendump you shared again, I notice several differences. For instance, your service includes three or more characteristics, while the UART service only has two. The client code I provided will only subscribe to notifications from the first characteristic with UUID:651135b0-dfe9-45a2-95c1-46552a8a77e2.

    I don't know which characteristics the peripheral is supposed to send notifications on in your case.

Reply
  • I thought you were using the Nordic UART service with custom UUIDs. However, after looking at the the nRF Connect screendump you shared again, I notice several differences. For instance, your service includes three or more characteristics, while the UART service only has two. The client code I provided will only subscribe to notifications from the first characteristic with UUID:651135b0-dfe9-45a2-95c1-46552a8a77e2.

    I don't know which characteristics the peripheral is supposed to send notifications on in your case.

Children
  • I've tried the 52840DK using your peripheral UART and that works. So I have done

    UART         |                                BLE                                                               | UART

    PC UART<->CENTRAL_UART on 52840<-><PERIPHERAL_UART on 528040<->PC UART


    When I try to connect to the custom unit, which uses the very same UUIDs as your custom program, rather than peripheral_uart, it does not work.

    The custom unit has successfully done exactly the same thing I'm trying to achieve here, but with a Raspberry Pi: 

    UART         |                                BLE                                  | UART

    PC UART <-> Raspberry Pi with BLE <-> Custom Unit<->STM32

    I want to replace that with

    UART         |                                BLE                                    | UART

    PC UART <-> CENTRAL_UART on 52840<-> Custom Unit<->STM32

    BTW, I know how crazy this is, but it's what we've been asked to do.

    The custom unit's service for which you had the screen shot has the following setup in its firmware where Rx is data going into it and Tx is data going out.

    // the service
    #define BASE_UUID128   "2a1f963c-143a-4f7d-9107-6315196a02a6"
    #define BASE_UUID16    0x963c
    // BLE Data into the custom unit (so the central_uart I'm trying to get working will write into this)
    #define RX_LENGTH      240
    #define RX_UUID128     "651135b0-dfe9-45a2-95c1-46552a8a77e2"
    #define RX_UUID16      0x35b0
    // Not sued for UART comms
    #define RX_ACK_LENGTH  2
    #define RX_ACK_UUID128 "946ba79e-3162-46d5-9ba7-8a9d08c11ff0"
    #define RX_ACK_UUID16  0xa79e
    // Data out from the custom unit into the central_uart over Bluetooth
    #define TX_LENGTH      240
    #define TX_UUID128     "e7d6274e-b765-11e9-a2a3-2a2ae2dbcce4"
    #define TX_UUID16      0x274e
    // Unused for this UART function
    #define TX_ACK_LENGTH  2
    #define TX_ACK_UUID128 "e7d629ba-b765-11e9-a2a3-2a2ae2dbcce4"
    #define TX_ACK_UUID16  0x29ba

    The custom unit is running an older Nordic device and I have successfully talked to it the custom unit by writing a Qt program on Linux to talk directly to it. So, the point being we know the custom unit works with these UUIDs

    I have tried swapping RX and TX round in custom_client.h just in case there was a BLE equivalent of a 2/3 swap needed, but that does not help.

    i.e.

    /** @brief UUID of the TX Characteristic. **/
    #define BT_UUID_CUSTOM_SRV_RX_VAL \
    BT_UUID_128_ENCODE(0x651135b0, 0xdfe9, 0x45a2, 0x95c1, 0x46552a8a77e2)

    /** @brief UUID of the RX Characteristic. **/
    #define BT_UUID_CUSTOM_SRV_TX_VAL \
    BT_UUID_128_ENCODE(0xe7d6274e, 0xb765, 0x11e9, 0xa2a3, 0x2a2ae2dbcce4)



    One ot her slight annoyance that needs sorting is this that is spat out of the UART at boot:

    *** Booting nRF Connect SDK v2.8.0-a2386bfc8401 ***␍␊

    *** Using Zephyr OS v3.7.99-0bc3393fb112 ***␍␊

    If I search for "Booting nRF Connect" in VSC it does not give me any hits. Do you

    know where that is in the source so I can get rid of it please?

  • I'm wondering if there any specific requirements for interfacing with your peripheral device or if it behaves just like the original NUS sample. For instance, if it requires notifications to be enabled on more than one characteristic to allow notifications to be sent or some kind of handshake, etc. Either way, I think it might be faster to use the nRF Connect app to determine what works and what doesn't. For example, you can check if you're able to receive data if you only enable notifications for the e7d6274e-b765-11e9-a2a3-2a2ae2dbcce4 characteristic:

    DiBosco said:
    One ot her slight annoyance that needs sorting is this that is spat out of the UART at boot:

    You can disable the boot banners by adding the following 2 lines to your project configuration file:

    CONFIG_NCS_BOOT_BANNER=n
    CONFIG_BOOT_BANNER=n

  • Thanks  for the boot banner tip.

    On the subject of writing from the Android app, I have made  some progress, This system is quite complex and the remote unit only writes when requested by a convoluted message, so I found what the standard debug request header is and wrote those 32 bytes using the BLE Scanner app by writing to characteristic UUID

    0x651135b0, 0xdfe9, 0x45a2, 0x95c1, 0x46552a8a77e2

    Now, unless and until I actually hit notify for the

    0xe7d6274e, 0xb765, 0x11e9, 0xa2a3, 0x2a2ae2dbcce4

    characteristic, I got nothing back. When I did hit notify then the
    remote node wrote some valid data into the phone.

    Is the issue that on this Zephyr app we're not subscribing
    (is that the right word) to the read characteristic?

    I'm assuming that should go on in the

    bt_custom_handles_assign

    function?

  • If it is necessary to enable notifications, how do you do that please?

  • OK, a little more info and more questions:

    Firstly - and I'm not sure this actually matters in terms of it functioning. This second line must be wrong:

    err = bt_scan_stop();
    if ((NO_ERROR == err) && (err != -EALREADY))
    {
    LOG_ERR("Stop LE scan failed (err %d)", err);
    }

    This line was originally the mind bending:

    if ((!err) && (err != -EALREADY))

    Even when written out to make it much more understandable where

    NO_ERROR is defined as 0 rather than a magic number that is
    littered throughout all this code.

    This seems like a mad line of code. If err is equal to 0
    it can't be anything else.

    However, as it's just printing out a line of debug code I
    suspect it doesn't actually matter.

    What doesn't seem to be getting called though is this:

    discovery_complete

    This is used in this:

    struct bt_gatt_dm_cb discovery_cb

    Which in turn is filled out, I think, in

    gatt_discover

    But

    gatt_discover never gets called from here:

    err = bt_conn_set_security(conn, BT_SECURITY_L1);

    if (NO_ERROR != err) // was if (err), changed for clarity
    {
    LOG_WRN("Failed to set security: %d", err);

    gatt_discover(conn);
    }

    Surely gatt_discover should be called if err *is* equal
    to 0 which is, again, defined as NO_ERROR for clarity.

    Oh, also I changed bt_conn_set_security to:

    err = bt_conn_set_security(conn, BT_SECURITY_L1);

    As we're not using security on our unit and it was giving
    me an error when it was set to L2. Does that sound right?

    gatt_discover is also called in:

    security_changed, but security_changed never gets called
    (I don't know what this is for).










Related