cancel
Showing results for 
Search instead for 
Did you mean: 

STM BlueNRG-MS Max Characteristic length limited to 255 due to aci_gatt_add_char function limitations.

aj.sk
Associate III

My general understanding is that the BLE standard supports characteristics with a lenght of up to 512 bytes. I'm using the BlueNRG-MS chip from STM but there the function call to add a characteristic has a uint8_t value for the length parameter

tBleStatus aci_gatt_add_char(uint16_t serviceHandle,

uint8_t charUuidType,

const uint8_t* charUuid,

uint8_t charValueLen,

uint8_t charProperties,

uint8_t secPermissions,

uint8_t gattEvtMask,

uint8_t encryKeySize,

uint8_t isVariable,

uint16_t* charHandle);

So this would allow only a maximum characteristic length of 255 bytes. According to this document the stack itself supports 2 bytes with FW 7.2 or higher. I have 7.23 so this should be fine but I cannot find any reference or example of a BlueNRG-MS middleware that would support a call with

charValueLen

of type

uint16_t

. I also downloaded the latest STSW-BLUENRG-DK and the examples also only support

uint8_t charValueLen

.

14 REPLIES 14
Winfred LU
ST Employee

Please manually modify the parameter accordingly.

in bluenrg_gatt_aci.h:

tBleStatus aci_gatt_add_char(uint16_t serviceHandle,
			     uint8_t charUuidType,
			     const uint8_t* charUuid, 
			     uint16_t charValueLen, 
			     uint8_t charProperties,
			     uint8_t secPermissions,
			     uint8_t gattEvtMask,
			     uint8_t encryKeySize,
			     uint8_t isVariable,
			     uint16_t* charHandle);

in bluenrg_gatt_aci.c:

tBleStatus aci_gatt_add_char(uint16_t serviceHandle,
                             uint8_t charUuidType,
                             const uint8_t* charUuid, 
                             uint16_t charValueLen, 
                             uint8_t charProperties,
                             uint8_t secPermissions,
                             uint8_t gattEvtMask,
                             uint8_t encryKeySize,
                             uint8_t isVariable,
                             uint16_t* charHandle)                     
{
  struct hci_request rq;
  gatt_add_serv_rp resp;
  uint8_t buffer[26];
  uint8_t uuid_len;
  uint8_t indx = 0;
  
  serviceHandle = htobs(serviceHandle);
  Osal_MemCpy(buffer + indx, &serviceHandle, 2);
  indx += 2;
  
  buffer[indx] = charUuidType;
  indx++;
  
  if(charUuidType == UUID_TYPE_16){
    uuid_len = 2;
  }
  else {
    uuid_len = 16;
  }        
  Osal_MemCpy(buffer + indx, charUuid, uuid_len);
  indx +=  uuid_len;
  
  charValueLen = htobs(charValueLen);
  Osal_MemCpy(buffer + indx, &charValueLen, 2);
  indx += 2;
  
  buffer[indx] = charProperties;
  indx++;
  
  buffer[indx] = secPermissions;
  indx++;
  
  buffer[indx] = gattEvtMask;
  indx++;
  
  buffer[indx] = encryKeySize;
  indx++;
  
  buffer[indx] = isVariable;
  indx++;
  
  Osal_MemSet(&resp, 0, sizeof(resp));
  
  Osal_MemSet(&rq, 0, sizeof(rq));
  rq.ogf = OGF_VENDOR_CMD;
  rq.ocf = OCF_GATT_ADD_CHAR;
  rq.cparam = (void *)buffer;
  rq.clen = indx;
  rq.rparam = &resp;
  rq.rlen = GATT_ADD_CHAR_RP_SIZE;
  
  if (hci_send_req(&rq, FALSE) < 0)
    return BLE_STATUS_TIMEOUT;
  
  if (resp.status) {
    return resp.status;
  }
  
  *charHandle = btohs(resp.handle);
  
  return 0;
}

aj.sk
Associate III

Thanks, I'll give it a try! I assume the same modification applies for aci_gatt_update_char_value()?

What confuses me a bit though is that if this is the fix, then I assume the buffer content would have been incorrect so far right? Or does it distinguish between buffer of size 25 and size 26 to determine whether I have 1 or 2 byte charValueLen?

I did the modification but when I do

ret = aci_gatt_add_char(serviceHandle, UUID_TYPE_128, uuid, 470, CHAR_PROP_READ, ATTR_PERMISSION_NONE,  GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP, 16, 0 , &charHandle);

I get return value 0x1F, so it fails to add the characteristic.

Did I miss something? What is the origin of this Osal_MemSet? My code uses BLUENRG_memcpy instead, is that a problem?

0x1F would be out of memory.

Please check the the "Max_Attribute_Records" value in your previous call to aci_gatt_add_serv().

aj.sk
Associate III

Thanks for your reply. That was my initial thought as well, but I already have it set to 30 with only 2 characteristics added. If I reduce the size of the characteristic to 250, it works. Any other idea how to fix that? Regarding the "max_attribute_records", is there a clarification how to get the number of attributes of a service?

A characteristic needs at least 2 attributes (1 for declaration and 1 for value).

It requires 1 additional attribute if the characteristic has the Notify (/Indicate) property, and 1 additional attribute for each descriptor.

In your service, normally the number of attributes you are going to need = 1 for service + 2 for *2 characteristics = 5 attributes

If you only need 1 connection in the application, please use "MODE 2" for the stack, as it reserves more memory (700 bytes) for characteristics records array size.

Please modify IFR to change the mode.

aj.sk
Associate III

But as it works with characteristic size of 250 I assume it's not an issue with the "max_attribute_records"? Any other Idea how I can troubleshoot this? This is a rather urgent project and I either need to solve this issue or reduce my characteristic size - I prefer the first one... :)

>But as it works with characteristic size of 250 I assume it's not an issue with the "max_attribute_records"?

No. I was just clarifying the minimum requirement on the number of attributes parameter. And it looks you've configured a number more than enough.

>I either need to solve this issue or reduce my characteristic size - I prefer the first one

Your customized service and characteristics consume memory = 4 + (4 + 250) + (4 + 250) = 512 bytes (in case of no descriptors)

This seems to be a reasonable limit for stack MODE4, which reserves 590 bytes the characteristics records array.

You will need to configure the stack to MODE2 instead to have a larger memory for your characteristics.

Please modify IFR.

Release Notes for BlueNRG, BlueNRG-MS Stacks:

file:///C:/Program%20Files%20(x86)/STMicroelectronics/BlueNRG%20DK%202.0.2/Docs/bluenrg_fw_stack_release_notes_html/_blue_n_r_g-_m_s__stack_v7_2_c.html

https://www.st.com/resource/en/user_manual/dm00164925-the-bluenrg-and-bluenrg-ms-information-register-ifr-stmicroelectronics.pdf

aj.sk
Associate III

Actually the IFR is already set to MODE2