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: get services and turn on Notification for UUID

Part Number: CC2340R5
Other Parts Discussed in Thread: SYSCONFIG

Hi, 

     I have am using my cc2340 as central and one as peripheral and i am able to successfully connect the central and peripheral and now i want to get services and turn on notification on which the peripheral will notify values.

the peripheral is working fine with mobile apps but i want to use my cc2340 as central and want to get notifications. which api's should i use and how can i get services and enable the notification from the cemtral.

my sdk version is simplelink_lowpower_f3_sdk_7_10_00_35.

Thanks in advance

  • Hello prince,

    Thanks for reaching out, I will send this to the corresponding expert.

    Kind Regards,

    Rogelio

  • Hi,

    Have you already set up the notification permission and logic on the peripheral side? When connecting with a smart phone to your peripheral CC2340R5 device, are you able to successfully enable notifications and successfully receive the notifications?

    Best Regards,

    Jan

  • Hi Jan,

                 yes i have set up the notificaton from the peripheral side and successfully able to enable and get the notification on the mobile app from peripheral(CC2340R5 ) .

    Thank you

    Prince Singh

  • Hi Prince Singh,

    I'm glad to hear you have set up the peripheral side properly on the CC2340R5 and that it is working as expected!

    To set up the central side, you will need to set the BLE role as Central through SysConfig (shown below):

    Afterwards, when the project is built, all of the code that is necessary for the central project to operate will be uncommented and any that is not will be commented through the use if #ifdef statements.

    You will need to add logic for interacting with the characteristics themselves to the project, I would recommend adding this logic in the app_connection.c. You will need to reference some of the GATT functions present in the gatt.h file. You will need to call the GATT_RegisterForInd() to register to receive commands in the first place. You will also need to enable the notifications for the attribute itself. You can do this using GATT functions as well. An older example from the previous generation of devices has some sample code that may be a helpful reference (you may need to do some modifications as this is for an older SDK):

    This code may be found here: https://github.com/TexasInstruments/ble_examples/blob/simplelink_cc13x2_26x2_sdk-5.10/source/ti/ble5stack/profiles/simple_serial_stream/simple_stream_profile_client.c

    Best Regards,

    Jan

  • Hi Jan

                I am using central+peripheral and initially the CC2340 is working as peripheral and when command is given on UART it works as central and connects with predefined BLE-MAC and till this point things are working fine i am able to connect the device with other peripheral but i am not able to find and change the characteristic value of peripheral using my central device , which function i need to use for these purposes. For finding the characteristics i am using uint8_t status = GATT_DiscAllPrimaryServices(connHandle, taskID); , and it returns SUCCESS but after that no event is being generated , means i am not getting any event (for finding Services)

    Thank you

    Prince singh

  • Hi Prince,

    Thank you for the additional details. To clarify, at this time the Basic BLE project, does not come with GATT table viewing functionality built-in. The stack should support all the operations but the example does not implement these by default. You will need to implement the functionality by adding to the application code or the bleAppUtil files. I think you are heading in a good direction.

    Have you subscribed to GATT events? This may be why we are not seeing the event return. I believe by default the BleAppUtil files subscribe to GATT events so the event may be being routed in those files.

    Best Regards,

    Jan

  • HI Jan,

                The GATT event is subscribed and i am able to get the characteristic value notification from the peripheral to client if i notify something from the peripheral with AUTO NOTIFICATION, but not able to get any event if i set MTU or GATT_DiscAllPrimaryServices from the central side.

    Thank you

    Prince Singh

  • Hi,

    Got it. As a quick test, can you try using GATT_DiscPrimaryServiceByUUID() and seeing if that returns a code or generates an event?

    Best Regards,

    Jan

  • Hi Jan,

               It returns SUCCESS but does not generate any event. i am using  status  =  GATT_DiscAllPrimaryServices(gapEstMsg->connectionHandle, INVALID_TASK_ID);

    in void Connection_ConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData) in Linnk stablished event.

  • Hi,

    My apologies, did you mean that calling GATT_DiscPrimaryServiceByUUID() returns success or that calling GATT_DiscAllPrimaryServices() returns success? I would like to verify if the other GATT discover functions behave in a different manner.

    Best Regards,

    Jan

  • Hi Jan,

                GATT_DiscAllPrimaryServices gives success , and i found that by GATT_WriteNoRsp () or  GATT_WriteCharValue( uint16 connHandle, attWriteReq_t *pReq, uint8 taskId ) can i set Value of characteristic of the peripheral from central ? and where can i get all these parameters ?

    i am using this function in bleapputill_process.c when central gets notification from the peripheral instant i am setting characteristic value using the same parameters

    void BLEAppUtil_processGATTEvents(BLEAppUtil_msgHdr_t *pMsg)
    {
    gattMsgEvent_t * pMsgData = (gattMsgEvent_t *)pMsg;
    uint32_t event = 0;
    uint8 *char_val = pMsgData->msg.writeReq.pValue;

    // Define the attribute write request structure
    attWriteReq_t writeReq1;
    writeReq1.handle = pMsgData->msg.writeReq.handle; // Set the handle of the characteristic to write to
    writeReq1.len = 0x01; // Set the length of the value to be written
    uint8 arr = 0x11;
    writeReq1.pValue = &arr; // Set the actual value to be written

    bStatus_t result = GATT_WriteNoRsp(pMsgData->connHandle, &writeReq1);
    if (result == SUCCESS) {

    UART2_write(uart,"successfully",12,NULL);
    }
    else
    {
    UART2_write(uart,&(result),1,NULL);
    }

    but i am getting 0x02 in return of GATT_WriteNoRsp() which indicates about invalid parameter

    Thank You 

    Prince singh

  • Hi Prince,

    I believe you need to allocate space for the writeReq1 message via the GATT_bm_alloc() function sho. Can you try setting the .cmd and the .sig field as well?

    Best Regards,

    Jan

  • Hi jan,

                I am able to get and set data of characteristic but only upto 1 PDU(size of MTU) in both get and set case. For example if MTU size is 30 bytes and i want to send 64 bytes then i am sending it in 30+30+4 packets(from peripheral) which is working with mobile app. but in my CC2340 event i am only getting first 30 bytes(equal to current MTU).

    Thank you 

  • Hi Prince,

    Does the behavior hold if you increase the PDU size? For example, if you increase it to 60, do you see 60 + 4?

    Best Regards,

    Jan

  • Hi Jan,

                  Peripheral is working fine now and now i am trying same thing in Central side and i am able to send whatever current MTU size is, but if i want to send more that MTU size then i need to send it in packets of current MTU size. For that i am using

    while(offset < BYTESTOSEND)
    {
    if((BYTESTOSEND-offset)>currentMTUSize)
    len = currentMTUSize;

    else
    len = BYTESTOSEND-offset;
    writeReq.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, len, NULL);

    if ( writeReq.pValue != NULL )
    {
    writeReq.handle = 0x25; // Set the handle of the characteristic to write to
    writeReq.len = len; // Set the length of the value to be written

    memcpy(writeReq.pValue, &charVal[offset], len);
    writeReq.sig = 0;
    writeReq.cmd = 0;
    ICall_EntityID selfEntity = BLEAppUtil_getSelfEntity();
    if (GATT_WriteCharValue(connHandle, &writeReq, selfEntity) != SUCCESS) {
    GATT_bm_free((gattMsg_t *)&writeReq, ATT_WRITE_REQ);
    offset = BYTESTOSEND;
    }
    else
    offset += len;

    }}

    But after  one pcaket GATT_WriteCharValue does not return succes it returns 0x16 

    Thank you 

    Prince Singh

  • Hi Prince,

    The return code 0x16 seems to map to blepending. The GATT_WriteCharValue() returns blepending when " A response is pending with this server.". As a quick test, can you try waiting some time before calling the function again?

    Best Regards,

    Jan

  • Hi Jan,

                I tried using GATT_WriteLongCharValue() and i am able to wrtie full PDU (MTU x number of PDU) at a time . and i am scanning for advertisements and only able to scan 2-4 devices in 40 seconds which are very less and while using mobile app i am able to scan 25-30 devices.

    Thank you

    Prince Singh

  • Hi Prince,

    The amount of devices that appear when you scan will highly depend on the environment, the scanning parameters, and the advertising parameters. I would recommend modifying the scanning parameters to best suit your environment. I would recommend increasing your scan time to start and finetuning the final settings based on the performance you see.

    Best Regards,

    Jan

  • Hi, 

          While sending data from peripheral to central , my central device stuck in while(1) at

    void *Mtx_getTlsPtr(void)
    {
    TaskHandle_t task;
    void *buf;

    if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED)
    {
    return (__section_begin("__iar_tls$$DATA"));
    }

    /* running in a secondary thread */
    task = xTaskGetCurrentTaskHandle();
    buf = pvTaskGetThreadLocalStoragePointer(task, MTX_TLS_INDEX);

    if (buf == NULL)
    {

    buf = __section_begin("__iar_tls$$DATA");
    vTaskSetThreadLocalStoragePointer(task, MTX_TLS_INDEX, buf);

    buf = pvPortMalloc(__iar_tls_size());

    if (buf != NULL)
    {
    __iar_tls_init((char *)buf);
    vTaskSetThreadLocalStoragePointer(task, MTX_TLS_INDEX, buf);
    }
    else
    {
    volatile int spin = 1;
    while (spin)
    ;
    }
    }

    return (buf);
    }

    and it happens after recieving perticular number of bytes like 30 packets of 128 bytes data , and when i increase heap size in the sysconfig i can get more packets before going into this while  but again it goes into while loop, currently i am using heap size 4900 and when i decrese heap to 4500 i can get only 19 packets of data .

    Thank you

     Prince Singh

  • Hi Prince,

    Can you monitor the heap consumption during runtime while the behavior occurs? Do we see the heap increase slowly? We may be missing a free() call somewhere to deallocate previously allocated memory.

    Best Regards,

    Jan

  • Hi Jan,

                I cant find the way to monitor heap consumption in runtime in IAR embedded workbench, and i am not assigning any memory in central for storing recieved data , i am not doing anything with that recived data still after sending fix amount of data from peripheral to central ,central get stuck in that while 

    Thank you

  • Hi Prince,

    Can you try using CSS at least for debugging purposes? This may provide us with more clues as to what may be going on.

    Best Regards,

    Jan

  • Hi Jan,

                i have debug the code into CCS also but same thing happenig after certain amount of data it goes into while(1) of void *Mtx_getTlsPtr(void). and you told that "We may be missing a free() call somewhere to deallocate previously allocated memory" is it about the example provided ? because i am not allocating any memory even i am not storing recieved data anywhere just sending the data from peripheral and then GATT_MSG_EVENT is generated and following line is called 

    case GATT_MSG_EVENT:
    BLEAppUtil_processGATTEvents(pMsgData); 

     after that void BLEAppUtil_processGATTEvents(BLEAppUtil_msgHdr_t *pMsg) is called 

    Thank you 

    Prince Singh

  • Hi Prince,

    Does the code below run every time a packet is sent? If so, then I have a few questions that may help me get a better understanding of what may be going on.

    void *Mtx_getTlsPtr(void)
    {
        TaskHandle_t task;
        void *buf;
        
        if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED)
        {
            return (__section_begin("__iar_tls$$DATA"));
        }
        
        /* running in a secondary thread */
        task = xTaskGetCurrentTaskHandle();
        buf = pvTaskGetThreadLocalStoragePointer(task, MTX_TLS_INDEX);
        
        if (buf == NULL)
        {
        
            buf = __section_begin("__iar_tls$$DATA");
            vTaskSetThreadLocalStoragePointer(task, MTX_TLS_INDEX, buf);
            
            buf = pvPortMalloc(__iar_tls_size());
            
            if (buf != NULL)
            {
                __iar_tls_init((char *)buf);
                vTaskSetThreadLocalStoragePointer(task, MTX_TLS_INDEX, buf);
            }
            else
            {
                volatile int spin = 1;
                while (spin)
                ;
            }
        }
        
        return (buf);
    }

    In the code above, I see that you are calling pvPortMalloc(), but there's no corresponding pvPortFree() call. I am not familiar with what vTaskSetThreadLocalStoragePointer(task, MTX_TLS_INDEX, buf);. Does that function free the buf when it is done with it? 

    Best Regards,

    Jan

  • Hi Jan,

                it is alredy implemented in the basic_ble example and this code only occures after some packets is recieved and after this code is performed central stops data receiving for example if i have set the heap size from sysconfig 4500 i can get and print on UART 14 packets of 232 bytes and this code perorms after 15th packet is recived   and when i set heap size to 5000 i can get and print on UART 19 packets and this code is permfomed after 20th packet received and after that code stuck in while(1)

    Thank you

  • Hi Prince,

    Are you only sending data using the GATT_WriteLongCharValue() function? If not, then please let me know how else data is being transmitted. In the case of GATT_WriteLongCharValue() have you added a case to free the allocated data if the transmission fails? This may be increasing our heap consumption. A debugging method we can try is to monitor the heap during runtime to try to narrow down exactly which actions or statements are causing the heap consumption to increase.

    Best Regards,

    Jan

  •     uint16_t connHandle = 0x00;
         
          attPrepareWriteReq_t writeReq;
          
          len = count;
          writeReq.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, len, NULL);
          
          if ( writeReq.pValue != NULL )
          {
            writeReq.handle = 0x25; // Set the handle of the characteristic to write to
            writeReq.len = len; // Set the length of the value to be written
            
            memcpy(writeReq.pValue, &input, len);
            // writeReq.sig = 0;
            // writeReq.cmd = 0;
            writeReq.offset = 0;
            ICall_EntityID selfEntity = BLEAppUtil_getSelfEntity();
            // bStatus_t  status = GATT_WriteCharValue(connHandle, &writeReq, selfEntity);
            bStatus_t  status = GATT_WriteLongCharValue(connHandle,&writeReq, selfEntity) ;
            if ( status != SUCCESS) {
              {
                //UART2_write(uart,&status,1,NULL);
                GATT_bm_free((gattMsg_t *)&writeReq, ATT_WRITE_REQ);
              }
              
            }
            
          }

    Hii Jan,

                  i do free the memory if transmission fails , but this code doen not stuck in transmission it stuck in the reception , beacuse i can transmit 100-200 packets code runs smoothly but even if i do not transmit anything still code stuck in reception.

    And can you tell me how can i chek heap in runtime in CCS

    Thank You

    Prince

  • Hi Prince,

    Got it. Thank you for providing the code. The Debugging Common Heap Issues section of the User's Guide contains information on how to monitor heap. Can you check and see if we can see the heap increasing with each packet sent? If so, then can you verify how much?

    Best Regards,

    Jan 

  • Hi Jan,

                 following are the heap availability before and after the code stucks. every time i send 232 bytes data heap avalability reduces by 400.

    Thank you 

    Prince

                 

  • Hi Prince,

    To confirm, each time a packet is sent we reduce by 400 and do not recover? In other words, you send the first packet and the free bytes are reduced by 400 and when we do it again we reduce by another 400 (for a total of 800)? If so, then there must be a memory leak somewhere. Can you share the amount of time between 232 byte packets transmission? Could we try increasing the amount of time as a test?

    Could we also try using ATT_PREPARE_WRITE_REQ instead of ATT_WRITE_REQ for the opcode? I would like to see if we experience the same behavior there as well.

    Best Regards,

    Jan

  • Hi Jan,

                Yes you are right every time memory reduced by 400 and does not get free and  I wait for 2-3 seconds before sending another packets and i waited more but memory doesn't get free .

    and i have also tried ATT_PREPARE_WRITE_REQ  but it didnt work because it will be called when i transmit data from central but in this case i am recieiving data to the central and memory doesnt get free but in case of other GATT events like MTU update memory gets free after allocation only in case of notification  this problem occur. 

    Thank you 

    Prince Singh

  • Hi Prince,

    My apologies for any confusion here. To confirm, the the issue is being observed on the central side when a packet is received correct? The peripheral side is behaving properly?

    Best Regards,

    Jan

  • Hi,

    Understood, then it is possible we are not handling the received packet properly somewhere in the application (could be in the bleapputil framework itself). Can you check what happens if we call a free() after the data is received (even if it has succeeded)?

    Best Regards,

    Jan

  • Hi Jan,

                 it calls free already but not full memory frees 400 bytes every time remains.  One thing i want to ask that  GATT_WriteLongCharValue(connHandle,&writeReq, selfEntity) ; function takes more than 1 second to transmit 232  bytes data and 900ms to transmit 1packet of 128 byte data cant we minimize this time.

    Thank you

    Prince Singh

  • Hi Prince,

    Can you share the connection interval as well as the PDU size you are using? This may impact the amount of packets you can send and how large these packets are in a connection event. I would try reducing the connection interval to see if this speeds up the data transfer time.

    Best Regards,

    Jan

  • Hi Jan,

                 connection interval is min 100ms and max 100ms and i am using 

    Max Number of PDUs =6
    Max Size of PDU (bytes) = 69

    and i want to send 128 bytes in every single packet. 

    Thank you

    Prince Singh

  • Hi Prince,

    Can you try increasing the Max size of PDUs to 255? This will lead to larger packet sizes and potentially reduce the amount of packets required to send your data. I think your connection interval setting is okay for this setup, but if lower latency is desired you could lower it further.

    Best Regards,

    Jan

  • Hi Jan,

               Still speed of GATT_WriteLongCharValue is less then SimpleGattProfile_setParameter(). For example i am sendig data peripheral to  central using SimpleGattProfile_setParameter and central to peripheral using GATT_WriteLongCharValue the speed of central to peripheral is less very less compared to SimpleGattProfile_setParameter .

    And  have you found any way to resolve  that heap issue becauese  still if i send data from peripheral to central using SimpleGattProfile_setParameter () this issue occures in central device (i  have not defined any variable or pointer the code is default )  .

    Thank you

    Prince singh

  • Hi Prince,

    Got it, I will prioritize the heap issue going forward. Can you clarify what code you have added to enable the read functionality on the central side? Are you calling GATT_ReadLongCharDesc()? How are you handling the ATT_READ_BLOB_RSP response on the central side?

    Best Regards,

    Jan

  • Hi Jan,

                I have not added any code to the central side. Whenever i set the parameter of the connected peripheral using SimpleGattProfile_setParameter() the GATT_MSG_EVENT in central automatically get triggered and in BLEAppUtil_processGATTEvents() i can get the value using following method

    Thank you 

    Prince SIngh

      gattMsgEvent_t * pMsgData = (gattMsgEvent_t *)pMsg;
        uint32_t event = 0;
         //vPortGetHeapStats(&heapStats);
    
        switch (pMsgData->method)
        case ATT_HANDLE_VALUE_NOTI :
        {  
        uint8 *char_val = pMsgData->msg.writeReq.pValue;
        uint16 len = pMsgData->msg.writeReq.len ;
        memcpy(&recieved_val[recieved_len],char_val,len);
        recieved_len = recieved_len+len;
        
        if(len!=currentMTUSize)
        {
          UART2_write(uart,&recieved_val,recieved_len,NULL);
          recieved_len =0;
        }
         break;  
        }
     

  • Hi Prince,

    My apologies for the delay. I took some time to research this issue further.

    Can you clarify exactly where you have placed the code you have provided? Based on your code, i think we are missing a GATT_bm_free() statement. I am basing this on how the SimpleSerialSocketClient handles received notifications. The relevant section is shown below:

    The code may be found here: https://github.com/TexasInstruments/ble_examples/blob/simplelink_cc13x2_26x2_sdk-5.10/examples/rtos/CC26X2R1_LAUNCHXL/ble5apps/simple_serial_socket_client/Application/simple_serial_socket_client.c

    The code is for a previous generation of device, but i expect the procedure to be very similar. i would start by trying to do GATT_bm_free() after you have extracted the data you need from the received pMsg.

    Best Regards,

    Jan

  • Hi Jan,

                 Now the heap issue is resolved using this free function , 

    Thank you

    Prince Singh 

  • Hello prince singh,

    Have you tried using the 2340 as a central to connect to other non-TI peripherals? I tried and found that it doesn't work, but the CC2642 does.

    Kind Regards,

    Sunger Sun

  • Hi Sunger,

    Could you post a new thread regarding this issue? This will ensure we are able to properly support your query and resolve it as promptly as possible.

    Best Regards,

    Jan