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.

Bluetopia MSP-430, max data per connection event

Other Parts Discussed in Thread: CC2540, CC2564

Hi!

I have 2 questions about Bluetopia stack:

1. What is max data per connection event? I have read for TI stack CC2540 it is 80 bytes per connection event. And what's about Bluetopia (CC2564) for MSP430?

2. What is max MTU value for GATT ?

#define BTPS_CONFIGURATION_L2CAP_MAXIMUM_SUPPORTED_STACK_MTU               (54 - L2CAP_DATA_PACKET_HEADER_SIZE)

so max value is 50

#define BTPS_CONFIGURATION_GATT_MAXIMUM_SUPPORTED_MTU_SIZE                ((48 > L2CAP_MAXIMUM_SUPPORTED_STACK_MTU)?L2CAP_MAXIMUM_SUPPORTED_STACK_MTU:48)

so max value is not grater 48

can I change these values? or it is limitation of implemetation?

Best regards

  • Hello,

    GATT MTU is locked at 48 in that release to satisfy some memory requirements. 

    Max data per connection is a controller parameter, we will check with TI to get their feedback on that one.

    Best Regards,

    Stonestreet One. 

  • Hello,

    Thank you for your response! Will wait information about TI feedback.

    Best Regards

    Artem Zemlyanukhin

  • Hi Artem,

    We allow up to 6 data packets per connection event.

    Regards,

    Miguel

  • Hi Miguel,

    Thank you for your answer!

  • Hi Miguel,

    I am using the EZ430-RF256x Bluetooth board for my project.
    I am using the SPPLEDEMO profile provided in the board's wiki page.
    I tried sending 8 bytes of data, but found out that only 6 bytes got through, while the remaining 2 bytes was not being resend.
    I checked through the code and found out that the maximum SPPLE Buffer Length can go up to 50 bytes, which should be able to send all 8 bytes of my data.
    What could be the problem for this to happen?
    Is there any other way to send a large value of data, say more than 50 bytes?

    Thank you.

    Regards,
    Yap
  • Yap,

    An issue has been found in SPPLEDemo.c that is seen when sending small amounts of data. If you send a larger amount of data, for example 30+ bytes, I expect that you won't see this behavior. This will be fixed in all future releases. I will provide an update here of what to change in the source code after the problem is resolved. It will be resolved by June 5th at the latest.

    Thanks,
    Samuel

  • Yap,

    The issue seen in SPPLEDemo.c specifically was that it could only send multiples of strlen(DataStr). The length of DataStr is 10 in the SDK's version of the app. So if the user requests to send 12 bytes only 10 would be sent, and if 2 bytes were requested then 0 would be sent. The problem you described sounds a little different unless you modified the app. Are you using the original version of the app found in "C:\ti\Connectivity\CC256X BT\CC256x MSP430 Bluetopia SDK\v1.5 R2\MSP430_Experimentor\Samples\SPPLEDemo\SPPLEDemo.c"  or a modified version of it?

    The patch for the problem I described is attached. You can apply it using:

      cd "C:\ti\Connectivity\CC256X BT\CC256x MSP430 Bluetopia SDK\v1.5 R2\MSP430_Experimentor\Samples\SPPLEDemo"
      patch --binary < SPPLEDemo_Send_Issue_Patch.txt

    patch may prompt you for the filename to patch, if so type SPPLEDemo.c and press enter.

    Thanks,
    Samuel

    SPPLEDemo_Send_Issue_Patch.txt
    --- C:\ti\Connectivity\CC256X BT\CC256x MSP430 Bluetopia SDK\v1.5 R2\MSP430_Experimentor\Samples\SPPLEDemo\SPPLEDemo_orig.c
    +++ C:\ti\Connectivity\CC256X BT\CC256x MSP430 Bluetopia SDK\v1.5 R2\MSP430_Experimentor\Samples\SPPLEDemo\SPPLEDemo.c
    @@ -235,15 +235,16 @@
     #define GAPLE_PARAMETERS_DATA_SIZE                       (sizeof(GAPLE_Parameters_t))
     
        /* The following structure holds status information about a send     */
        /* process.                                                          */
     typedef struct _tagSend_Info_t
     {
    -   Boolean_t BufferFull;
    -   DWord_t   BytesToSend;
    -   DWord_t   BytesSent;
    +   Boolean_t    BufferFull;
    +   DWord_t      BytesToSend;
    +   DWord_t      BytesSent;
    +   unsigned int DataStrIndex;
     } Send_Info_t;
     
        /* The following defines the structure that is used to hold          */
        /* information about all open SPP Ports.                             */
     typedef struct SPP_Context_Info_t
     {
    @@ -264,17 +265,17 @@
     
     } SPP_Context_Info_t;
     
        /* The following defines the format of a SPPLE Data Buffer.          */
     typedef struct _tagSPPLE_Data_Buffer_t
     {
    -   unsigned int  InIndex;
    -   unsigned int  OutIndex;
    -   unsigned int  BytesFree;
    -   unsigned int  BufferSize;
    -   Byte_t        Buffer[SPPLE_DATA_CREDITS];
    +   unsigned int InIndex;
    +   unsigned int OutIndex;
    +   unsigned int BytesFree;
    +   unsigned int BufferSize;
    +   Byte_t       Buffer[SPPLE_DATA_CREDITS];
     } SPPLE_Data_Buffer_t;
     
        /* The following structure represents the information we will store  */
        /* on a Discovered GAP Service.                                      */
     typedef struct _tagGAPS_Client_Info_t
     {
    @@ -719,13 +720,13 @@
     static unsigned int AddDataToBuffer(SPPLE_Data_Buffer_t *DataBuffer, unsigned int DataLength, Byte_t *Data);
     static unsigned int RemoveDataFromBuffer(SPPLE_Data_Buffer_t *DataBuffer, unsigned int BufferLength, Byte_t *Buffer);
     static void InitializeBuffer(SPPLE_Data_Buffer_t *DataBuffer);
     
     static int EnableDisableNotificationsIndications(unsigned int ConnectionID, Word_t ClientConfigurationHandle, Word_t ClientConfigurationValue, GATT_Client_Event_Callback_t ClientEventCallback);
     
    -static unsigned int FillBufferWithString(SPPLE_Data_Buffer_t *DataBuffer, unsigned *CurrentBufferLength, unsigned int MaxLength, Byte_t *Buffer);
    +static unsigned int FillBufferWithString(SPPLE_Data_Buffer_t *DataBuffer, unsigned *CurrentBufferLength, unsigned int MaxLength, Byte_t *Buffer, unsigned int *DataStrIndex);
     
     static void SPPLESendProcess(LE_Context_Info_t *LEContextInfo, DeviceInfo_t *DeviceInfo);
     static void SPPLESendCredits(LE_Context_Info_t *LEContextInfo, DeviceInfo_t *DeviceInfo, unsigned int DataLength);
     static void SPPLEReceiveCreditEvent(LE_Context_Info_t *LEContextInfo, DeviceInfo_t *DeviceInfo, unsigned int Credits);
     static unsigned int SPPLESendData(LE_Context_Info_t *LEContextInfo, DeviceInfo_t *DeviceInfo, unsigned int DataLength, Byte_t *Data);
     static void SPPLEDataIndicationEvent(LE_Context_Info_t *LEContextInfo, DeviceInfo_t *DeviceInfo, unsigned int DataLength, Byte_t *Data);
    @@ -2377,13 +2378,13 @@
           DataBuffer->InIndex    = 0;
           DataBuffer->OutIndex   = 0;
        }
     }
     
        /* The following function function is used to enable/disable         */
    -   /* notications on a specified handle.  This function returns the     */
    +   /* notifications on a specified handle.  This function returns the   */
        /* positive non-zero Transaction ID of the Write Request or a        */
        /* negative error code.                                              */
     static int EnableDisableNotificationsIndications(unsigned int ConnectionID, Word_t ClientConfigurationHandle, Word_t ClientConfigurationValue, GATT_Client_Event_Callback_t ClientEventCallback)
     {
        int              ret_val;
        NonAlignedWord_t Buffer;
    @@ -2398,49 +2399,55 @@
        else
           ret_val = BTPS_ERROR_INVALID_PARAMETER;
     
        return(ret_val);
     }
     
    -   /* The following funcition is a utility function that exists to fill */
    +   /* The following function is a utility function that exists to fill  */
        /* the specified buffer with the DataStr that is used to send data.  */
        /* This function will fill from the CurrentBufferLength up to Max    */
        /* Length in Buffer.  CurrentBufferLength is used to return the total*/
    -   /* length of the buffer.  The first parameter specifies the          */
    -   /* DeviceInfo which is used to fill any remainder of the string so   */
    +   /* length of the buffer.  The last parameter specifies the data      */
    +   /* string index which is used to fill any remainder of the string so */
        /* that there are no breaks in the pattern.  This function returns   */
    -   /* the number of bytes added to the transmit buffer of the specified */
    -   /* device.                                                           */
    -static unsigned int FillBufferWithString(SPPLE_Data_Buffer_t *DataBuffer, unsigned *CurrentBufferLength, unsigned int MaxLength, Byte_t *Buffer)
    +   /* the number of bytes added to the transmit buffer.                 */
    +static unsigned int FillBufferWithString(SPPLE_Data_Buffer_t *DataBuffer, unsigned *CurrentBufferLength, unsigned int MaxLength, Byte_t *Buffer, unsigned int *DataStrIndex)
     {
        unsigned int DataCount;
        unsigned int Added2Buffer = 0;
    +   unsigned int RemainingDataStrLen;
     
        /* Verify that the input parameter is semi-valid.                    */
        if((DataBuffer) && (CurrentBufferLength) && (MaxLength) && (Buffer))
        {
           /* Copy as much of the DataStr into the Transmit buffer as is     */
           /* possible.                                                      */
           while(*CurrentBufferLength < MaxLength)
           {
              /* Cap the data to copy at the maximum of the string length and*/
              /* the remaining amount that can be placed in the buffer.      */
    -         DataCount = (DataStrLen > (MaxLength-*CurrentBufferLength))?(MaxLength-*CurrentBufferLength):DataStrLen;
    +         DataCount = (DataStrLen > (MaxLength - (*CurrentBufferLength))) ? (MaxLength - (*CurrentBufferLength)) : DataStrLen;
     
    -         /* Note we should only add full strings into the transmit      */
    -         /* buffer.                                                     */
    -         if(DataCount == DataStrLen)
    -         {
    -            /* Build the data string into the SPPLEBuffer.              */
    -            BTPS_MemCopy(&Buffer[*CurrentBufferLength], DataStr, DataCount);
    +         /* Calculate the remaining space in the data string.           */
    +         RemainingDataStrLen = DataStrLen - (*DataStrIndex);
    +
    +         /* Possibly reduce the amount of data to add to the buffer by  */
    +         /* the current index within the data string.                   */
    +         DataCount = DataCount > RemainingDataStrLen ? RemainingDataStrLen : DataCount;
    +
    +         /* Build the data string into the SPPLEBuffer.                 */
    +         BTPS_MemCopy(&Buffer[*CurrentBufferLength], &DataStr[*DataStrIndex], DataCount);
     
    -            /* Increment the index.                                     */
    -            *CurrentBufferLength += DataCount;
    -         }
    -         else
    -            break;
    +         /* Increment the data string index.                            */
    +         *DataStrIndex += DataCount;
    +
    +         if((*DataStrIndex) >= DataStrLen)
    +            *DataStrIndex = 0;
    +
    +         /* Increment the index.                                        */
    +         *CurrentBufferLength += DataCount;
           }
        }
     
        return(Added2Buffer);
     }
     
    @@ -2485,13 +2492,13 @@
                    /* what we just removed.                                 */
                    if(Added2Buffer>=SPPLEBufferLength)
                       Added2Buffer -= SPPLEBufferLength;
                 }
     
                 /* Fill up the rest of the buffer with the data string.     */
    -            Added2Buffer     += FillBufferWithString(&(LEContextInfo->SPPLEBufferInfo.TransmitBuffer), &SPPLEBufferLength, MaxLength, SPPLEBuffer);
    +            Added2Buffer     += FillBufferWithString(&(LEContextInfo->SPPLEBufferInfo.TransmitBuffer), &SPPLEBufferLength, MaxLength, SPPLEBuffer, &(LEContextInfo->SPPLEBufferInfo.SendInfo.DataStrIndex));
     
                 /* Reset the Transmit Index to 0.                           */
                 TransmitIndex     = 0;
     
                 /* If we dont have any data to send (i.e.  we didn't have   */
                 /* enough credits to fill up a string) we should just exit  */
    @@ -7459,15 +7466,16 @@
           LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.TransmitCredits      = 0;
     
           /* Flag that no credits are queued.                               */
           LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.QueuedCredits        = 0;
     
           /* Clear the SPPLE Send Information.                              */
    -      LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.SendInfo.BytesToSend = 0;
    -      LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.SendInfo.BytesSent   = 0;
    -      LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.SendInfo.BufferFull  = FALSE;
    +      LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.SendInfo.BytesToSend  = 0;
    +      LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.SendInfo.BytesSent    = 0;
    +      LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.SendInfo.BufferFull   = FALSE;
    +      LEContextInfo[LEConnectionIndex].SPPLEBufferInfo.SendInfo.DataStrIndex = 0;
        }
     }
     
        /* ***************************************************************** */
        /*                         Event Callbacks                           */
        /* ***************************************************************** */