Cy_BLE_GATTS_WriteAttributeValuePeer on a CYBLE-416045-02

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
SuMa_296631
Level 5
Level 5
50 replies posted 25 replies posted 10 replies posted

I am using PSoC Creator 4.2 to write a BLE application for a CYBLE-416045-02 and the basics are all working very well.

Of the 3 custom services I have, one is a readable/writable 32-character UTFS8 string. The initial value set in the component is a null string.

As the app starts up, it looks to the EEPROM to read the name that has been given to the system previously and if none has been set, it creates a default name of 'No Given Name' which is 13 character long. I use the Cy_BLE_GATTS_WriteAttributeValueLocal() function to set the name.

When this is read by the client, it is a 32-character value that is null-padded after the actual string.

When I write to the service with (say) 'Test Lamp' I can see the 'handleValPair' structure has the new value and the 'len' parameter is 9 (which is correct).

I then use the Cy_BLE_GATTS_WriteAttributeValuePeer() function to write the value to the local database (and I also update the EEPROM).

However when I then read the service value, what I get is 'Test LampName'.

When I look at the full string sent to the client, it is the same ASCII character null terminated.

If I reboot the code, it will then correctly read 'Test Lamp' form the EEPROM and sets the value in the local GATTS database accordingly.

What do I have to do to save the name to the local database with the correct length (other than rebooting!)?

The code I use is:

  case CY_BLE_EVT_GATTS_WRITE_REQ:

       writeReqParameter = (cy_stc_ble_gatts_write_cmd_req_param_t*)eventParam;

       if( CY_BLE_LOCATION_SETTING_CHAR_HANDLE ==

                 writeReqParameter->handleValPair.attrHandle)

       {

            tLocalName newLocalName;

            memset( &newLocalName, 0, sizeof( tLocalName));

            memset( newLocalName.localName, ' ', sizeof( newLocalName.localName));

            newLocalName.nameLength = writeReqParameter->handleValPair.value.len & 0xff;

            memcpy(newLocalName.localName, writeReqParameter->handleValPair.value.val,

            writeReqParameter->handleValPair.value.len & 0xff);

            // Save to the EEPROM for the next reboot

            EEPROM_Write(0, &newLocalName,sizeof(tLocalName));

           

            // Save to the local GATTS database

            writeReqParameter->handleValPair.value.val = newLocalName.localName;

            Cy_BLE_GATTS_WriteAttributeValuePeer(&writeReqParameter->connHandle,

                           &writeReqParameter->handleValPair);

       }

       Cy_BLE_GATTS_WriteRsp(writeReqParameter->connHandle);

  break;

You can see there my attempts to space-pad the name and also repoint the string pointer. (It doesn't mater if I don't do this and leave the 'val' pointer pointing to whatever it originally was.)

Susan

0 Likes
2 Replies
VenkataD_41
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi Susan,

I guess you are using Emulated EEPROM which is implemented in Flash. Flash writes happen in row wise. When you initiate a Flash write request the entire row of flash gets erased and the new values will be written. That is the reason you are getting the exact value of name when you reset the device.

The GATT database (characteristics) is stored in RAM. So when you are writing to GATT database we recommend you to erase completely and write new value just like how Flashwrite happens.

Thanks

Ganesh

@MichaelF_56 - can you please stop marking responses to my questions as 'helpful'. I think you have done this to every single response I have received in all of my questions.

In this case I have not yet tried the suggested answer, but on the face of it, it seems as though it is exposing a logical flaw. The struct that holds the pointer to the new value (string or whatever) also contains the length of the value. It sounds like the length for a string is not being saved as the value is being written to the database.

If that is the case then what is the point of passing in the length of the value (string) and why is there no documentation to say that a string in the GATT database MUST always be written with the full length?

Susan

0 Likes