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.

Parents
  • Hello,

    Any particular reason for why you use such an old SDK? I suggest, if you are not far in your development to move to SDK12.3.0, which is the latest SDK for nRF51 - S130.

    What do you mean by "hangs before all data is received by iPhone"?

    I suspect that you are caught in an APP_ERROR_CHECK(). Probably in the part:

    err_code = ble_nus_string_send(...)
    if (err_code != NRF_ERROR_INVALID_STATE)
    {
        APP_ERROR_CHECK(err_code);
    }

    Maybe you get err_code == NRF_ERROR_RESOURCES (= 19 or 0x13)?

    This means that the softdevice queue is full, and you need to wait for a BLE_EVT_TX_COMPLETE event before you can send more data. The reason this happens on the iPhone and not the Android may be because they are giving you different connection parameters, and that the connection parameters on the Android is allowing a higher throughput.

    You can add the BLE_EVT_TX_COMPLETE event in the on_ble_evt() function in main.c, and use this event to set a flag indicating that you can send more data when this event occurs.

    Best regards,

    Edvin

  • I've actually already implemented waiting for BLE_EVT_TX_COMPLETE event to be generated every 1 word (4 bytes I send). As for the connections parameters, aren't they the same for both Android and iOS as my device is acting as Central and the phone is Peripheral. 

  • Yes, bleTxComplete is set true in "on_ble_evt()" handler. I am sure that the breakpoint in "main()" is going to be hit in case of reset, because I have used it a couple of times to detect such a behavior. 

    Now I'm going to place a breakpoint earlier - in the "APP_ERROR_CHECK()" and see what will happen. I know how to set DEBUG in preprocessor, but what do you mean by RTT log, is that the Debugger Log.

  • 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. 

Reply Children
No Data
Related