This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

[S132] BLE_EVT_TX_COMPLETE not being triggered

Hi, I'm not completely sure if this is a bug but I've been struggling with this for two days so I don't think this is related to my own application code.

The situation is the following, I'm using a custom service with two characteristics which are updated at a frequency of 20hz. To avoid exhausting the TX buffers I created a semaphore which tracks the number of free tx buffers which is initialized with sd_ble_tx_buffer_count_get(). Inside my service code, every time I call sd_ble_gatts_hvx, if it returns NRF_SUCCESS, I decrement the free_tx_buffers:

  [...]
  err_code = sd_ble_gatts_hvx(p_sts->conn_handle, &hvx_params);
  if(err_code == NRF_SUCCESS)
  {
    (*p_sts->free_tx_buffers_p)--;        

    if(hvx_length != pkt_length)
    {
      err_code = NRF_ERROR_DATA_SIZE;
    }
  }
  [...]

Then on my application BLE event handler I look for a BLE_EVT_TX_COMPLETE event and then I increment the semaphore:

switch(p_ble_evt->header.evt_id)
{
[...]
case BLE_EVT_TX_COMPLETE:
  free_tx_buffers++;
  break;
[...]
}

This works well as long as I only enable notifications for one of the characteristics, I can see how the variable gets incremented and decremented. But If I enable notifications on both characteristics, sometimes, not always, the BLE_EVT_TX_COMPLETE is only being triggered once so I end "losing" one available TX buffer. After some time I "lose" all the tx buffers which ends on a deadlock.

I noticed that this is not happening if I add a small delay, something around 10ms between the sd_ble_gatts_hvx calls.

Thanks

  • I finally managed to solve it by myself. It was clearly my fault for not reading thoroughly the documentation.

    sd_ble_gatts_hvx() doesn't throw a BLE_EVT_TX_COMPLETE on each call, but per interval, so instead of incrementing the semaphore the solution is to add the count of completed TXs contained on the event itself.

    So instead of

      case BLE_EVT_TX_COMPLETE:
        free_tx_buffers++;
        break;
    

    is

    case BLE_EVT_TX_COMPLETE:
        free_tx_buffers += p_ble_evt->evt.common_evt.params.tx_complete.count;
        break;
    

    I need a vacation...

Related