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.

CC2340R5: CC2340R5 Central receives only 21 bytes (18+3) while sniffer shows 26 bytes from BLE 5.0 peripheral

Part Number: CC2340R5

Hi Team,

My customer is facing a potential BLE stack issue on CC2340R5 running as Central. When connected to a BLE 5.0 peripheral (Realtek solution), the CC2340R5 consistently receives truncated ATT data for packets larger than 21 bytes, while the sniffer shows the peripheral actually transmits the full payload.

1) Environment

  • Central: TI CC2340R5 (Central role)
  • Peripheral: BLE 5.0 device (Realtek solution)
  • SDK / BLE Stack versions tested:
    • SimpleLink Low Power F3 SDK 9.11.00.18
    • SimpleLink Low Power F3 SDK 9.12.00.19

    Same issue reproduced on both versions.

 

2) Issue Description

After CC2340R5 connects to the BLE 5.0 peripheral, we send a Write Without Response command. The peripheral then sends back a data packet (e.g., via Notification/Indication or other ATT data path).

  • Expected: Receive 26 bytes total (including 3-byte ATT header)
  • Actual on CC2340R5: Receive only 21 bytes total (18 bytes payload + 3-byte header)
  • Sniffer capture: The peripheral indeed sends 26 bytes total (full data)

3) Additional Observation (Key Point)

We verified that whenever the peripheral sends a packet > 21 bytes, CC2340R5 always receives only 21 bytes (i.e., truncated).
However, when connecting to a BLE 4.0 peripheral (1M PHY), CC2340R5 can receive > 21 bytes correctly.

 

Please help check the possible reasons.
Thanks.
  • Hi,

    Thank you for reaching out! Can you confirm the MTU size you are setting on the CC2340R5 side?

    Best Regards,

    Jan

  • The MAX_PDU_SIZE is 251 in ti_ble_config.h and exchange PDU size is 247 in sniffer.

  • Hi Jan,

    Do you have any update or suggestion?

    We have concerns about the project schedule and the capability of this BLE IC.

    Thx.

  • Hi !

    Could you please share with me the sniffer logs that you are referencing, and the snippet of code that you are using in order to read your characteristic ?

    If you are using GATT_ReadCharValue, this function only returns up to (ATT_MTU - 1) octets in length. If the MTU exchange did not succeed for some reason, then the function will always read up to around 21 bytes, which is the default MTU value.

    Kind regards,
    Lea

  • Additionally, to check that the MTU exchange was successful, you can add BLEAPPUTIL_ATT_MTU_UPDATED_EVENT to your eventMask for your GATT event handler. If your project is based on basic_ble, this GATT handler should be in a variable called dataGATTHandler.

  • Hi lea,

    my project is from basic_ble sample code and i can received the ATT_MTU_UPDATED_EVENT  in app_data.c

  • Did you modify anything from the basic_ble code ?

  • Hi Lea,

    Our project requirements are added: Peripheral mode, Central mode, SPI interface to main IC mainly.
    Need your help to review our coding changes?
    - app_peripheral.c
    - app_data.c
    - Menu_doGattWriteCB.TXT --> GATT write in this API and callback in app_data.c (Related to this issue directly)

    /******************************************************************************
    
    @file  app_peripheral.c
    
    @brief This example file demonstrates how to activate the peripheral role with
    the help of BLEAppUtil APIs.
    
    Two structures are used for event handling, one for connection events and one
    for advertising events.
    In each, eventMask is used to specify the events that will be received
    and handled.
    In addition, fill the BLEAppUtil_AdvInit_t structure with variables generated
    by the Sysconfig.
    
    In the events handler functions, write what actions are done after each event.
    In this example, after a connection is made, activation is performed for
    re-advertising up to the maximum connections.
    
    In the Peripheral_start() function at the bottom of the file, registration,
    initialization and activation are done using the BLEAppUtil API functions,
    using the structures defined in the file.
    
    More details on the functions and structures can be seen next to the usage.
    
    Group: WCS, BTS
    Target Device: cc23xx
    
    ******************************************************************************
    
     Copyright (c) 2022-2025, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    ******************************************************************************
    
    
    *****************************************************************************/
    
    #if defined( HOST_CONFIG ) && ( HOST_CONFIG & ( PERIPHERAL_CFG ) )
    
    //*****************************************************************************
    //! Includes
    //*****************************************************************************
    #include "ti_ble_config.h"
    #include "ti/ble/app_util/framework/bleapputil_api.h"
    #include "ti/ble/app_util/menu/menu_module.h"
    #include <app_main.h>
    
    //*****************************************************************************
    //! Prototypes
    //*****************************************************************************
    void Peripheral_AdvEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData);
    void Peripheral_GAPConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData);
    hciStatus_t start_DTM();
    extern uint8_t gStopAdvisting;
    //*****************************************************************************
    //! Globals
    //*****************************************************************************
    
    BLEAppUtil_EventHandler_t peripheralConnHandler =
    {
        .handlerType    = BLEAPPUTIL_GAP_CONN_TYPE,
        .pEventHandler  = Peripheral_GAPConnEventHandler,
        .eventMask      = BLEAPPUTIL_LINK_ESTABLISHED_EVENT |
                          BLEAPPUTIL_LINK_PARAM_UPDATE_REQ_EVENT |
                          BLEAPPUTIL_LINK_TERMINATED_EVENT,
    };
    
    BLEAppUtil_EventHandler_t peripheralAdvHandler =
    {
        .handlerType    = BLEAPPUTIL_GAP_ADV_TYPE,
        .pEventHandler  = Peripheral_AdvEventHandler,
        .eventMask      = BLEAPPUTIL_ADV_START_AFTER_ENABLE |
                          BLEAPPUTIL_ADV_END_AFTER_DISABLE
    };
    
    //! Store handle needed for each advertise set
    uint8 peripheralAdvHandle_1;
    
    //! Advertise param, needed for each advertise set, Generate by Sysconfig
    const BLEAppUtil_AdvInit_t advSetInitParamsSet_1 =
    {
        /* Advertise data and length */
        .advDataLen        = sizeof(advData1),
        .advData           = advData1,
    
        /* Scan respond data and length */
        .scanRespDataLen   = sizeof(scanResData1),
        .scanRespData      = scanResData1,
    
        .advParam          = &advParams1
    };
    
    #ifdef BO17
    
    uint8 peripheralAdvHandle_2;
    
    const BLEAppUtil_AdvInit_t advSetInitParamsSet_2 =
    {
        /* Advertise data and length */
        .advDataLen        = sizeof(advData1),
        .advData           = advData1,
    
        /* Scan respond data and length */
        .scanRespDataLen   = sizeof(scanResData2),
        .scanRespData      = scanResData2,
    
        .advParam          = &advParams2
    };
    
    #endif
    const BLEAppUtil_AdvStart_t advSetStartParamsSet_1 =
    {
        /* Use the maximum possible value. This is the spec-defined maximum for */
        /* directed advertising and infinite advertising for all other types */
        .enableOptions         =  GAP_ADV_ENABLE_OPTIONS_USE_MAX,
        .durationOrMaxEvents   = 0
     //   .enableOptions         =  GAP_ADV_ENABLE_OPTIONS_USE_DURATION, //GAP_ADV_ENABLE_OPTIONS_USE_MAX,
     //   .durationOrMaxEvents   = 18000
    };
    
    //*****************************************************************************
    //! Functions
    //*****************************************************************************
    
    /*********************************************************************
     * @fn      Peripheral_AdvEventHandler
     *
     * @brief   The purpose of this function is to handle advertise events
     *          that rise from the GAP and were registered in
     *          @ref BLEAppUtil_registerEventHandler
     *
     * @param   event - message event.
     * @param   pMsgData - pointer to message data.
     *
     * @return  none
     */
    void Peripheral_AdvEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
        switch(event)
        {
            case BLEAPPUTIL_ADV_START_AFTER_ENABLE:
            {
                MenuModule_printf(APP_MENU_ADV_EVENT, 0, "Adv status: Started - handle: "
                                  MENU_MODULE_COLOR_YELLOW "%d" MENU_MODULE_COLOR_RESET,
                                  ((BLEAppUtil_AdvEventData_t *)pMsgData)->pBuf->advHandle);
                break;
            }
    
            case BLEAPPUTIL_ADV_END_AFTER_DISABLE:
            {
                MenuModule_printf(APP_MENU_ADV_EVENT, 0, "Adv status: Ended - handle: "
                                  MENU_MODULE_COLOR_YELLOW "%d" MENU_MODULE_COLOR_RESET,
                                  ((BLEAppUtil_AdvEventData_t *)pMsgData)->pBuf->advHandle);
                break;
            }
    
            default:
            {
                break;
            }
        }
    }
    
    /*********************************************************************
     * @fn      Peripheral_GAPConnEventHandler
     *
     * @brief   The purpose of this function is to handle connection related
     *          events that rise from the GAP and were registered in
     *          @ref BLEAppUtil_registerEventHandler
     *
     * @param   event - message event.
     * @param   pMsgData - pointer to message data.
     *
     * @return  none
     */
    void Peripheral_GAPConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
        switch(event)
        {
            case BLEAPPUTIL_LINK_ESTABLISHED_EVENT:
            {
                /* Check if we reach the maximum allowed number of connections */
                if(linkDB_NumActive() < linkDB_NumConns())
                {
                    /* Start advertising since there is room for more connections */
                    BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
    #ifdef BO17
                    BLEAppUtil_advStart(peripheralAdvHandle_2, &advSetStartParamsSet_2);
    #endif
                }
                else
                {
                    /* Stop advertising since there is no room for more connections */
                    BLEAppUtil_advStop(peripheralAdvHandle_1);
    #ifdef BO17
                    BLEAppUtil_advStop(peripheralAdvHandle_2);
    #endif
                }
                break;
            }
    
            case BLEAPPUTIL_LINK_TERMINATED_EVENT:
            {
                if  (gStopAdvisting != 0)
                  BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
    #ifdef BO17
                 BLEAppUtil_advStart(peripheralAdvHandle_2, &advSetStartParamsSet_2);
    #endif
                break;
            }
    
            default:
            {
                break;
            }
        }
    }
    
    /*********************************************************************
     * @fn      Peripheral_start
     *
     * @brief   This function is called after stack initialization,
     *          the purpose of this function is to initialize and
     *          register the specific events handlers of the peripheral
     *          application module
     *
     * @return  SUCCESS, errorInfo
     */
    bStatus_t Peripheral_start()
    {
        bStatus_t status = SUCCESS;
    
        status = BLEAppUtil_registerEventHandler(&peripheralConnHandler);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_registerEventHandler(&peripheralAdvHandler);
        if(status != SUCCESS)
        {
            return(status);
        }
    
        
    #if 0
      status = start_DTM();
        if(status != SUCCESS)
        {
            return(status);
        }
     #else 
        status = BLEAppUtil_initAdvSet(&peripheralAdvHandle_1, &advSetInitParamsSet_1);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    #endif
    
    #ifdef BO17
        status = BLEAppUtil_initAdvSet(&peripheralAdvHandle_2, &advSetInitParamsSet_2);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_advStart(peripheralAdvHandle_2, &advSetStartParamsSet_1);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    #endif
        // Return status value
        return(status);
    }
    
    hciStatus_t start_DTM()
    {
        //DTM
        hciStatus_t status;
        
        BLEAppUtil_advStop(peripheralAdvHandle_1);
        
      //Set the number of packets
      uint16_t txPktCnt = 1400;
      status = HCI_EXT_SetDtmTxPktCntCmd(txPktCnt);
      if (HCI_SUCCESS != status)
            status = 1;
      //Define the starting TX power
      int8 txPowerDbm = -8;
      uint8 fraction = 0;
      status = HCI_EXT_SetMaxDtmTxPowerDbmCmd(txPowerDbm, fraction);
      if (HCI_SUCCESS != status)
            status = 2;
      status = HCI_EXT_SetTxPowerDbmCmd(txPowerDbm, fraction);
    if (HCI_SUCCESS != status)
            status = 3;
      //Start DTM
      uint8 txChan = 11;
      uint8 payloadLen = 15;
      uint8 payloadType = HCI_DIRECT_TEST_PAYLOAD_0x0F;
      uint8 txPhy = HCI_PHY_1_MBPS;
      status = HCI_LE_EnhancedTxTestCmd(txChan,payloadLen, payloadType, txPhy);
      if (HCI_SUCCESS != status)
            status = 4;
        
     
    return status;
    }
    
    hciStatus_t end_DTM()
    {
     //DTM
        hciStatus_t status;
        status = HCI_LE_TestEndCmd();
    
    
        status = BLEAppUtil_initAdvSet(&peripheralAdvHandle_1, &advSetInitParamsSet_1);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
    }
    
    #endif // ( HOST_CONFIG & ( PERIPHERAL_CFG ) )
    
    /******************************************************************************
    
    @file  app_data.c
    
    @brief This file contains the application data functionality
    
    Group: WCS, BTS
    Target Device: cc23xx
    
    ******************************************************************************
    
     Copyright (c) 2022-2025, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    ******************************************************************************
    
    
    *****************************************************************************/
    
    //*****************************************************************************
    //! Includes
    //*****************************************************************************
    #include <string.h>
    #include "ti/ble/app_util/framework/bleapputil_api.h"
    #include "ti/ble/app_util/menu/menu_module.h"
    #include <app_main.h>
    #include "FreeRTOS.h"
    #include "timers.h"
    
    //*****************************************************************************
    //! Defines
    //*****************************************************************************
    extern uint8_t gStartCentralMode;
    void AddDebuggingflowState(uint8_t state);
    //*****************************************************************************
    //! Globals
    //*****************************************************************************
    //#define BLE_CENTRAL_CMD_TIMEOUT
    #ifdef BLE_CENTRAL_CMD_TIMEOUT
    uint8_t benablecentraltimer = false;
    uint8_t bcentraltimercreaterd = false;
    TimerHandle_t centraltimerhandle ;
    extern void myCentralRspTimeoutToRXCallback(TimerHandle_t xTimer);
    #endif
    
    #define BACKUP_CMD_OFFSET (1024)
    #define CENTRAL_CONNECT_INTERVAL 48
    static void GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData);
    #define DEBUG_RESPONSE_BUF_SIZE 24
    extern uint8_t DebugFFRespnoseBackup[DEBUG_RESPONSE_BUF_SIZE];
    // Events handlers struct, contains the handlers and event masks
    // of the application data module
    BLEAppUtil_EventHandler_t dataGATTHandler =
    {
        .handlerType    = BLEAPPUTIL_GATT_TYPE,
        .pEventHandler  = GATT_EventHandler,
        .eventMask      = BLEAPPUTIL_ATT_FLOW_CTRL_VIOLATED_EVENT |
                          BLEAPPUTIL_ATT_MTU_UPDATED_EVENT |
                          BLEAPPUTIL_ATT_FIND_BY_TYPE_VALUE_RSP | 
                          BLEAPPUTIL_ATT_READ_BY_TYPE_RSP |
                          BLEAPPUTIL_ATT_READ_BY_GRP_TYPE_RSP |
                          BLEAPPUTIL_ATT_READ_RSP |
                          BLEAPPUTIL_ATT_HANDLE_VALUE_NOTI |
                          BLEAPPUTIL_ATT_FIND_INFO_RSP
    };
    
    extern uint8_t InstaxDataInUUID[ATT_UUID_SIZE]; 
    extern uint8_t InstaxDataOutUUID[ATT_UUID_SIZE];
     uint16_t attManuFHandle =0;
     uint16_t attDataInHandle =0;
     uint16_t attDataOutHandle =0;
     #define SPI_MSG_LENGTH 2048
     extern unsigned char peripheralTxBuffer[SPI_MSG_LENGTH]; 
     extern unsigned char bleRxBuffer[SPI_MSG_LENGTH];
     extern uint16_t bleTxBufferlen;
     extern uint8_t NotifyTPResponse();
     uint8_t downloadcount =0;
    //*****************************************************************************
    //! Functions
    //*****************************************************************************
    /* Characteristics */
    #define DIS_MANUFACTURER_UUID     0x2A29
    #define DIS_MODEL_NUMBER_UUID     0x2A24
    #define DIS_FIRMWARE_UUID         0x2A26
    /*********************************************************************
     * @fn      GATT_EventHandler
     *
     * @brief   The purpose of this function is to handle GATT events
     *          that rise from the GATT and were registered in
     *          @ref BLEAppUtil_RegisterGAPEvent
     *
     * @param   event - message event.
     * @param   pMsgData - pointer to message data.
     *
     * @return  none
     */
    
    //extern uint16_t attManuFHandle;
    void Menu_ReadManuFactoryNameCB(char *pData)
    {
        bStatus_t status;
        uint16_t connHandle;
        attReadReq_t req;
    
        connHandle =  Connection_getConnhandle(0); // InstaxDataInUUID      
        req.handle = attManuFHandle;
        status = GATT_ReadCharValue(connHandle, &req,
                               BLEAppUtil_getSelfEntity());
    }
    
    extern void Menu_doGattWriteCB(char *pData);
    #define SHORTBLERESPONSESIZE 48
    //extern unsigned char shortbleresponsebuf[SHORTBLERESPONSESIZE];
    uint8_t tmp_readdevicename = 0;
    static void GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
      gattMsgEvent_t *gattMsg = ( gattMsgEvent_t * )pMsgData;
      switch ( gattMsg->method )
      {
        case ATT_FIND_BY_TYPE_VALUE_RSP:
        {
            uint16_t lastStart;
            uint16_t lastEnd;
            uint16_t display_index =0;
            attFindByTypeValueRsp_t att = (attFindByTypeValueRsp_t)gattMsg->msg.findByTypeValueRsp;
            
            /* We need to build the 16-bit handles that we received when we discovered the service. */
            for (uint8_t i = 0; i < att.numInfo; i++)
            {
                /* NOTE: We are in little endian, but the BUILD_UINT16 macro accounts for this */
    
                /* The first two bytes will be start handle */
                uint16_t attHandle = BUILD_UINT16(att.pHandlesInfo[i * 4], att.pHandlesInfo[i * 4 + 1]);
                /* The second two bytes will be the end handle */
                uint16_t endHandle = BUILD_UINT16(att.pHandlesInfo[i * 4 + 2], att.pHandlesInfo[i * 4 + 3]);
                
                lastStart = attHandle;
                lastEnd = endHandle;
    
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "start: %x", attHandle);
                display_index++;
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "end: %x", endHandle);
                display_index++;
            }
    
            /* This delay can be replaced with a timer, or applicaton event that then calls GATT_DiscAllChars.
             * Without a delay, timer, or separate application event, this call will fail since the stack is busy
             * processing messages during this time. For the sake of the example, a delay was used, but
             * it does not have to be an explicit delay.
             */
    
           // ClockP_sleep(1);
            uint8_t retry = 0;
            while(retry < 10)
            {
              ClockP_usleep(200*1000); //100 ms
              bStatus_t bstatus = GATT_DiscAllChars(gattMsg->connHandle,
                                                    lastStart,
                                                    lastEnd,
                                                    BLEAppUtil_getSelfEntity());
              if (bstatus != SUCCESS)
              {
                  MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"FAILED!!!");
                  display_index++;
                  retry++;
              }
              else 
                  retry = 10;          
            }
      
        }
        break;
        case ATT_READ_BY_GRP_TYPE_RSP:
        {     
          uint16_t display_index =0;
          uint16_t lastStart;
          uint16_t lastEnd;
          attReadByGrpTypeRsp_t att = (attReadByGrpTypeRsp_t)gattMsg->msg.readByGrpTypeRsp;     
          for (uint8_t i = 0; i < att.numGrps; i++)
          {
            
          }
        }
        break;
        case ATT_READ_BY_TYPE_RSP:
        {
            uint16_t display_index =0;
            bStatus_t bstatus;
            uint16_t startHandle =0;
            uint16_t endHandle1 = 0;
    
            attReadByTypeRsp_t att = (attReadByTypeRsp_t)gattMsg->msg.readByTypeRsp;
    
            if (att.numPairs == 0)
                break;
    
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "ATT_READ_BY_TYPE_RSP");
            display_index++;
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0, "Length: %d : Number of Pairs: %d", att.len, att.numPairs);
            display_index++;
            
      
    
    
            for (uint8_t i = 0; i < att.numPairs; i++)
            {
                /* This is the Attribute Handle */
                uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
    
                /* This is the index to the beginning of the value data AFTER the attribute handle */
                uint8_t index = i * att.len + 2;
    
                /* The characteristic value data */
                uint8_t char_properties = att.pDataList[index];     // Bit field of characteristic properties
    
                uint16_t value_handle = BUILD_UINT16(att.pDataList[index + 1], att.pDataList[index + 2]);
    
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,
                                  "    ATT Handle: %x : Value Handle %x : Properties : %x",
                                  attHandle, value_handle, char_properties);
                display_index++;
                
                if (tmp_readdevicename == 1) //backup the central name
                {
                    tmp_readdevicename = att.len;
                    if (tmp_readdevicename > DEBUG_RESPONSE_BUF_SIZE-5) tmp_readdevicename = DEBUG_RESPONSE_BUF_SIZE -5;
                    //offset 4 byte after pair code
                    memcpy(DebugFFRespnoseBackup+5 , (void*)&(att.pDataList[index]) , tmp_readdevicename);
                    //bleTxBufferlen =  att.len;
                }
                 uint8_t data2 = att.pDataList[index + 1]; // Second Byte of Characteristic Value Handle
                uint8_t data3 = att.pDataList[index + 2]; // First Byte of Characteristic Value Handle
                if (att.len - 5 == 2)
                {
                   attReadReq_t req;
                   req.handle = attHandle;
                   uint16_t char_16bit_uuid = BUILD_UINT16(att.pDataList[index + 3], att.pDataList[index + 4]);
                   MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"    UUID: %x", char_16bit_uuid);
                   display_index++;
                   switch (char_16bit_uuid)
                    {
                      case DIS_MANUFACTURER_UUID:                  
                        //  attManuFHandle = attHandle;
                      //   bstatus = GATT_ReadCharValue(gattMsg->connHandle, &req,
                      //         BLEAppUtil_getSelfEntity());
                       // BLEAppUtil_invokeFunctionNoData(Menu_ReadManuFactoryNameCB);
                        break;
                      case DIS_MODEL_NUMBER_UUID:
                        
                        break;
                      case DIS_FIRMWARE_UUID:
                        attManuFHandle = attHandle;
                        break;
                       case GATT_CLIENT_CHAR_CFG_UUID:
                        attManuFHandle = attHandle;
                        break;
                    }              
                }
                else
                {
                    MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, 0,"    UUID: ");
                    uint8_t bfound = true;
                    for (uint8_t j = 0; j < 16; j++)
                    {
                      if (InstaxDataOutUUID[j] != att.pDataList[index + 3 + j])
                      {                     
                        bfound = false; break;
                      }                  
                    }
                    if (bfound)  
                    {                  
                        attDataOutHandle = BUILD_UINT16(data2, data3); 
      endHandle1 = BUILD_UINT16(data2, data3); 
                    }
                                    
                    bfound = true;
                    for (uint8_t j = 0; j < 16; j++)
                    {
                      if (InstaxDataInUUID[j] != att.pDataList[index + 3 + j])
                      {                     
                        bfound = false; break;
                      }                  
                    }
                    if (bfound) 
                    {
                        attDataInHandle = BUILD_UINT16(data2, data3);                      
                        startHandle = BUILD_UINT16(data2, data3);    
                    }
                    MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index, j + 10, "%x", att.pDataList[index + 3 + j]);                                
                    //NotifyBLEConnectStatus(3);  // debug
                    display_index++;
                }
            }
    
            // Call the GATT_DiscAllCharDesc()
            if (att.numPairs > 0)
            {
              uint8_t retry = 0;
              
              // ClockP_sleep(1);
              while (retry < 10)
              {
                ClockP_usleep(200 *1000); 
                bstatus = GATT_DiscAllCharDescs(gattMsg->connHandle, endHandle1+1 , endHandle1+10 , BLEAppUtil_getSelfEntity());
                if (bstatus != SUCCESS )
                {
                  bstatus = 0;
                  retry++;
                }
                else retry = 10;
              }  
            }
        }
        break;
        case ATT_FIND_INFO_RSP:
        {
          attFindInfoRsp_t rsp = (attFindInfoRsp_t)gattMsg->msg.findInfoRsp;
          MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"Event ATT_FIND_INFO_RSP Recieved");
    
            for (uint8_t i = 0; i < rsp.numInfo; i++)
            {
                /* This is the Attribute Handle */
                // uint16_t attHandle = BUILD_UINT16(att.pDataList[i * att.len + 0], att.pDataList[i * att.len + 1]);
                uint16_t attHandle = BUILD_UINT16(rsp.pInfo[0], rsp.pInfo[1]);
    
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"ATT Handle: %x", attHandle);
            
    
                /* This is the index to the beginning of the value data AFTER the attribute handle */
                uint8_t index = i * rsp.numInfo + 2;
    
                /* The characteristic value data */
                uint8_t data1 = rsp.pInfo[index];     // UUID LSB
                uint8_t data2 = rsp.pInfo[index + 1]; // UUID MSB
                
                uint16_t UUID = BUILD_UINT16(data1,  data2);
    
                
              if(UUID==0x2902){
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE + display_index++, 0,"CCCD Discovered");
    
                // Write to the CCCD
              //  ClockP_sleep(1);
             // ClockP_usleep(500000); //500 ms
                uint8_t retry = 0;
                while (retry < 4)
                {
                  ClockP_usleep(500*1000);                 
    
                  uint8_t val[2] = {0x01, 0x00};
                  attWriteReq_t writeReq;
    
                  writeReq.cmd = 0;
                  writeReq.handle = attHandle;
                  writeReq.len = 2;
                  writeReq.sig = 0;
          //        connn = gattMsg->connHandle;
                  
                  writeReq.pValue = GATT_bm_alloc(gattMsg->connHandle, ATT_WRITE_REQ, writeReq.len, NULL);
                  if (writeReq.pValue) {
                    writeReq.pValue[0] = 0x01;   // notifications = 0x0001 (little-endian)
                    writeReq.pValue[1] = 0x00;
                    
                    bStatus_t s = GATT_WriteCharValue(gattMsg->connHandle, &writeReq, BLEAppUtil_getSelfEntity());
                    if (s != SUCCESS) {
                      GATT_bm_free((gattMsg_t *)&writeReq, ATT_WRITE_REQ);
                      retry++;
                    }
                    else retry = 10;
                  }
                  else  retry++;
                }
    
                  
                    bStatus_t status;
                    gapUpdateLinkParamReq_t pParamUpdateReq =
                    {
                    .connectionHandle = gattMsg->connHandle,
                    .intervalMin = CENTRAL_CONNECT_INTERVAL,
                    .intervalMax = CENTRAL_CONNECT_INTERVAL,
                    .connLatency = 0,
                    .connTimeout = 400,
                    };                
                    downloadcount = 0;
                  
                    // Send a connection param update request
                    status = BLEAppUtil_paramUpdateReq(&pParamUpdateReq);
                  //  ClockP_usleep(100*1000);
                   // Menu_doGattWriteCB(NULL);
                   // 
                    if (gStartCentralMode)   
                    { 
                  //    BLEAppUtil_invokeFunction(Menu_doGattWriteCB , NULL);
                 //    ClockP_usleep(500*1000);
                      NotifyBLEConnectStatus(3);  
                    }
                   
                  // if (SUCCESS != status)
                  //    status =0; //debug
                  
                }                             
            }
        }
        break;
        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);
              //GAPBondMgr_Pair(Connection_getConnhandle(0));     
              if (!gStartCentralMode) 
              {
              uint8_t retry = 0;
              while (retry < 10) 
              {
                ClockP_usleep(100*1000);
                              attReadByTypeReq_t req;
              req.startHandle = 0x0001;
              req.endHandle = 0xFFFF;
              req.type.len = ATT_BT_UUID_SIZE;
              req.type.uuid[0] = LO_UINT16(DEVICE_NAME_UUID);
              req.type.uuid[1] = HI_UINT16(DEVICE_NAME_UUID);
              bStatus_t  status = GATT_ReadUsingCharUUID(Connection_getConnhandle(0), &req ,  BLEAppUtil_getSelfEntity());
              if (status != SUCCESS) 
              {
                      retry++;
              }  
                else  
                {    
                  retry = 10;
                  tmp_readdevicename =1;
                }
              } 
              }
              else {
    
    #ifdef BLE_CENTRAL_CMD_TIMEOUT                        
                              if (bcentraltimercreaterd == false)
                              {
                              centraltimerhandle =  xTimerCreate("MyTimer",
                               pdMS_TO_TICKS(1000),   // period in ms
                               pdTRUE,                // auto-reload
                               (void *)0,
                               myCentralRspTimeoutToRXCallback);
                               bcentraltimercreaterd = true;
                               if (centraltimerhandle != NULL) {
                                xTimerStart(centraltimerhandle, 0);    
                                }
                              }
      #endif
              }  
            //   GATT_UpdateMTU(Connection_getConnhandle(0) , 247);
          }
          break;
         case  ATT_READ_RSP:
         {
          //    uint16_t handle = gattMsg->msg.readRsp.handle;
              uint8_t *data   = gattMsg->msg.readRsp.pValue;
              uint8_t len     = gattMsg->msg.readRsp.len;
    
         }
         break;
    
         case ATT_HANDLE_VALUE_NOTI:
         {
            uint8_t len     = gattMsg->msg.readRsp.len;
            uint8_t *data   = gattMsg->msg.readRsp.pValue;
            uint8_t length = 16;
            
    #ifdef BLE_CENTRAL_CMD_TIMEOUT       
          //  xTimerStop(centraltimerhandle , 0);  // disable timeout
          benablecentraltimer = false;
     #endif
            AddDebuggingflowState(138);
          //  memcpy(&peripheralTxBuffer[4] ,  data , len);
           // if (data[4] ==0x10 && data[5] ==0x01)
            { 
               downloadcount++;           
            }        
            if (len < 16) 
               length = len;       
            if (tmp_readdevicename == 0)
                memcpy(DebugFFRespnoseBackup ,  data , length); 
    
            memcpy(&bleRxBuffer[BACKUP_CMD_OFFSET] ,  data , len);   
            bleTxBufferlen = len;
            NotifyTPResponse(); 
         }
         break;
    
        default:
          break;
      }
    }
    
    /*********************************************************************
     * @fn      Data_start
     *
     * @brief   This function is called after stack initialization,
     *          the purpose of this function is to initialize and
     *          register the specific events handlers of the data
     *          application module
     *
     * @return  SUCCESS, errorInfo
     */
    bStatus_t Data_start( void )
    {
      bStatus_t status = SUCCESS;
    
      // Register the handlers
      status = BLEAppUtil_registerEventHandler( &dataGATTHandler );
    
      // Return status value
      return( status );
    }
    
    
    /*********************************************************************
     * @fn      SimpleBLECentral_EnableNotification
     *
     * @brief   Enable notification for a given attribute handle.
     *
     * @param   connHandle - connection handle to send notification on
     * @param   attrHandle - attribute handle to send notification for
     *
     * @return  none
     */
    static void SimpleBLECentral_EnableNotification( uint16 connHandle, uint16 attrHandle )
    {
      attWriteReq_t req;
    
      req.pValue = GATT_bm_alloc( connHandle, ATT_WRITE_REQ, 2, NULL );
      if ( req.pValue != NULL )
      {
        uint8 notificationsOn[] = {0x01, 0x00};
        req.handle = attrHandle;
    
        req.len = 2;
        memcpy(req.pValue, notificationsOn, 2);
    
        req.sig = FALSE;
        req.cmd = TRUE;
    
        if ( GATT_WriteNoRsp( connHandle, &req ) != SUCCESS )
        {
          GATT_bm_free( (gattMsg_t *)&req, ATT_WRITE_REQ );
        }
    
      }
    }
    
    Menu_doGattWriteCB.TXT

  • Hi Lea, 

    Hope you’re doing well.

    Thanks for your support on a BLE interoperability issue we’re seeing with CC2340R5 in Central role.

    The annual volume of this project is significant, so they are quite concerned about the schedule impact.

    I’d really appreciate your help to take a closer look and guide us on the fastest path to resolution.

  • Hi Mike !

    I think that the issue comes from your ATT_HANDLE_VALUE_NOTI case in GATT_EventHandler under data.c.
    The gattMsg->msg object is of the type gattMsg_t, which is a union type. This means that instead of being a very big object, it's the size of the maximum struct in the union, and knowing the right type is essential.

    In your case, you are reading the readRsp member of the union, while you should be reading handleValueNoti instead, since you are filtering for ATT_HANDLE_VALUE_NOTI messages. You are therefore reading in a attReadRsp_t instead of attHandleValueNoti_t

    The difference between those two structs is that while the len member for attReadRsp_t is at offset 0, the member at offset 0 is the handle. This means that you are reading the handle of the notification as the length of your data.

    Please change your code to instead use :

    uint16_t len    = gattMsg->msg.handleValueNoti.len;
    uint8_t *data   = gattMsg->msg.handleValueNoti.pValue; 

    And see if it works.

    Kind regards,
    Lea

  • Hi Lea, 

    Thanks for your prompt support.

    I have contacted Luke to test the code.

  • Hi Lea,

    Thank you.

    It work right now !!

  • So happy to hear ! If you have another similar issue please feel free to create another thread.

    Have a nice day !