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

Understanding BLE_EVT_TX_COMPLETE events

I am sending a data packet by notification that spans many MTU sizes. So I do a loop over the sd_ble_gatts_hvx(m_connection_handle, &hvx_params) method until I get a  BLE_ERROR_NO_TX_PACKETS error. Now I have to wait for the BLE_EVT_TX_COMPLETE event before repeating the notification that failed and continuing on. I may run out of TX packets again, so the process repeats. 

Now I am trying to understand when that BLE_EVT_TX_COMPLETE is called and how often it is called and when can I perform the next send which is an indication on another characteristic. I am running this on the nRF51 DK so I have a putty window catching print statements (which often overflows in this test). These BLE_EVT_TX_COMPLETE events keep coming until all the packets I have notified have been accounted for.

The question is when can I start doing the indication? I finish doing all the notifications before all the BLE_EVT_TX_COMPLETE events have been received; a good tenth of a second before all BLE_EVT_TX_COMPLETE events have been received. Can I start sending indications BEFORE all the BLE_EVT_TX_COMPLETE events have been received or will I just get an NRF_ERROR_BUSY error?

In other words, if I send a notification and receive no error, is that packet out the door? Additionally, if that happens to be the last notification I need to send for that data packet, can I immediately start sending an indication?

Please explain the relation between sending a notification, having the notification successfully on its way to the peer, and the BLE_EVT_TX_COMPLETE events.

Note that I am using only SoftDevice and I am pulling events from SoftDevice in the main for-loop when the sd_app_evt_wait() is triggered. When it is triggered I check if notifications/indications need to be sent and if they do, they are done.

Parents
  • Hi,

    The BLE_EVT_TX_COMPLETE is typically raised every time a packet has been transmitted. However, sometimes when more packets are sent in the same connection event you may not get this event for each. Therefor you must also check the count field in the ble_evt_tx_complete_t struct you get with the event.

    The question is when can I start doing the indication? I finish doing all the notifications before all the BLE_EVT_TX_COMPLETE events have been received; a good tenth of a second before all BLE_EVT_TX_COMPLETE events have been received. Can I start sending indications BEFORE all the BLE_EVT_TX_COMPLETE events have been received or will I just get an NRF_ERROR_BUSY error?

    You need to wait for the BLE_EVT_TX_COMPLETE event to be sure that a buffer has been freed. There is no way to know before this. You could of course try and just live with another BLE_ERROR_NO_TX_PACKETS error if spending a bit of extra CPU time is not problem.

    In other words, if I send a notification and receive no error, is that packet out the door?

    No. The packet will remain buffered by the SoftDevice until it is acknowledged by the peer (or the link is disconnected due to supervision timeout).

    Additionally, if that happens to be the last notification I need to send for that data packet, can I immediately start sending an indication?

    No. The same buffer is used for both notifications and indications.

    Please explain the relation between sending a notification, having the notification successfully on its way to the peer, and the BLE_EVT_TX_COMPLETE events.

    When you send a notification, you really just queue it. Then it is sent and potentially retransmitted several times before it is acknowledged by the peer. Once acknowledged the buffer is freed and you get a BLE_EVT_TX_COMPLETE event. If it was a indication instead of a notification it would have to be acknowledged by the application layer as well, which takes more time (see this old post).

Reply
  • Hi,

    The BLE_EVT_TX_COMPLETE is typically raised every time a packet has been transmitted. However, sometimes when more packets are sent in the same connection event you may not get this event for each. Therefor you must also check the count field in the ble_evt_tx_complete_t struct you get with the event.

    The question is when can I start doing the indication? I finish doing all the notifications before all the BLE_EVT_TX_COMPLETE events have been received; a good tenth of a second before all BLE_EVT_TX_COMPLETE events have been received. Can I start sending indications BEFORE all the BLE_EVT_TX_COMPLETE events have been received or will I just get an NRF_ERROR_BUSY error?

    You need to wait for the BLE_EVT_TX_COMPLETE event to be sure that a buffer has been freed. There is no way to know before this. You could of course try and just live with another BLE_ERROR_NO_TX_PACKETS error if spending a bit of extra CPU time is not problem.

    In other words, if I send a notification and receive no error, is that packet out the door?

    No. The packet will remain buffered by the SoftDevice until it is acknowledged by the peer (or the link is disconnected due to supervision timeout).

    Additionally, if that happens to be the last notification I need to send for that data packet, can I immediately start sending an indication?

    No. The same buffer is used for both notifications and indications.

    Please explain the relation between sending a notification, having the notification successfully on its way to the peer, and the BLE_EVT_TX_COMPLETE events.

    When you send a notification, you really just queue it. Then it is sent and potentially retransmitted several times before it is acknowledged by the peer. Once acknowledged the buffer is freed and you get a BLE_EVT_TX_COMPLETE event. If it was a indication instead of a notification it would have to be acknowledged by the application layer as well, which takes more time (see this old post).

Children
  • I did not realize that notifications were acknowledged at any layer, but I guess they have to be in some sense just to keep the 'heartbeat' alive.

    You say above that I will get another BLE_ERROR_NO_TX_PACKETS if I send an indication before all my notifications have been evented (I realize that one BLE_EVT_TX_COMPLETE event may encompass more than one notification and I take that into account).

    However, I am confused about getting a BLE_ERROR_NO_TX_PACKETS if I send an indication before all my notifications have been evented. My understanding from the documentation is that I can only get a BLE_ERROR_NO_TX_PACKETS from notifications. Indications will generate an NRF_ERROR_BUSY error only. Is that not true?

    Another thing I want to understand - if I get more than one notification evented in the BLE_EVT_TX_COMPLETE event does that means more than one notification went out in a single connection interval? I note that 90% of my notifications generate a BLE_EVT_TX_COMPLETE with only a single notification. That's a little disappointing. I'm pushing only 20 bytes per notification in the characteristic value.

    Yet another thing: If I send notifications with 1 byte per notification versus 10 bytes per notification as fast as I can, in which case will I exhaust the buffers the fastest? IN which case will  I have sent more bytes by the time the buffers are exhausted? Which is the fastest way to deliver data to the peer?

  • Hi,

    brianreinhold said:
    I did not realize that notifications were acknowledged at any layer, but I guess they have to be in some sense just to keep the 'heartbeat' alive.

    Not just that. BLE provide data integrity so all data packets are acknowledged (or retransmitted if necessary) on the link layer.

    brianreinhold said:
    You say above that I will get another BLE_ERROR_NO_TX_PACKETS if I send an indication before all my notifications have been evented (I realize that one BLE_EVT_TX_COMPLETE event may encompass more than one notification and I take that into account).

    I didn't mean to say that. But if the buffer is full, then one packet has to be successfully transmitted (meaning also acknowledged by the peer) before it can be freed so that another packet can be queued. The Tx buffer does not need to be emptied completely.

    brianreinhold said:
    However, I am confused about getting a BLE_ERROR_NO_TX_PACKETS if I send an indication before all my notifications have been evented. My understanding from the documentation is that I can only get a BLE_ERROR_NO_TX_PACKETS from notifications. Indications will generate an NRF_ERROR_BUSY error only. Is that not true?

    No, you are right. I should have refreshed my memory there. That makes sense, as an indications needs to be acked by the peer's app layer before another can be queued.

    brianreinhold said:
    Another thing I want to understand - if I get more than one notification evented in the BLE_EVT_TX_COMPLETE event does that means more than one notification went out in a single connection interval?

    Yes. But it is not necessarily the other way around. You could get more BLE_EVT_TX_COMPLETE events for the same connection event.

    brianreinhold said:
    Yet another thing: If I send notifications with 1 byte per notification versus 10 bytes per notification as fast as I can, in which case will I exhaust the buffers the fastest?

    The buffer has a fixed number of elements (for old SoftDevices that is 1, 3 or 6 depending on bandwidth configuration), and those are scaled for the maximum size packets. But you cannot fit more than the specified number of packets, so 6 packets is max with high bandwidth configuration, even if the payload is only 1 byte.

Related