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.

LAUNCHXL-CC26X2R1: Packed Structure over BLE Characteristic

Part Number: LAUNCHXL-CC26X2R1


Hi Folks,

You know that feeling when you go to a different room to get something and come back only to realize you didn't get all the things you should have gotten? Well, my problem is not so different. I am working from a Simple Peripheral SDK 5.10 project and I have nine (9) characteristics that are all uint16_ts. I can happily read and write to these values without any problems. However, it seems kind of strange to use nine characteristics (nine separate trips) when the only time I might access any of the nine values I would also want to see the other eight. I have developed a solution that ostensibly should work but I am probably missing something very obvious since it doesn't work.

It begins with a dense data structure to minimize the memory footprint and avoid fragmentation. This is done partially also because I erroneously thought BLE was still limited to 20 byte packets, but since I am only sending (9*2) 16 Bytes of Data it doesn't matter.  I have developed two approaches for storage, neither work, but I certainly prefer the structure over the array since assigning dataPacked_A.data1 or dataPacked_A ->data1 is more easily read than a hard coded or defined index.

// Dense way to store related information A
typedef struct __attribute__((__packed__)) {
    uint16_t data1;
    uint16_t data2;
    uint16_t data3;
    uint16_t data4;
    uint16_t data5;
    uint16_t data6;
    uint16_t data7;
    uint16_t data8;
    uint16_t data9;
} dataPacked_A;

// Dense way to store related information B
uint16_t dataPacked_B[9];

Next, I developed a method that gets this data into my Simple Peripheral Thread and passes a typecast pointer to the address of the data structure/array::

// Function in Simple_Peripheral.c
void BLE_Set_Data(dataPacked_A value){
    dataService_SetParameter(DATACHAR, DATACHAR_LEN, (uint8_t *)&value);
}

Finally, the data arrives in ti_ble_gatt_Service.c where it can be assigned to the appropriate memory location:

bStatus_t dataService_SetParameter( uint8 param, uint8 len, void *value )
{
  bStatus_t ret = SUCCESS;
  switch ( param )
  {

  case DATASERVICE_CHAR:
    if ( len == sizeof ( DATASERVICE_CHAR_LEN ) )
    {
      memcpy(dataChar, value, len);
    }
    else
    {
      ret = bleInvalidRange;
    }
    break;
    
  default:
    ret = INVALIDPARAMETER;
    break;
    
  }
  return ret;
}

Here is characteristic is for reference:

// Characteristic defines
#define DATASERVICE_CHAR   29
#define DATASERVICE_CHAR_UUID 0x21E
#define DATASERVICE_CHAR_LEN  18

...

// Characteristic "dataChar" Value variable
uint8 DataServiceChar[DATASERVICE_CHAR_LEN] = { 0x0 };

The code correctly populates the values and brings them as far as the Simple Peripheral thread. However, memcpy consistently is skilled while debugging and it would appear that it doesn't like the (void *) value argument which doesn't make sense considering that this is how I assign every other value.

I have clean built this, written functions to copy the value back and forth and transform it, but in the end it always seems to get caught in dataService_setParameter. 

Any and all suggestions are welcome.

Best,

Ken

  • I should probably acknowledge that my “packed” struct is not guaranteed to be organized in any way. Frankly, an array is the programmatically better choice, but the problem stands.

    - Ken

  • Hi Ken,

    I have assigned an expert to look into this. Does the program get stuck in memcpy or does it continue executing afterwards? Where specifically in the setParameter function does the program get stuck?

    Best Regards,

    Jan

  • Hi Jan,

    It seems to just skip the memcpy expression completely. When breakpoints are set on the "If...", "memcpy...", and "else..." only the If statement is caught. The other two are not triggered. Breakpoints on other memcpy methods here all trigger their breakpoints so it appears to only be this one.

    Best,

    Ken

  • Hi Ken,

    It looks like the if condition is not correct. "len == sizeof ( DATASERVICE_CHAR_LEN )" should be replaced by "len == DATASERVICE_CHAR_LEN".

    As a side note, I am not sure the value the expression "sizeof ( DATASERVICE_CHAR_LEN )" has and I am pretty sure it would be compiler dependent. In other words I do not recommend using this type of syntax.

    I hope this will help,

    Kind regards,

  • Oh man. That is definitely egg on my face. I also discovered my ReadCB function for this service didn't provide the UUID for this case and instead provided just the index.

    Thank you for finding this bug - I lost too much time ignoring the basics.