Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Issue when calling "ble_nus_c_string_send" multiple times to send multiple single bytes

Hi,

I am using the ble_app_uart_c example for the ble_central of SDK 12.2.0 to send data over UART to a nrf52832 based peripheral. When following the format as suggested in the example everything appears to be working fine (terminate data to be sent with \n). I sucessfully sent commands with 60 bytes and \n terminated spread across 3 BLE packets at 20 bytes payload each.

However, when commenting out the section that tests for \n or size>20 bytes my code stops working (see attached code snippet). I am basically trying to force sending each individual byte,  not only when certain conditions are met. When sending small amounts (less than 5 bytes) it still works ok, but when sending more than 5 bytes the code seems to be stuck at line "while (ble_nus_c_string_send(&m_ble_nus_c, data_array, index) != NRF_SUCCESS)" and I am struggling to find out why. Could someone please point me in the right direction?

void uart_event_handle(app_uart_evt_t * p_event)
{
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint8_t index = 0;

    switch (p_event->evt_type)
    {
        /**@snippet [Handling data from UART] */
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
            index++;

            //if ((data_array[index - 1] == '\n') || (index >= (BLE_NUS_MAX_DATA_LEN)))
            //{
                while (ble_nus_c_string_send(&m_ble_nus_c, data_array, index) != NRF_SUCCESS)
                {
                    // repeat until sent.
                }
                index = 0;
            //}
            break;
        /**@snippet [Handling data from UART] */
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}

Parents
  • Hi,

    It would be interesting to see what value ble_nus_c_string_send() returns if not NRF_SUCCSS. Maybe you can change your code to something like this, and then debug to find out:

    uint32_t err_code;
    do
    {
        err_code = ble_nus_c_string_send(&m_ble_nus_c, data_array, index);
    }while(err_code != NRF_SUCCESS);

    You can also add APP_ERROR_CHECK(err_code) between line 4 and 5 to have your code end up in an error handler and print your errors to a terminal. 

  • Hi Martin,

    thanks for your help. I changed my code to what you suggested and also added the APP_ERROR_CHECK(err_code). The error code is 0x3004 and the error handler prints this:

    0> SDH:DEBUG:sd_ble_enable: RAM start at 0x20001fe8
    0> BLE_DB_DISC:INFO:Starting discovery of service with UUID 0x1 for Connection handle 0
    0> BLE_DB_DISC:INFO:Found service UUID 0x1
    0> BLE_DB_DISC:INFO:Discovery of service with UUID 0x1 completed with success for Connection handle 0
    0> APP_ERROR:ERROR:Fatal

    Can you see from that what the issue is?

    Thanks

  • Hi,

    thanks for your reply. Unfortunately I'm not having much luck with this. I compiled and flashed the UART examples for central and peripheral from SDK v13.1 and S132 v4 but still get an error when trying to send single bytes multiple times. At the moment the maximum amount of bytes I can send is 27 (that's 27 times 1 byte payload, so 27 packets). When attempting to send 28 bytes the transmitter resets and I am getting the following error message on the Segger RTT terminal:

     0> :ERROR:Error: ID: 16385, PC: 0x0
     0> :ERROR:Error: ID: 1, PC: 0x1AAA4
     0> :ERROR:Error: Code: 0x0579 (1401), Line: 1024, File: KGJ`hó

    Are you able to decipher this error message?

    Thanks.

  • Hi,

    In this case the program counter (PC) points to an assert that originates inside the Softdevice (PC value is smaller than the Softdevice's flash size). I'll have to consult with the Softdevice team to get an explanation of the assert. Are you using S132 v4.0.2 which is bundled with SDK 13.1 by default? If so, can you try upgrading to v4.0.5? (Upgrading to v4.0.5 requires no changes in your code)

  • BTW: I'll be traveling the rest of the week, so the progress might be slow until next week. 

  • Hi, yes I originally used the SDK13.1 with bundled s132 v4.0.2 softdevice. I upgraded to S132 v4.0.5 but I am still getting an error and the firmware resets when attempting to transmit more than 28 bytes of payload. I am attaching the full debug log of one session which attempts to transmit 29 bytes. It's itneresting that when transmitting 28 bytes there is no issue at all. But when attempting to transmit 29 bytes not a single byte actually arrives at the receiver, although the RTT log would indicate that it started transmitting over BLE.

     0> SDH:DEBUG:RAM start at 0x200020c8.
     0> APP:INFO:BLE UART central example started.
     0> APP:INFO:Connecting to target 19f0a32761e0
     0> APP:INFO:Connected to target
     0> BLE_DB_DISC:DEBUG:Starting discovery of service with UUID 0x1 on connection handle 0x0.
     0> nrf_ble_gatt:DEBUG:Requesting to update ATT MTU to 158 bytes on connection 0x0.
     0> nrf_ble_gatt:DEBUG:sd_ble_gattc_exchange_mtu_request() on connection 0x0 returned busy, will retry.
     0> nrf_ble_gatt:DEBUG:Requesting to update data length to 162 on connection 0x0.
     0> nrf_ble_gatt:DEBUG:Peer on connection 0x0 requested an ATT MTU of 64 bytes.
     0> APP:INFO:ATT MTU exchange completed.
     0> BLE_DB_DISC:DEBUG:Found service UUID 0x1.
     0> nrf_ble_gatt:DEBUG:Data length updated to 162 on connection 0x0.
     0> nrf_ble_gatt:DEBUG:max_rx_octets: 162
     0> nrf_ble_gatt:DEBUG:max_tx_octets: 162
     0> nrf_ble_gatt:DEBUG:max_rx_time: 1408
     0> nrf_ble_gatt:DEBUG:max_tx_time: 1408
     0> BLE_DB_DISC:DEBUG:Discovery of service with UUID 0x1 completed with success on connection handle 0x0.
     0> APP:INFO:Discovery complete.
     0> APP:DEBUG:Ready to send data over BLE NUS
     0> APP:DEBUG:
     0> 31                                               1               
     0> APP:DEBUG:Ready to send data over BLE NUS
     0> APP:DEBUG:
     0> 32                                               2               
     0> APP:DEBUG:Ready to send data over BLE NUS
     0> APP:DEBUG:
     0> 33                                               3               
     0> APP:DEBUG:Ready to send data over BLE NUS
     0> APP:DEBUG:
     0> 34                                               4               
     0> :ERROR:Error: ID: 1, PC: 0x11994
     0> :ERROR:Error: Code: 0x0579 (1401), Line: 1024, File: KGJ`hóˆ@h

  • Hi,

    I went ahead and tested the latest SDK 15.0.0 with S132 v6.0.0 and received the following error when sending more than 18 bytes of payload:

     0> <info> app: BLE UART central example started.
     0> <info> app: Connecting to target 19F0A32761E0
     0> <debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
     0> <debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
     0> <info> app: Connected to target
     0> <debug> ble_db_disc: Starting discovery of service with UUID 0x1 on connection handle 0x0.
     0> <debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 247 bytes.
     0> <debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
     0> <debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
     0> <info> app: ATT MTU exchange completed.
     0> <info> app: Ble NUS max data length set to 0xF4(244)
     0> <debug> ble_db_disc: Starting discovery of service with UUID 0x1 on connection handle 0x0.
     0> <debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
     0> <debug> nrf_ble_gatt: max_rx_octets: 251
     0> <debug> nrf_ble_gatt: max_tx_octets: 251
     0> <debug> nrf_ble_gatt: max_rx_time: 2120
     0> <debug> nrf_ble_gatt: max_tx_time: 2120
     0> <debug> ble_db_disc: Found service UUID 0x1.
     0> <debug> ble_db_disc: Discovery of service with UUID 0x1 completed with success on connection handle 0x0.
     0> <info> app: Discovery complete.
     0> <info> app: Connected to device with Nordic UART Service.
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  31                     |1       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  32                     |2       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  33                     |3       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  34                     |4       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  35                     |5       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  36                     |6       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  37                     |7       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  38                     |8       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  39                     |9       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  30                     |0       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  31                     |1       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  32                     |2       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  33                     |3       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  34                     |4       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  35                     |5       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  36                     |6       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  37                     |7       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  38                     |8       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  39                     |9       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  30                     |0       
     0> <error> app: Error: ID: 16385, PC: 0x2BCC9
     0> 
     0> <error> app: Error: Code: 0x0013 (19), Line: 246, File: ..\..\..\main.c
     0> 
     0> <error> app: ERROR 19 [NRF_ERROR_RESOURCES] at ..\..\..\main.c:246
     0> PC at: 0x0002BCC9
     0> <error> app: End of error report

Reply
  • Hi,

    I went ahead and tested the latest SDK 15.0.0 with S132 v6.0.0 and received the following error when sending more than 18 bytes of payload:

     0> <info> app: BLE UART central example started.
     0> <info> app: Connecting to target 19F0A32761E0
     0> <debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
     0> <debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
     0> <info> app: Connected to target
     0> <debug> ble_db_disc: Starting discovery of service with UUID 0x1 on connection handle 0x0.
     0> <debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 247 bytes.
     0> <debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
     0> <debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
     0> <info> app: ATT MTU exchange completed.
     0> <info> app: Ble NUS max data length set to 0xF4(244)
     0> <debug> ble_db_disc: Starting discovery of service with UUID 0x1 on connection handle 0x0.
     0> <debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
     0> <debug> nrf_ble_gatt: max_rx_octets: 251
     0> <debug> nrf_ble_gatt: max_tx_octets: 251
     0> <debug> nrf_ble_gatt: max_rx_time: 2120
     0> <debug> nrf_ble_gatt: max_tx_time: 2120
     0> <debug> ble_db_disc: Found service UUID 0x1.
     0> <debug> ble_db_disc: Discovery of service with UUID 0x1 completed with success on connection handle 0x0.
     0> <info> app: Discovery complete.
     0> <info> app: Connected to device with Nordic UART Service.
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  31                     |1       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  32                     |2       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  33                     |3       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  34                     |4       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  35                     |5       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  36                     |6       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  37                     |7       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  38                     |8       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  39                     |9       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  30                     |0       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  31                     |1       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  32                     |2       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  33                     |3       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  34                     |4       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  35                     |5       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  36                     |6       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  37                     |7       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  38                     |8       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  39                     |9       
     0> <debug> app: Ready to send data over BLE NUS
     0> <debug> app:  30                     |0       
     0> <error> app: Error: ID: 16385, PC: 0x2BCC9
     0> 
     0> <error> app: Error: Code: 0x0013 (19), Line: 246, File: ..\..\..\main.c
     0> 
     0> <error> app: ERROR 19 [NRF_ERROR_RESOURCES] at ..\..\..\main.c:246
     0> PC at: 0x0002BCC9
     0> <error> app: End of error report

Children
  • Hi

    Error NRF_ERROR_RESOURCES means that you are still filling up the Softdevice's transmit queue too fast. What kind of central device do you use for testing? Have you tried more than one?

    There are a couple of suggestions here. Have you tried something similar?

    Can you upload your project if you are still stuck?

  • Hey,

    I am using two of the Rigado BMD-300 evaluation kits ( Rigado Eval Kit ) which are similar to the Nordic pca 10040 boards. One is configured as central and the other one as peripheral device. My project is the exact SDK UART example code (ble_app_uart_c and ble_app_uart) and I only made a small change to the function uart_event_handle of the file main.c of the central example. The single change was to comment out the if statement as indicated in my very first post here. The peripheral example code is unchanged.

  • Hi,

    I think I finally see the problem here. The uart_event_handle() function is an interrupt, so what you are doing is transmitting single UART bytes from within an interrupt context.

    By default the SDK configures the UART to use a baud rate of 115200. This means that if you are receiving strings of UART data you will receive new bytes every 10 us or so. The problem is that the lowest BLE connection interval you can have is 7.5 ms so you are receiving UART data way faster than you can transmit them. Unless you buffer the UART data and transmit as many bytes as you can per connection interval. 

    Furthermore, because we are using while loops inside the UART handler, the code is stuck there waiting for a successful BLE notification to be sent while new UART data mercilessly keeps flowing in. This creates a queue of interrupts and because of this the code enters some sort of deadlock (which I have yet to be able to wrap my head around). 

    The solution is to move the transmission of the data out of the interrupt and into the main context. Store the incoming UART bytes and set a flag in the UART handler. Then check this flag inside the main loop. If the flag is set, call ble_nus_data_send() and transmit the data. However, losing some of the UART data is inevitable if you insist on transmitting one by one byte. 

  • Hi Martin,

    thatnks for your explanation, this makes a lot of sense. I managed to implement a circular buffer that gets filled in the interrupt routines and in the main section I added some code to check if there is anything new in the buffer and starts the BLE transmission if required. I also added some functionality to pack more bytes into one message and only in certain circumstances sends single bytes in a BLE message. Those two additions seem to work and I am now able to transmit data in both directions with variable and unknown data packet lengths.

    Thanks for your help on this.

Related