Sending data over bluetooth to a peripheral UART

Greetings Nordic Team,

I am trying to pass data from an application on a dk-nrf52840 to a nrf52840-dongle whose uart is connected to the uart on a microcontroller.
Using the example programs for central_uart and peripheral_uart in nrf connect desktop. everything works fine sending data to and from the respective central and peripheral uarts.
However, I need to send internal data from the application on the dk to the dongles uart (and vice versa). I thought it would be simple enough to just use the
bt_nus_client_send() function, and replace the buf->data and buf->len with my own data. Alas, this only results in an error.

//this is my attempt to use bt_nus_client_send()
char internal_data[UART_BUF_SIZE]={"Jim was here."};
uint16_t length = sizeof(internal_data);
err = bt_nus_client_send(&nus_client, internal_data, length);
if (err) {
LOG_WRN("Fudge! Failed to send data over BLE connection"
"(err %d)", err);
}

//this is the error
<wrn> central_uart: Fudge! Failed to send data over BLE connection(err -128)

//this is the working sample code
for (;;) {
/* Wait indefinitely for data to be sent over Bluetooth */
struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
K_FOREVER);

err = bt_nus_client_send(&nus_client, buf->data, buf->len);
if (err) {
LOG_WRN("Failed to send data over BLE connection"
"(err %d)", err);
}

err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
if (err) {
LOG_WRN("NUS send timeout");
}
}
any sugestions?

Parents
  • Greetings Karl,

    Thank you for your timely response.
    Thank you for showing a link to all error codes.
    If I force the issue by changing my code to:

    char internal_data[UART_BUF_SIZE]={"Jim was here.\r\n"};
    uint16_t length = sizeof(internal_data);
    printf("Sending %s to dongle\n\r",internal_data);
    do{
    err = bt_nus_client_send(&nus_client, internal_data, length);
    if (err) {
    LOG_WRN("Initial Error# %d", err);
    err = bt_nus_client_send(&nus_client, internal_data, length);
    LOG_WRN("2nd Error# %d", err);
    }
    }while(err);

    I get the following in the debug terminal (this repeats).
    ...
    <wrn> central_uart: Initial Error# -128
    <wrn> central_uart: 2nd Error# -128
    <wrn> central_uart: Initial Error# -128
    <wrn> central_uart: 2nd Error# -128
    <wrn> central_uart: Initial Error# -128
    <wrn> central_uart: 2nd Error# -128
    <wrn> central_uart: Initial Error# -128
    <wrn> central_uart: 2nd Error# -128
    <inf> central_uart: Service discovery completed
    <wrn> central_uart: Initial Error# -128
    <wrn> central_uart: 2nd Error# 0
    <err> os: r0/a1: 0x00000004 r1/a2: 0x00000081 r2/a3: 0x00000001
    <err> os: r3/a4: 0x00020259 r12/ip: 0x00000000 r14/lr: 0x00023f27
    <err> os: xpsr: 0x41000000
    <err> os: Faulting instruction address (r15/pc): 0x0002a800
    <err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
    <err> os: Current thread: 0x20001a20 (unknown)
    <err> fatal_error: Resetting system

    So it appears my function gets executed before bluetooth initialization is
    finished. I could work with that.
    The data does get sent to and received by the peripheral
    dongle. YAY!!!
    But then I get a self destruct error causing the system to reset/reboot.

    This is the message I get on the central device console.

    Starting Bluetooth Central UART example
    Sending Jim was here. to dongle

    ASSERTION FAIL [z_spin_lock_valid(l)] @ WEST_TOPDIR/zephyr/include/spinlock.h:129
    Recursive spinlock 0x1079d
    Starting Bluetooth Central UART example
    Sending Jim was here. to dongle

    ASSERTION FAIL [z_spin_lock_valid(l)] @ WEST_TOPDIR/zephyr/include/spinlock.h:129
    Recursive spinlock 0x1079d

    And the cycle repeats ad infinitum.

    Any suggestions for avoiding a fatal error?

  • Hello,

    Jim Ellyson said:
    Thank you for your timely response.
    Thank you for showing a link to all error codes.

    No problem at all, I am happy to help! :) 

    Jim Ellyson said:
    If I force the issue by changing my code to:

    The best approach here depends on the requirements and constraint of your application - i.e if it is just 'spewing' sensor data, and it is not important if some data is lost, or if every piece of data needs to get across the link so long as the link is active. In case of the latter you should instead make sure that you are in a connection before you start sending data, and implement a ring-buffer for storage of any data that is not successfully queued for transmission (whenever the call to bt_nus_client_send fails, for whatever reason) to avoid this data being lost.
    In case of the former, you are a lot more free with regards to the approach, and you could basically just ignore the failure and move on to the next sample.

    The issue with your currently implementation is that your device immediately will get stuck in this infinite while-loop, because there is no telling when you will actually enter into a connection. This is why I would not recommend using a while loop for this, since the bt_nus_client_send can start failing at any time, such as if the connection is suddenly terminated by the peer.
    If you are to keep the current setup I would at the very least add specific error handling, i.e make the different handling specific to the different errors that you expect could be returned. In this case, the handling for the -128 error code could for example be to buffer the attempted data (if necessary) and then stop re-trying to send (since you know this will continue to fail so long as you are not in a connection anymore).

    Best regards,
    Karl

Reply
  • Hello,

    Jim Ellyson said:
    Thank you for your timely response.
    Thank you for showing a link to all error codes.

    No problem at all, I am happy to help! :) 

    Jim Ellyson said:
    If I force the issue by changing my code to:

    The best approach here depends on the requirements and constraint of your application - i.e if it is just 'spewing' sensor data, and it is not important if some data is lost, or if every piece of data needs to get across the link so long as the link is active. In case of the latter you should instead make sure that you are in a connection before you start sending data, and implement a ring-buffer for storage of any data that is not successfully queued for transmission (whenever the call to bt_nus_client_send fails, for whatever reason) to avoid this data being lost.
    In case of the former, you are a lot more free with regards to the approach, and you could basically just ignore the failure and move on to the next sample.

    The issue with your currently implementation is that your device immediately will get stuck in this infinite while-loop, because there is no telling when you will actually enter into a connection. This is why I would not recommend using a while loop for this, since the bt_nus_client_send can start failing at any time, such as if the connection is suddenly terminated by the peer.
    If you are to keep the current setup I would at the very least add specific error handling, i.e make the different handling specific to the different errors that you expect could be returned. In this case, the handling for the -128 error code could for example be to buffer the attempted data (if necessary) and then stop re-trying to send (since you know this will continue to fail so long as you are not in a connection anymore).

    Best regards,
    Karl

Children
No Data
Related