You are here

Problems with BLE notifications | Cypress Semiconductor

Problems with BLE notifications

Summary: 9 Replies, Latest post by Oliver Zabel on 23 Dec 2016 04:40 AM PST
Verified Answers: 0
Last post
Log in to post new comments.
Suresh Joshi's picture
User
14 posts

Hi all, I've been trying to get BLE notifications working correctly on the PROC, but I keep running into issues (perhaps they are related?)

1) I'm using an iOS app called LightBlue as my BLE client interface (I've used this for a year or two on dozens of BLE projects from other vendors, with no problems - so I think the app is solid). When I 'listen for notifications', and then perform an action which should send a notification from the PROC to the phone, I ALWAYS get 2 identical notifications. However, nowhere in my code am I sending the same notification twice (I've printf'd the hell outta my code and manually debugged). 

Is there something in ProcessEvents, or elsewhere that I should be looking for potential causes?

 

2) I'm trying to send multiple notifications in a row, however, I get a crash which pushes the PROC into the exception handler infinite loop (I should be able to send 4-6 per connection interval, but at this point, I don't care about performance, I just don't want a crash). It crashes after the very first notification.

Here is the code which causes it (ble_Run gets called every iteration of the main.c loop, fakesync_data is just a uint8 pointer to a few hundred data points - static data, so it's not disappearing off the stack):

void ble_Run(void)
{
    if (mIsSynching)
    {
        if(CyBle_GattGetBusStatus() == CYBLE_STACK_STATE_FREE && remainingPackets > 0)
        {
            ble_SendNotification(CYBLE_DATA_SYNC_DATA_CHAR_HANDLE, fakesync_data(), 20);
            --remainingPackets;
        }
        if (remainingPackets <= 0) // Reset the test
        {
            mIsSynching = 0;
            remainingPackets = 20;
        }
    }
    CyBle_ProcessEvents();
}

void ble_SendNotification(CYBLE_GATT_DB_ATTR_HANDLE_T characteristic,
                          uint8* data, uint16 length)
{
    CYBLE_GATTS_HANDLE_VALUE_NTF_T notification;
    notification.value.val  = data;
    notification.value.len  = length;
    notification.attrHandle = characteristic;
    if (CyBle_GattsNotification(cyBle_connHandle, &notification) != CYBLE_ERROR_OK) 
    {
        PRINT("ERROR sending notification\r\n");
    }    
    //CyBle_ProcessEvents();
}

 

Thanks!

Suresh Joshi's picture
User
14 posts

Also, I added a CyDelay(15) right before I send the notification, and that seems to help. The problem is, depending on the amount of data I want to send (which I don't know at compile time), the delay needs to be different to stop the crash (sometimes works with 10ms, sometimes 15, sometimes more - and I'm sure it also depends on the connection interval and the mobile phone I'm communicating with, so this isn't a solution). 

This is pretty brutal, so I'm hoping I'm doing something wrong. My hope was that checking for the busy state of the BLE would be enough (note: I changed the above from CyBle_GattGetBusStatus to CyBle_GattGetBusyStatus - still no difference).  Also, it's a straight crash, I don't even make it into the api error block.

jrow's picture
Cypress Employee
123 posts

Hi Suresh,

This appears to be very similar to an issue I encountered a little while ago. Assuming you are using PSoC Creator 3.3 CP2 and BLE component v3.10, there is an internal memory corruption issue that appears in some cases due to an improperly bounded memcpy() call. This issue has been fixed and will be included in the next BLE component update (should be v3.20).

As a workaround, you can modify one line in BLE_Stack.h (in /Generated_Source/PSoC4) from this:

#define CYBLE_MEM_EXT_SZ    (0x08u)

...to this:

#define CYBLE_MEM_EXT_SZ    (0x10u)

This provides enough padding in the pre-allocated stack buffers that the error condition should not occur even without proper bounding on the memcpy() call. It will slightly increase SRAM usage.

Note that this workaround requires modifying auto-generated code. Therefore, you will need to re-apply the modification any time you change the TopDesign schematic or clean the build environment since these operations cause all of that code to be regenerated.

Suresh Joshi's picture
User
14 posts

Thanks Jeff, unfortunately, 0x10 didn't work - problems 1 and 2 still occur on my system.

However, what I did do is take it a step crazier and make it (0x20u) instead, and problem #2 (the crash) seems to go away with my sample test set (only about 20 notifications of 20 bytes). I don't know how it's being used under the hood, but maybe allocating 16 bytes wasn't enough?

Do you have an ETA on when the next component will be released? Also, any thoughts on problem number 1? I was hoping it might be caused by the same problem, but I think only I am running into it (even though my notification code is only called once).

Thanks!

 

jrow's picture
Cypress Employee
123 posts

That's curious about the larger required memory increase in your case.

I don't know the specific release schedule for the next component version, but it should be pretty soon since it's going through final validation testing now.

Concerning the double-notification problem, I've never observed that behavior before. I assume you've tried with other apps (or ideally other platforms) on the client side to make sure it happens in all cases? I'd expect that it does since LightBlue is pretty well vetted at this point, as you stated. It would be good to confirm if you haven't, though.

Your code doesn't immediately jump out as broken. What happens if you remove all loops/error checks and use exactly one API call to CyBle_GattsNotification?

Suresh Joshi's picture
User
14 posts

I have a bit of a working theory here that I need to test. I think the problem specifically happens when I notify directly after sending an ack to a write_with_response. 

When I just do an 'out of the blue' notification, there is no problem. However, specifically when I notify after also sending a response ack, I notice the problem. However, without the write_ack, everything hangs and disconnects. Do I need a ProcessEvents() between?

        case CYBLE_DATA_SYNC_CONTROL_CHAR_HANDLE:
            CyBle_GattsWriteRsp(cyBle_connHandle);
            ble_SendNotification(...);
            break;

jrow's picture
Cypress Employee
123 posts

My understanding is that another call to CyBle_ProcessEvents() shouldn't be necessary, but it's possible that it is either by design or otherwise. Have you tried it to see the result?

It's possible that the BLE stack is internally writing or somehow overwriting the payload portion of the write ack packet with notification data, resulting in duplicate transmissions. A BLE sniffer would show more in this case, even something as simple as the old TI CC2540 dongle and BLE Sniffer tool (assuming your connection is not encrypted).

Suresh Joshi's picture
User
14 posts

I tested my theory, but it was a no-go. Adding/removing ProcessEvents doesn't do anything. What's interesting is that this seems to happen about 60ms apart (my connection interval range is 7.5-30ms talking to iOS)

user_459156114's picture
User
35 posts

Were you ever able to fix this? 

Oliver Zabel's picture
User
4 posts

Hi, 

i have exactly the same issue. Double notifications on charactersistics where properties set to WRITE and NOTIFY.

Is there meanwhile a solution or at least are reference to an existing bug?

I'm using the creator 4.0 with ble comp. 3.20.

Oli

 

EDIT: I get also notification, if i'm not sending any. Just write to a characteristic with WRITE and NOTIFY (without read) and i get a notification. Content is from the last notification. On first write content is empty.

Log in to post new comments.