This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LP-EM-CC2340R5: Callback DSS_writeAttrCB not receiving data when WRITE WITHOUT RESPONSE is sent very fast

Part Number: LP-EM-CC2340R5
Other Parts Discussed in Thread: CC2340R5

Dear TI team,

Our code is based in the data_stream example, when the smartphone APP sends data slowly using the write without response there is no problem and the callback from DSS_writeAttrCB is receiving the data correctly. When app is sending very quickly, then DSS_writeAttrCB  callback is receiving the frist packets and then is not receiving anymore data this is happening when the characteristic is using encryption, if we don't use the encryption neither bonding then the data is received properly. It seems that internally the Bluetooth stack is out of resources. Do you have an idea which parameter is affecting that behaviour?

I await your comments.

  • Hi,

    Thank you for reaching out. Can you specify which SDK version you are using? Do you have access to a BLE sniffer? If so, then could you take a sniffer log of the behavior? This will help us determine if the packets are actually being sent or not. Also, can you share how fast you are sending the data and what connection parameters are being used? Also how much data?

    Best Regards,

    Jan

  • Hi,

    We are using the SDK version sdk_7_40_00_64  and I don't have a BLE sniffer.

    I have modified the data_stream example source code adding the essencial parts that are causing the issue, I have also developed a testing android app and you will be able to replicate the issue.

    I have shared those resources to our FAE Sai Sandesh and he will resend them to you ASAP.

    Best regards

  • Hi,

    Understood. I will keep an eye out on the email from Sai. In the meantime, can you use ROV while reproducing the issue and check on the stack size of the ble task?

    Best Regards,

    Jan

  • Hi,

    In the following link you can check the ROV while reproducing the issue. https://youtu.be/VGf-jsIAUH8

    I don't see any issue or at least I am not able to see it.

    Best regards

  • Hi,

    Thank you. At a glance it looks okay to me. I am working with Sai to get the project over to my side ASAP. Sai mention that the issue happens when your custom app performs a "burst" can you quantify what a burst is? How often are you sending data and how much data are you sending each time?

    Best Regards,

    Jan

  • Hi,

    The CC2340R5 is receiving around 75 writes without response per second, each write is 10bytes. At same time we are sending Indications to the smartphone, when we receive the indication callback ATT_HANDLE_VALUE_CFM, then we send again another indication, each indication is 1 byte of data. The connection parameters are the default ones of data stream example.

    I have uploaded the project files in TI Drive link 

    Regards

  • Hi,

    I apologize for the delay. I was out of office over the past few days. Could you quickly clarify what happens if you perform the following steps?

    1. Start transmission

    2. Wait until the callback stops working

    3. Stop transmission

    4. Restart transmission

    Does the callback work again? Could you also clarify the connection parameters (specifically what the connection interval is?) 75 writes per second works out to a write every 13.33ms, so I would like to see if that is able to fit nicely in the connection parameters you have configured.

    Best Regards,

    Jan

  • Hi,

    When the callback stops working I cannot stop the transmission because the chipset disconnects the connection and it is not responding until I reset it. The connection parameters are the following ones:

    connInterval: 6

    MTU: 23

    connTimeout: 500

    connLatency: 0

    As you have the source code you can check it.

    In my case I am not interested to check if the bytes fits in the correct connection interval to get the max throughput, it is not our main goal. What I require is a stable firmware in front incorrect behaviour from app side.

    With regards

  • Hi,

    Got it. I would like to see what the state of the program execution is at the time the transmission stops. Can you reproduce the behavior with a debugger connected, pause execution and then share the call stack? Also could you try increasing the connection interval to 10ms or so? I'm curious to see if the behavior happens there as well.

    Best Regards,

    Jan

  • Hi,

    It is not possible to control the connection interval in Android with exact values, there are only three modes

    BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER
    BluetoothGatt.CONNECTION_PRIORITY_BALANCED
    BluetoothGatt.CONNECTION_PRIORITY_HIGH

    Using CONNECTION_PRIORITY_LOW_POWER value and rejecting the BLEAPPUTIL_LINK_PARAM_UPDATE_REQ_EVENT, with BLEAppUtil_paramUpdateRsp(pReq,FALSE), then I can get a connection interval of 36. With that value I confirm you that the problem is still persisting. 

    The following video shows you the call stack content and the issue with connection interval of 36.

    Multimedia4 (youtube.com)

    The only observation that I can say you is that removing the uart MenuModule_printf the issue takes a little bit more time to happen, around 5seconds more.

    With regards

  • Hi,

    Thank you for confirming that the issue is present in different connection intervals. We have recently released the 8.10 SDK. Can you re-test on the new SDK? There were several improvements and fixes made to the BLE5 Stack that may have an impact on the behavior you are seeing. Some of these may be seen here: https://software-dl.ti.com/simplelink/esd/simplelink_lowpower_f3_sdk/8.10.00.55/exports/docs/ble5stack/release_notes_ble5stack_3_03_01_00.html

    Best Regards,

    Jan

  • Hi,

    I have tested the SDK 8.10.00.55 and the problem still persists. As you have the source code you can also check the issue.

    Just for your information, If I don't send any indication and I just receive WRITE WITHOUT RESPONSE everything is working correctly.

    But If I send indications while I receive WRITE WITHOUT RESPONSE messages, then problem appears again.

    Source Code for receptions WRITE WITHOUT RESPONSE

    static bStatus_t DSS_writeAttrCB( uint16 connHandle,
                                            gattAttribute_t *pAttr,
                                            uint8 *pValue, uint16 len,
                                            uint16 offset, uint8 method )
    .
    .
    .
      /******************************************************/
      /*********** Data In Characteristic  ******************/
      /******************************************************/
      else if ( ! memcmp( pAttr->type.uuid, dss_dataRx_UUID, pAttr->type.len ) )
      {
        // Only notify profile if there is any data in the payload
        if ( len > 0  && dss_profileCBs && dss_profileCBs->pfnIncomingDataCB)
        {
          DSS_dataIn_t *dataIn;

          if ( len > DSS_MAX_DATA_IN_LEN )
          {
            len = 0;
          }

          // This allocation will be free by bleapp_util
          dataIn = (DSS_dataIn_t *)ICall_malloc( sizeof( DSS_dataIn_t ) + len);
          if ( dataIn == NULL )
          {
            // Return error status
            return ( bleMemAllocError );
          }

          // If allocation was successful,
          // Copy the data and send it to the profile
          if ( len > 0 )
          {
            memcpy( dataIn->pValue, pValue, len );
          }
          dataIn->connHandle = connHandle;
          dataIn->len = len;

          // Callback function to notify profile of change on the client characteristic configuration
          status = BLEAppUtil_invokeFunction( dss_profileCBs->pfnIncomingDataCB, (char *)dataIn );
        }
        else
        {
          status = SUCCESS;
        }
      }

    Where  invokeFunction callback is 

    static void DS_incomingDataCB( uint16 connHandle, char *pValue, uint16 len )
    {
        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE4,
                          0,
                          "Hello World TI");
    }
    From Indication side, this is the function for sending indications:
    A first indication is sent and when we receive the callback that it is sent, correclty then we send another indication
     
    Here you have the code
    static void GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
      gattMsgEvent_t *gattMsg = ( gattMsgEvent_t * )pMsgData;
      switch ( gattMsg->method )
      {
        case ATT_FLOW_CTRL_VIOLATED_EVENT:
          {
              MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT flow control is violated");
          }
          break;

        case ATT_MTU_UPDATED_EVENT:
          {
              MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "GATT status: ATT MTU update to %d",
                                gattMsg->msg.mtuEvt.MTU);
          }
          break;

        case ATT_HANDLE_VALUE_CFM:
            //MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "Indication Callback ok");
            BLEAppUtil_invokeFunctionNoData(vfn_DSS_WriteInitialTxCredits);
        break;


        default:
          break;
      }
    }
    void vfn_DSS_WriteInitialTxCredits(char *ptr_value)
    {
      terminalio_credits_tx = 0x20U; //Just uint8_t
      vfn_setIndicationStatus(R_TRUE); // This is just a flag
      DSS_sendIndication(&terminalio_credits_tx, 1U);
      //MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE4,
      //                    0,
      //                    "Indication Sent");
    }
    /*********************************************************************
     * @fn      DSS_sendIndication
     *
     * @brief   Transmits data over BLE notifications.
     *
     * @param   pValue - pointer to data to be written
     * @param   len - length of data to be written
     *
     * @return  SUCCESS, or stack call status
     */
    static bStatus_t DSS_sendIndication(uint8 *pValue, uint16 len)
    {
      bStatus_t status = SUCCESS;
      gattAttribute_t *pAttr = NULL;
      attHandleValueNoti_t indication = {0};
      linkDBInfo_t connInfo = {0};
      uint16 offset = 0;
      uint8 i = 0;

      // Verify input parameters
      if ( pValue == NULL )
      {
        return ( INVALIDPARAMETER );
      }

      // Find the characteristic value attribute
      pAttr = GATTServApp_FindAttr(dss_attrTbl, GATT_NUM_ATTRS(dss_attrTbl), &dss_creditsTx_val);
      if ( pAttr != NULL && pValue != NULL)
      {

        // Check the ccc value for each BLE connection
        gattCharCfg_t *pItem = &(dss_creditsTx_config[0]);
        // If the connection has register for notifications
        if ( ( pItem->connHandle != LINKDB_CONNHANDLE_INVALID ) &&
             ( pItem->value == GATT_CLIENT_CFG_INDICATE) )
        {
          // Find out what the maximum MTU size is for each connection
          status = linkDB_GetInfo(pItem->connHandle, &connInfo);
          offset = 0;
          while ( status != bleTimeout && status != bleNotConnected &&  len > offset )
          {
            // Determine allocation size
            uint16_t allocLen = (len - offset);
            if ( allocLen > ( connInfo.MTU - DSS_NOTI_HDR_SIZE ) )
            {
              // If len > MTU split data to chunks of MTU size
              allocLen = connInfo.MTU - DSS_NOTI_HDR_SIZE;
            }
            /* Try to allocate memory for the notification or indication payload using GATT_bm_alloc(). */
            /* According to the documentation: */
            /* Warning The payload must be dynamically allocated using GATT_bm_alloc */
            indication.len = allocLen;
            indication.pValue = (uint8 *)GATT_bm_alloc( pItem->connHandle, ATT_HANDLE_VALUE_IND, allocLen, 0 );
            if ( indication.pValue != NULL )
            {
              // If allocation was successful, copy out data and send it
              memcpy(indication.pValue, pValue + offset, indication.len);
              indication.handle = pAttr->handle;
              // Send the data over BLE notifications
              //status = GATT_Notification( pItem->connHandle, &noti, FALSE );
              status = GATT_Indication( pItem->connHandle, //connection to use
                                        &indication,       //pointer to indication to be sent
                                        FALSE,             //authenticated  - whether an authenticated link is required 0x01: LE Legacy authenticated 0x02: Secure Connections authenticated
                                        BLEAppUtil_getSelfEntity());           //taskId    - task to be notified of response
              /* NOTE: If the return value of the notification or indication is SUCCESS (0x00), the stack freed the
                 memory*/
              /* If unable to send the data, free allocated buffers and return */
              /* According to the documentation: */
              /* Use GATT_bm_free() to free the memory if the return value is something other than SUCCESS (for
                 example, blePending)*/
              if ( status != SUCCESS )
              {
                GATT_bm_free( (gattMsg_t *)&indication, ATT_HANDLE_VALUE_IND );
                // Failed to send notification, print error message
              }
              else
              {
                // Increment data offset
                offset += allocLen;
              }
            }
            else
            {
              status = bleNoResources;
            }
          } // End of while
        }
      } // End of if

      // Return status value
      return ( status );
    }
    Let me know If you see any issue, but Indication code is taken from services/health_thermometer/health_thermometer_server.c (HTS_sendInd function) as  TI suggested here CC2340R5: GATT_Indication example - Bluetooth forum - Bluetooth®︎ - TI E2E support forums
    Regards
  • Hi,

    Thank you for verifying this on the new SDK! I have tested using your custom application and I believe I am seeing the same behavior you are.

    With  the app, I am able to see the custom project advertising:

    I can then connect

    Afterwards, I can send a single packet successfully it seems

    When sending a burst,  it seems to work for a few seconds, but then hang.

    Pausing execution shows the device here:

    To confirm, is this what you are seeing on your side? I want to confirm we are looking at the same behavior as we continue the debug.

    Best Regards,

    Jan

  • Hi,

    I confirm you that we are aligned with the same issue.

    Regards

  • Hi,

    I have done a bit more debugging and found that the timing of the issue is a bit variable. I have added some print statements that track how many indications have been sent and how many writes have been sent.

    During my testing, I found that the write amount varies. My guess right now is that the BLE5-Stack is getting overwhelmed due to the number of indications and writes. I would like to take some sniffer logs early next week to better understand what is going on over the air.

    In the meantime, I have some suggestions to try to see if we can work around this.

    1. Can you try reducing the speed at which the writes and the indications are sent? I would half the speed until the crash does not occur.

    2. Can you try using notifications instead of indications?

    3. Can you try stopping the indication stream during a GATT write burst? This way at any given moment either indications are being sent or gatt writes, but not both at the same time.

    Best Regards,

    Jan

  • Hi,

    Sorry for my late reply.

    1. Can you try reducing the speed at which the writes and the indications are sent? I would half the speed until the crash does not occur.

    I have tried to send writes with handler.postDelayed in Android which allows you to send writes with specific period, the resolution of that is about +-10ms. It fails with 25ms between writes, with upper values is working fine. The indication period has not modified, so it is still sending indications and when it receive the callback it sends again the indication.

    2. Can you try using notifications instead of indications?

    In burst mode, If I send a notification using BLEAppUtil_invokeFunction when I just receive the WRITE WITHOUT RESPONSE callback then it fails too.

    3. Can you try stopping the indication stream during a GATT write burst? This way at any given moment either indications are being sent or gatt writes, but not both at the same time.

    I have modified the android test app and data stream example with the following way: When CC2340R5 receives a write without response then it sends an indication to the app and when app receives an indication, app sends a write without response to the CC2340R5. With that approach everything is working correctly.

    In this case and from CC2340R5 point of view it is sending indications and receiving gatt writes very fast but not at same time.

    From your side do you have any news?

    Regards

  • Hi,

    Understood. Thank you for the update. An small update to the SDK is planned to be released in the coming days. There was a fix added that is related to repeated GATT writes that I would like to see if it is related to your issue. Once it is released, can you try the new SDK and verify if the issue still occurs?

    Best Regards,

    Jan

  • Hi,

    Understood, I will try it as soon as it is available. Do you know the planned day?"

    Regards

  • Hi,

    It is planned to be released early next week. Please keep an eye on the download page for the SDK. Once available, please try again and see if the issue still occurs. If it still occurs in the new SDK, then I would suggest retrying with the PDU size and amount set to 255.

    Best Regards,

    Jan

  • Hi,

    I have tried the SDK 8.10.01.02 with PDU size 255 and the problem still persists. Can you double check from your side? Any suggestion? How can I detect that the BLE5-Stack is getting overwhelmed? 

    Regards

  • Hi,

    Got it. Thank you for verifying this. I will attempt to reproduce this on my side on the latest SDK and attempt to get some sniffer logs to see if there something improper with the data stream being sent from the app.

    I will provide an update by Monday.

    Best Regards,

    Jan

  • Hi,

    My apologies for the delay here. It took some additional time to source the sniffer log. I have taken the following log with an Ellisys BLE sniffer:

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/538/BLE_5F00_Packet_5F00_Log.btt

    As you can see, there are an extremely large amount of indications and GATT writes occurring when the burst happens. I think we are trying to send too much data (in different ways) in too short of a time span. Can you try reducing the frequency at which the indications are sent or potentially, sending a message to the CC2340R5 before a burst begins to make it slow down the indications? I would like to see if we can find a compromise between how many indications and writes we can perform.

    Best Regards,

    Jan

  • Hi,

    The firmware that we are developing uses a common BLE GATT protocol already implemented in other chipsets already in production with no issues, for example with NRF52840, burst mode is working correctly.

    The idea of reducing frequency of GATT Writes from app side is not acceptable because it is not under my control and CC2340R5 must not crash under this situation. I am open to reduce the indications period because it is under my control, can you tell me a way to detect in an exact manner when the TI BLE stack is starting to be overwelmed? With this, I will send the indications when the BLE stack is less saturated and avoid the issue. I am thinking to put a timer between the writes and if the value is less than certain crash value wait for send the indication until this value is better. Can you tell me other ways to do some flow control in order to control the overwelmed situation?

    You should agree that above solution is a workaround and If it is a BLE5-Stack issue it should be fixed from your side.

    I think to arrange an small call to exchange ideas and solutions could be interesting. Can you manage it?

    Regards

  • Hi,

    Got it. Agreed that the stack should not be crashing in the way it is under this load. I will continue investigating this on our side to see what can be done beyond reducing the indication frequency. I would be happy to support a call. Please let your TI representative know and we will arrange something for sometime next week.

    In the meantime, can you look for &l2capNumDataPkts in the memory browser and record the number you see before you start transmitting packets, while you are transmitting packets and then after the behavior occurs?

    Best Regards,

    Jan