This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Sending data to iOS crashes midway

Using NRF51822 + SoftDevice 130, version 2.0.0, I have written a program which reads data from on-chip flash memory and transfers it to smartphone once connection is established. In order to determine if connection is established I wait for event "BLE_GAP_EVT_CONNECTED" in "on_ble_evt" handler. After that data is transferred using "ble_nus_string_send". 

When I connect to the device using NRF Toolbox app (in UART mode) on Android - All data is transferred correctly and can be seen in the application's Log.
When I connect to the device using the same app but this time on iOS - Data strarts to transfer correctly but hangs before all data is received by iPhone.

  • Sorry, I forgot that you used SDK v 11. No the error will not be printed in the log. My bad.

    However, if you turn off optimization, and define DEBUG in the preprocessor defines, you will see that APP_ERROR_CHECK() will follow this call:

    APP_ERROR_CHECK() -> APP_ERROR_HANDLER() -> app_error_handler(), which contains the error_code, line number and a pointer to the file name that the error occured.

    If this is not hit, then something else is going on, but I don't know exactly what. If it "stops"/"hangs", maybe

    while(!bleTxComplete){};

    never passes, possibly because the message is never sent, because the ble_nus_string_send() returned BLE_ERROR_NO_TX_PACKETS. That may very well be.

    You see, ble_nus_string_send(), which calls the softdevice call, sd_ble_gatts_hvx() only queues the packet if it returns NRF_SUCCESS.

    In the case where some packet has not yet been delivered, and you fill up the queue, sd_ble_gatts_hvx() will not return NRF_SUCCESS because there isn't room in the softdevice queue for this new packet, or some other reason. The return value should give you some hints. 

    The issue with the implementation is that if this doesn't return NRF_SUCCESS, then you will not get the TX_COMPLETE event, because the packet was never queued. In this case, you are waiting for the bleTxComplete to be true, which it never will, and you are stuck.

    Try to call APP_ERROR_CHECK(err_code) before waiting for bleTxComplete. Then you will know if a packet isn't queued. 

  • I have been tweaking the code and I may have found a solution. Sending data like the way shown below seems to work for both Android and iOS. 

    do
    {
    	err_code = ble_nus_string_send(&m_nus, (uint8_t *)integer2String(TIMESTAMP_MARKER), sizeof(stringData));
    }
    while(err_code != NRF_SUCCESS);
    while(!bleTxComplete);
    bleTxComplete = false;

  • Yes. That confirms my suspicion. You probably got the BLE_ERROR_NO_TX_PACKETS.

    The implementation you have above will work just fine, but it is denying the nRF to go to sleep in between the packets. Now it has to wait until it is able to successfully queue the packet, and that it has been ACKed in the TX_COMPLETE event. If current consumption is a concern for your product, I suggest you use flags and counters instead of waiting functions (while() ), so that you can return to the main() context in between the packets. You can use the TX_COMPLETE event to resume the queuing of packets.

    Best regards,

    Edvin

  • Thanks for the advice, I'll have that in mind and will implement sleep further down the development flow. First I want to make sure everything works correctly. 

Related