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: ATT_HANDLE_VALUE_IND event stops happening after some time

Part Number: CC2340R5
Other Parts Discussed in Thread: CC2541

Tool/software:

Hello

I´m developing an application based in the basic BLE project set as Central (in syscfg file) and I´m using the example available in the simplelink_lowpower_f3_sdk_8_10_01_02.

The implementations below were done and works as expected:

* Connection handling - OK

* Services discovery - OK

* Characteristics and their descriptors discovery - OK

* CCCD discovery - OK

* Menu module options and functions to enable/disable indications were created - OK

* Register the BLEAPPUTIL_ATT_HANDLE_VALUE_IND event  - OK

The peripherals I need to connect have 2 characteristics set to Indicate and one set as Write. Everything until this point is working really good.

So, after connecting and discovering everything mentioned above, I proceed to manually turn ON indications for one of these 2 characteristics and the result is the central starts to receive ATT_HANDLE_VALUE_IND notifications as expected. I see the payload data received by central is perfect.

At first, central was receiving only the first notification and never a second one. Then I learned centrals need to send acknowledgment back after receiving Indication data so I added a call to function ATT_HandleValueCfm(gattMsg->connHandle);

After doing this, my central started to receive Indications constantly, always with updated data on it. But after a few seconds the Indication events stops and ATT_FLOW_CTRL_VIOLATED_EVENT happens.


This is the event code snippet that access the nofitication data and invokes the ATT_HandleValueCfm function.

    case   ATT_HANDLE_VALUE_IND:
        {
           
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE1, 0, "Indication length= %d",
                                          gattMsg->msg.handleValueInd.len);
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE2, 0, "DATA BYTES = 0x%02x, 0x%02x, 0x%02x",
                                          gattMsg->msg.handleValueInd.pValue[0],
                                          gattMsg->msg.handleValueInd.pValue[1],
                                          gattMsg->msg.handleValueInd.pValue[2]);
            pesoBruto=gattMsg->msg.handleValueInd.pValue[6]<<24;
            pesoBruto|=gattMsg->msg.handleValueInd.pValue[5]<<16;
            pesoBruto|=gattMsg->msg.handleValueInd.pValue[4]<<8;
            pesoBruto|=gattMsg->msg.handleValueInd.pValue[3];
            MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE3, 0, "PESO BRUTO = %ld", pesoBruto);
            //ClockP_usleep(100000);
           // vTaskDelay( 1000 );
            ATT_HandleValueCfm(gattMsg->connHandle);

            break;
        }

I tried to add a variety of delays but I don´t know if this is right. When I uncomment one fo those 2 delay lines (ClockP_usleep(10000); or vTaskDelay( 100 ); ) the flow control violation does not happen anymore but the Indication event still stops happening after a few seconds.

So a few questions:

1) Is ATT_HandleValueCfm(gattMsg->connHandle); the correct way to acknowledge an Indication?

2) If yes, is this the correct place to call it? (inside the event handler right after dealing with the payload data)

3) Those delays are a good thing to use in that place? (inside the event handler right after dealing with the payload data)

Thank you in advance

 

  • A few more information. Inside the indication event posted above, I included print information about the heap stats.

    I see the total free size starts good but after each Indication processing this heap free size drops until it has a few bytes left. Thats when everything stops working (of course).

    I am not allocating any type of memory thus I believe I don´t have to explicitly free anything.

    Below is an example of the last heap free size value before the indication stop.

        case   ATT_HANDLE_VALUE_IND:
            {
               
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE1, 0, "Indication length= %d",
                                              gattMsg->msg.handleValueInd.len);
                
                ICall_heapStats_t stats;
                ICall_getHeapStats(&stats);
             
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE2, 0, "Total Heap Size: %lu - Total Free Size: %lu",
                                              stats.totalSize,stats.totalFreeSize);
                pesoBruto=gattMsg->msg.handleValueInd.pValue[6]<<24;
                pesoBruto|=gattMsg->msg.handleValueInd.pValue[5]<<16;
                pesoBruto|=gattMsg->msg.handleValueInd.pValue[4]<<8;
                pesoBruto|=gattMsg->msg.handleValueInd.pValue[3];
                MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE3, 0, "PESO BRUTO = %ld", pesoBruto);
                ClockP_usleep(10000);
               // vTaskDelay( 100 );
                ATT_HandleValueCfm(gattMsg->connHandle);
    
                break;
            }

  • Well, adding this line at the end of GATT_EventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData) function solves the heap problem above.

    GATT_bm_free(&(gattMsg->msg), gattMsg->method);

    I wonder why it is not there by default in the SDK original app_data.c file

    But the ATT_FLOW_CTRL_VIOLATED_EVENT problem is still happening. I was wrong about those delay lines. They do not prevent this event from happening in the central app. What was happening before is the heap memory was ocurring prior to flow control violation. Once I stoped the heap decrease this violation happens no matter what delay is or isn´t used.

    Any thoughts about how to prevent the central from doing this? When I connect to the peripherals I´m using to test my central from a smartphone this never happens in the smartphone side, so I believe this is something that can be fixed in the central app behavior in the code.

    Any thoughts?

  • Hi,

    Thank you for reaching out. Can you share how quickly you are receiving the indications and how much data is contained in each one?

    Best Regards,

    Jan

  • Hello Jan

    The peripheral is set to indicate each 80 ms.

    The actual amount of useful data is 15 bytes. Short packages. 

    Thank you.

  • Hello Alexandre,

    The ATT_FLOW_CTRL_VIOLATED_EVENT is send to the app when the Central/Client has violated the ATT flow control requirements, for instance: central sending a read request before sending an indication confirmation. Are you doing some other operation in between or in addition to indications that could violate the flow or delay the ack of the indication to be send back to the peripheral?

    After doing this, my central started to receive Indications constantly, always with updated data on it. But after a few seconds the Indication events stops and ATT_FLOW_CTRL_VIOLATED_EVENT happens.

    Do you have a Bluetooth sniffer at hand? Comparing the ble logs between your central and the phone could be useful to spot the difference here.

    BR,

    David.

  • Hello David

    Thank you for taking the time to help.

    I did not do any modification that could trigger an ATTRead or any other ATT operation.

    It´s the basic BLE project set as central and operating through the Terminal Menu it provides over the serial port and the modifications done by my side are related basically to app_data.c, app_menu.c and app_connection.c files but everything is triggerd by the LP_EM_CC2340R5 side buttons and the Terminal menus. I´m using LP_XDS110 for debugging.

    Unfortunately I don´t have any BT Sniffer yet.

    I understand what this violation event means but I´m not sure what might be triggering it since I don´t intentionally start any ATT operation that could lead to this problem.

    The peripheral has 3 characteristics (2 Indicate and 1 Write) and at this point I just turn ON Indication of char 1 that is the peripheral transmission buffer where it update it´s buffer each 80 ms and pack 15 bytes of payload data to be sent to central through Indication.

    My code is not writing to any other characteristic nor is trying to turn ON indication in the second characteristic. At this point I just want to receive the data buffer, process the information and display it somewhere.

  • An update. I measured the time between indications received and my peripheral was sending some with 48 ms interval in some situations, most likely because it already had a data ready and it received the acknowledge from client, then it sent it right of the bat.

    I fixed this behavior on the peripheral side since it´s also mine and I have full control over it (uses CC2541).

    80 ms original interval which is desired, is not an issue but those 48 ms or probably some even lower that I didn´t catch with the scope are.

    Is there a way to tweak the stack to avoid this problem? What is the minimum interval between indications that could cause this violation? 48 ms does not seems fast enough to cause this.

    It almost feels like a #define somewhere is the answer

  • Hello Alexandre,

    Thanks for the update, very useful. Could you please share with me where in the code are you measuring this interval? It might be the case that as you mention the central is responding back with a enqueued msg.

    BR,

    David

  • Hello David

    Thank you reaching out again.

    Yes is in the function GATT_EventHandler (app_data.c) inside the ATT_HANDLE_VALUE_IND event.

    I´m toggling the red led in the launchpad and measure it with the scope.

    case   ATT_HANDLE_VALUE_IND:
            {
                GPIO_toggle(CONFIG_GPIO_LED_RED);
                if(gattMsg->msg.handleValueInd.len==WT_PAYLOAD_SIZE)
                {
                  uint8_t* payload = gattMsg->msg.handleValueInd.pValue;
                  
                  batLevel  = payload[0];
                  unidade   = payload[1]&0x0F;
                  dpto      = payload[1]>>4;
                  pFlags    = payload[2];
                  
                  pesoBruto=payload[6]<<24;
                  pesoBruto|=payload[5]<<16;
                  pesoBruto|=payload[4]<<8;
                  pesoBruto|=payload[3];
    
                  pesoTara=payload[10]<<24;
                  pesoTara|=payload[9]<<16;
                  pesoTara|=payload[8]<<8;
                  pesoTara|=payload[7];
    
                  pesoLiq=payload[14]<<24;
                  pesoLiq|=payload[13]<<16;
                  pesoLiq|=payload[12]<<8;
                  pesoLiq|=payload[11];
                 
    #ifdef  USE_WEIGHT_HUD 
                  char *colorB, *colorT, *colorL;
                  int line = APP_MENU_PROFILE_STATUS_LINE1;
                  char format[100];
    #ifdef DEBUG_INDICATION 
                  line = APP_MENU_PROFILE_STATUS_LINE3;
    #endif         
                  //Mostra pesos
                  if(pFlags&FLAG_ERRO_AD)
                  {
                    MenuModule_printf(line++, 0, 
                                      MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_RED 
                                      "        REPORTADO ERRO AD       "
                                      MENU_MODULE_COLOR_RESET);
                  }
                  else if(pFlags&FLAG_OVER)
                  {
                     MenuModule_printf(line++, 0, 
                                      MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_RED 
                                      "           OVERLOAD!!!          "
                                      MENU_MODULE_COLOR_RESET);
                  }
                  else
                  {
                    if(pFlags&FLAG_BRUTO)
                    {
                      colorB=MENU_MODULE_COLOR_GREEN;
                      colorL=MENU_MODULE_COLOR_WHITE;
                    }
                    else
                    {
                      colorL=MENU_MODULE_COLOR_GREEN;
                      colorB=MENU_MODULE_COLOR_WHITE;
                    }
                    colorT=MENU_MODULE_COLOR_WHITE;
                    sprintf(format, "%s%sB: %%07ld %s%sT: %%07ld %s%sL: %%07ld",MENU_MODULE_BORDER_COLOR_BLUE,colorB,MENU_MODULE_BORDER_COLOR_BLUE,colorT,MENU_MODULE_BORDER_COLOR_BLUE,colorL);
                    MenuModule_printf(line++, 0,format, pesoBruto, pesoTara, pesoLiq);
                    //Mostra estabilidade
                    if(pFlags&FLAG_STABLE)
                    {
                      MenuModule_printf(line++, 0, 
                                        MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_GREEN 
                                        "             ESTAVEL            "
                                        MENU_MODULE_COLOR_RESET);
                    }
                    else
                    {
                      MenuModule_printf(line++, 0, 
                                        MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_YELLOW 
                                        "            INSTAVEL            "
                                        MENU_MODULE_COLOR_RESET);
                    }
                    //Mostra nível de bateria
                    if(batLevel<100)
                    {
                      if(batLevel>=60)
                        MenuModule_printf(line++, 0,MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_GREEN "          Bateria: %d " "%%         ",batLevel);
                      else if(batLevel>=30)
                        MenuModule_printf(line++, 0,MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_YELLOW "          Bateria: %d " "%%         ",batLevel);
                      else
                        MenuModule_printf(line++, 0,MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_RED "          Bateria: %d " "%%         ",batLevel);
                        
                    }
                    else
                    {
                      MenuModule_printf(line++, 0,MENU_MODULE_BORDER_COLOR_BLUE MENU_MODULE_COLOR_GREEN "         Bateria: %d " "%%         ",batLevel);
                    }
                    
                  }
    
    #endif
                }
                //ClockP_usleep(50000);
                //vTaskDelay( 80 );
                //Ack Indication
                ATT_HandleValueCfm(gattMsg->connHandle);
                break;
            }

    Another useful information. This does not seem to be related to how fast the peripheral send the indication. 

    I did modify my peripheral (CC2541 with code based on SimpleBLEPreipheral project) to send Indications with more than 100 ms interval and I still have the same problem happening from time to time. It just takes more time to happen but eventually it will happen.

    I also have another product that uses BT900 from Laird and I did implement the same GATT profile in this product as well. So my central can connect on that product and read everything. I do not have this issue when I connect to BT900 and enable the same char indication. With this product it runs without having this violation problem.

    I understand the implementation in both CC2541 and BT900 are different. I´m just trying to understand what exactly is happening.

  • Hello Alexandre,

    Have you tried using another device such as the cc23xx as the peripheral to send indications (I understand it works fine with another peripheral device). Would it be possible to consider using the cc23xx as an alternative. This is of course not a justification/explanation of why things are not currently working, but I want to understand if there is window here for selecting a newer device. Regarding the current peripheral, what SDK version for CC2541 are you using?

    BR,

    David.

  • Hello David

    Unfortiunately I don´t have a window to change the BT chip in my products. This one I´m developing is a new one and I select CC2340R5 because it can hold 8 connections at the same time. (CC2541 can hold only 3).

    As explained, one of them uses BT900 from Laird and another one uses CC2541. I understand without a sniffer this becomes really difficult to fix, but I suspect this flow control violation problem is being caused by CC2541 operation.

    I did increase the time interval between indications in CC2541 (peripheral) and this made the violaton stop when in really short range (they are near each other). When I put the CC2541 peripheral far from my central (RSSI from peripheral is between -80 and -90 dBm) the flow control violation starts to happen again.

    Doing this same test with my other peripheral (BT900) the central never gets the flow control violation. I put the BT900 far from central just like I do with CC2541 but I never ever had a flow control violation with that peripheral with BT900. I go as far as I can and what happens is the connection gets terminated due to LL_STATUS_ERROR_CONNECTION_TIMEOUT because the peripheral is out of range.

    So I have been trying to modify the SimpleBLEProject in the CC2541 firmware side in order to try to fix this behavior. So now the attention shifted from CC2340R5 to CC2541 because i really believe the issue is there.

    Any thoughts about this? I mean, what I could try to set, modify or enable in the CC2541 firmware to avoid this?

    Thank you and best regards

  • Oh and the SDK for CC2541 is BLE-CC254x-1.5.2.1

  • Hello Alexandre,

    Thanks for the additional information. Please allow me until Monday to provide take a closer look at this issue an provide better advice. I will see as well if there are known issues related to flow control violation with that SDK version.

    BR,

    David.