Changing the Client MTU size with C# API with CY5677

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

cross mob
lock attach
Attachments are accessible only for community members.
MuNa_4652896
Level 4
Level 4
First like received First like given

Hi again.

I have been testing the connection between both the Dongle and the Psoc 6 Kit. It seems I am only limited to send 20 bytes per notification packet. I am guessing this is an MTU limitation on the dongle side. How shall I raise the Client MTU to the maximum? Do I need to Exchange MTU? or can I adjust it directly via code?

This is the part in the C# code where I receive the notification packet and check its byte contents

/ Setup the characteristic changed handler

                        GATTClientEventCallback.CharacteristicChangedHandler = (NotifyEventParam) =>

                        {

                            //All Notification Values are retrieved from here

                            if (NotificationText.InvokeRequired)

                            {

                                Invoke((MethodInvoker) (() =>

                                {

                                    string[] notificationArray = new string[20];  //<===== 20 bytes per notification packet

                                    for (int i = 0; i < notificationArray.Length; i++)

                                    {

                                        notificationArray = NotifyEventParam.Value.ToString("X");

                                    }

                                    NotificationText.Text = NotifyEventParam.Value[19].ToString("X") + NotifyEventParam.Value[0].ToString("X");

                                    //var dateTime = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss",

                                    //        CultureInfo.InvariantCulture);

                                    //    notificationArray[0] = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss",

                                    //        CultureInfo.InvariantCulture);

                                    //Dump Data to file

                                    File.AppendAllLines(path + fileName, notificationArray, Encoding.UTF8);

                                }));

                            }

                            else

                            {

                                //NotificationText.Text = NotifyEventParam.Value[1].ToString() + NotifyEventParam.Value[0].ToString();

                            }

                        };

On the C code on the kit

I define the size here

#define TICK_ARRAY_SIZE       (20)

Fill dummy data here, then call updateTickValue function

    for (int i = 0; i < TICK_ARRAY_SIZE ; i++)

    {

        timerTick += 1;

    }

    updateTickValue();

Then Send the notification here:

void updateTickValue()

{

    cy_stc_ble_gatt_handle_value_pair_t handleValuePair;

    handleValuePair.attrHandle = CY_BLE_LEDSERV_LEDPWM_CHAR_HANDLE;

    handleValuePair.value.val = timerTick;

    handleValuePair.value.len = TICK_ARRAY_SIZE ;

    Cy_BLE_GATTS_WriteAttributeValueLocal(&handleValuePair);

   

    if (notify == 1)

    {

        Cy_BLE_GATTS_SendNotification(&cy_ble_connHandle[0], &handleValuePair);

        printf("Notification Tick Value Sent: %d - %d\r\n", timerTick[TICK_ARRAY_SIZE  - 1], timerTick[0]);

    }

}

pastedImage_8.png

1: I need help to exchange MTU with the kit on C# Application to negotiate for the maximum MTU possible. MTU exchange is already present on the kit. I checked it with CySmart App on PC and it is able to negotiate on 512 bytes MTU. So how do I use CyGattExchangeMtuInfo and CyGattExchangeMtuResult to exchange and display the exchange results?

2. Setting "Clock" at high speeds like 400 KHz for the counter timer freezes the notifications after a while, and the kit needs to be restarted again. Why is this happening?

3. Another side issue, but it is not important at the meantime for while, the GUI freezes when I disable the notifications. Is it something related to threading?

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
DheerajK_81
Moderator
Moderator
Moderator
First comment on KBA First comment on blog 5 questions asked

I have been testing the connection between both the Dongle and the Psoc 6 Kit. It seems I am only limited to send 20 bytes per notification packet. I am guessing this is an MTU limitation on the dongle side. How shall I raise the Client MTU to the maximum? Do I need to Exchange MTU? or can I adjust it directly via code?

Yes, if no MTU exchange is done, the default MTU size of 23 bytes is taken and thus 20 bytes of data is continuously sent. You need to negotiate the MTU size for more size which is explained in the next question.

1: I need help to exchange MTU with the kit on C# Application to negotiate for the maximum MTU possible. MTU exchange is already present on the kit. I checked it with CySmart App on PC and it is able to negotiate on 512 bytes MTU. So how do I use CyGattExchangeMtuInfo and CyGattExchangeMtuResult to exchange and display the exchange results?

After the connection is established you can negotiate the MTU size by calling the following APIs.

CyGattExchangeMtuInfo gattMTUSize = new CyGattExchangeMtuInfo(512);

                        GattClient.ExchangeMtu(gattMTUSize);

Once the negoatiation is complete, you can check the result of this negotiation using the OnGattMtuExchanged callback function. Add this override function to the GattClientCb function you have defined in the following manner:

public override void OnGattMtuExchanged(CyGattExchangeMtuResult result, CyStatus status)

{

        MessageBox.Show("Gatt MTU Exchange Status :" + result.GattMtuRequested + " " + result.NegotiatedGattMtu + " " + status.ToString());

}

I have attached the modified code for reference.

2. Setting "Clock" at high speeds like 400 KHz for the counter timer freezes the notifications after a while, and the kit needs to be restarted again. Why is this happening?

Currently I see that you have set the clock to be 200KHz in your PSoC Creator project. This means that the clock is running at 5us. You have set the period count to be 999. This means you have the terminal count interrupt being generated every 999*5us (~5ms). And you are sending this timer value via BLE every 5ms. I'm not sure about your application, but from what I see, I think you want to plot some data over a period of time. Such high speeds will definitely cause your application to hang. 400Khz is only going to make this worse. I would recommend making use of Timer class in C# itself that you can attach to the data when you receive it instead of doing this from PSoC side.

You might need to see how much granularity you need and set your time according to that. In your PSoC Creator code, make sure you check if the stack is free before sending the next data by adding this line of code:

if(Cy_BLE_GATT_GetBusyStatus(handleValuePair.attrHandle) == CY_BLE_STACK_STATE_FREE)

{

        Cy_BLE_GATTS_SendNotification(&cy_ble_connHandle[0], &handleValuePair);

        printf("Notification Tick Value Sent: %d - %d\r\n", timerTick[TICK_ARRAY_SIZE  - 1], timerTick[0]);

}

3. Another side issue, but it is not important at the meantime for while, the GUI freezes when I disable the notifications. Is it something related to threading?

This is not an issue because of threading but the high data rates. Check this code example for more information on throughput measurement: https://www.cypress.com/documentation/code-examples/ce222046-psoc-6-mcu-bluetooth-low-energy-ble-con...

Regards,

Dheeraj

View solution in original post

0 Likes
5 Replies
lock attach
Attachments are accessible only for community members.
DheerajK_81
Moderator
Moderator
Moderator
First comment on KBA First comment on blog 5 questions asked

I have been testing the connection between both the Dongle and the Psoc 6 Kit. It seems I am only limited to send 20 bytes per notification packet. I am guessing this is an MTU limitation on the dongle side. How shall I raise the Client MTU to the maximum? Do I need to Exchange MTU? or can I adjust it directly via code?

Yes, if no MTU exchange is done, the default MTU size of 23 bytes is taken and thus 20 bytes of data is continuously sent. You need to negotiate the MTU size for more size which is explained in the next question.

1: I need help to exchange MTU with the kit on C# Application to negotiate for the maximum MTU possible. MTU exchange is already present on the kit. I checked it with CySmart App on PC and it is able to negotiate on 512 bytes MTU. So how do I use CyGattExchangeMtuInfo and CyGattExchangeMtuResult to exchange and display the exchange results?

After the connection is established you can negotiate the MTU size by calling the following APIs.

CyGattExchangeMtuInfo gattMTUSize = new CyGattExchangeMtuInfo(512);

                        GattClient.ExchangeMtu(gattMTUSize);

Once the negoatiation is complete, you can check the result of this negotiation using the OnGattMtuExchanged callback function. Add this override function to the GattClientCb function you have defined in the following manner:

public override void OnGattMtuExchanged(CyGattExchangeMtuResult result, CyStatus status)

{

        MessageBox.Show("Gatt MTU Exchange Status :" + result.GattMtuRequested + " " + result.NegotiatedGattMtu + " " + status.ToString());

}

I have attached the modified code for reference.

2. Setting "Clock" at high speeds like 400 KHz for the counter timer freezes the notifications after a while, and the kit needs to be restarted again. Why is this happening?

Currently I see that you have set the clock to be 200KHz in your PSoC Creator project. This means that the clock is running at 5us. You have set the period count to be 999. This means you have the terminal count interrupt being generated every 999*5us (~5ms). And you are sending this timer value via BLE every 5ms. I'm not sure about your application, but from what I see, I think you want to plot some data over a period of time. Such high speeds will definitely cause your application to hang. 400Khz is only going to make this worse. I would recommend making use of Timer class in C# itself that you can attach to the data when you receive it instead of doing this from PSoC side.

You might need to see how much granularity you need and set your time according to that. In your PSoC Creator code, make sure you check if the stack is free before sending the next data by adding this line of code:

if(Cy_BLE_GATT_GetBusyStatus(handleValuePair.attrHandle) == CY_BLE_STACK_STATE_FREE)

{

        Cy_BLE_GATTS_SendNotification(&cy_ble_connHandle[0], &handleValuePair);

        printf("Notification Tick Value Sent: %d - %d\r\n", timerTick[TICK_ARRAY_SIZE  - 1], timerTick[0]);

}

3. Another side issue, but it is not important at the meantime for while, the GUI freezes when I disable the notifications. Is it something related to threading?

This is not an issue because of threading but the high data rates. Check this code example for more information on throughput measurement: https://www.cypress.com/documentation/code-examples/ce222046-psoc-6-mcu-bluetooth-low-energy-ble-con...

Regards,

Dheeraj

0 Likes

I would to offer my thanks and appreciation for your support regarding the C# API. You have been of great help to me regarding it, since its documentation and examples are really scarce.

Currently I see that you have set the clock to be 200KHz in your PSoC Creator project. This means that the clock is running at 5us. You have set the period count to be 999. This means you have the terminal count interrupt being generated every 999*5us (~5ms). And you are sending this timer value via BLE every 5ms. I'm not sure about your application, but from what I see, I think you want to plot some data over a period of time. Such high speeds will definitely cause your application to hang. 400Khz is only going to make this worse. I would recommend making use of Timer class in C# itself that you can attach to the data when you receive it instead of doing this from PSoC side.

Good Guess regarding plotting data, but not only that, I want to plot them on the C# A;pp on demand to monitor it.. I have a device which samples data at a certain speed in KHz. When it samples at 32 KHz, it generates 32,000 reading / sec. Each reading is 2 bytes, thus I have 64,000 bytes, which is ~64KB, to be sent over BLE per second. From what I understand, BLE can reach speeds up to 700 kbps using BLE 4.2. This means it can reach speeds of up to 87.5 KBytes / sec, which is more than enough to send the data. What is the right approach to send all of this data over BLE without causing this previous behavior?

if(Cy_BLE_GATT_GetBusyStatus(handleValuePair.attrHandle) == CY_BLE_STACK_STATE_FREE) 

        Cy_BLE_GATTS_SendNotification(&cy_ble_connHandle[0], &handleValuePair); 

        printf("Notification Tick Value Sent: %d - %d\r\n", timerTick[TICK_ARRAY_SIZE  - 1], timerTick[0]); 

}

else

{

        printf("FULL STACK\r\n");

}

I have added an else condition for this part to see if the problem is because of the stack being fully taken, but the error was not printed even once when the freeze occurs. If I have been sending 20 bytes at a speed of 400Khz which is 400 notification packet / sec at the CM0 Core speed of 100MHz, this is yielding 8KBytes / sec of data. Alternatively after the MTU exchange is fixed, I decided to use an MTU of 400 bytes at 160Khz clock speed. Therefore, 400 x 160 = 64,000 =~ 64KBytes / sec (ignoring all the headers being sent too in the way),. What am I doing wrong here?

0 Likes

You have been of great help to me regarding it, since its documentation and examples are really scarce.

I agree. We will try to put out more collateral on the usages of the APIs. Thank you for your feedback.

What is the right approach to send all of this data over BLE without causing this previous behavior?

The reason your GUI freezes is probably because you are operating on the main UI thread directly when the data arrives. You can try using worker threads to offload any kind of processing in the background and only update the UI once the processing is complete. Background Worker class in C# might be useful here. Regarding BLE throughput on the PSoC side, I see you have a discussion ongoing already on this thread, so skipping that here.

I have added an else condition for this part to see if the problem is because of the stack being fully taken, but the error was not printed even once when the freeze occurs. What am I doing wrong here?

This indicates that the BLE is able send the data effeciently. The issue seems to be on the host side trying to handle the received data. Let me know if using the background worker thread can mitigate this problem. Here's a simple example you can refer for the implementation.

Regards,

Dheeraj

0 Likes

Thanks @DheerajK_81 ​for your reply

I have edited the code, when I was using the Timer at 160Khz with 460 MTU BLE size, The BLE becomes unresponsive, causing BLE Full Stack error without anyway to get out of it except resetting the kit.

The reason your GUI freezes is probably because you are operating on the main UI thread directly when the data arrives. You can try using worker threads to offload any kind of processing in the background and only update the UI once the processing is complete. Background Worker class in C# might be useful here. Regarding BLE throughput on the PSoC side, I see you have a discussion ongoing already on this thread, so skipping that here.

Regarding that part, I will deal with it later. Background Workers might deal with it. Regarding the BLE throughput, I am no longer going to discuss it their, since it is not relevant to my application anymore. So, I decided to remove the Timer and follow the same approach as the GATTOut example provided, however, I am now dealing with Busy Stack Issue, which means placing the Notification Sending in a for loop is being processed faster than freeing the BLE Stack. I have read the following:

3. To increase the BLE Stack's default queue depth(CY_BLE_L2CAP_STACK_Q_DEPTH_PER_CONN) and achieve better throughput for the attribute MTU greater than 32, use the AddQdepthPerConn parameter in the 'Expression View' of the Advanced tab in the BLE component GUI. To Access the 'Expression View', right click on the 'Advanced' tab in the BLE Component GUI and select the 'Show Expression Vew' option.

Where is that AddQdepthPerConn Parameter located? I have incread CY_BLE_L2CAP_STACK_Q_DEPTH_PER_CONN up to 60 but I am not gaining any noticeable performance.

0 Likes

Hello,

1. Where is that AddQdepthPerConn Parameter located?
Ans: In the PSoC Creator, Go to Tools ->Options ->Design Entry ->Component Catalog and Enable Param Edit Views. In the BLE component, right click on the 'Advanced' tab and select the 'Show Expression Vew' option to get the AddQdepthPerConn Parameter.

2. I have incread CY_BLE_L2CAP_STACK_Q_DEPTH_PER_CONN up to 60 but I am not gaining any noticeable performance.
Ans: Make sure that Cy_BLE_ProcessEvents() is called at regular intervals in the firmware. This function checks the internal task queue in the BLE Stack, and pending operation of the BLE Stack, if any. This must be called at least once every connection interval or Adv interval, whichever is smaller.

Please let me know if this helps.

Thanks,
P Yugandhar.

0 Likes