This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF51822 Disconnects when enabling notification for the 4th time.

Hello,

I am developing a simple app for nRF51822 which sends notification data to a characteristic with a random value. All seems to work good but while testing in-depth and searching for bugs, I found something I am not able to explain and fix.

While connected to the peripheral with and Android device (5.0.2) and nRF Master Control Panel app, I search for my characteristic and I enable notifications. It sends/recieves properly. Then I disable the notifications. And repeat the process 4 times.

At the 4th time, when I enable the notification, I do not receive any notification and after a few seconds, the peripheral disconnects with a GATT error.

Is there any kind of internal limitation for enabling/disabling notifications for the chip? What am I missing?

This is the notifications callback I use:

uint32_t value_change(ble_NOTIF_t * p_lbs, uint8_t * mData)
{
	uint32_t err_code = NRF_SUCCESS;

    uint16_t len = 6;

    err_code = sd_ble_gatts_value_set(p_lbs->notif_handles.value_handle,
                                      0,
                                      &len,
                                      mData);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    if(isNotifyEnable == 0x01)
			{
        ble_gatts_hvx_params_t hvx_params;
        memset(&hvx_params, 0, sizeof(hvx_params));					
        hvx_params.handle = p_lbs->notif_handles.value_handle;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset = 0;
        hvx_params.p_len  = &len;
        hvx_params.p_data = mData;

        err_code = sd_ble_gatts_hvx(p_lbs->conn_handle, &hvx_params);
    }
    else
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }
return err_code;
}

Where mData is a 6 bytes array with the random value.

The notifications is triggered by a timer every second.

The disconnection error is:

nRF Master Control Panel, 2015-05-18
No name (F3:F7:E9:5F:66:07)
V	08:53:00.758	Connecting to F3:F7:E9:5F:66:07...
D	08:53:00.767	gatt = device.connectGatt(autoConnect = false)
D	08:53:16.540	[Callback] Connection state changed with status: 0 and new state: 2 (CONNECTED)
I	08:53:16.565	Connected to F3:F7:E9:5F:66:07
...
V	08:53:50.198	Enabling notifications for 00000003-0000-1000-8000-00805f9b34fb
D	08:53:50.214	gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
I	08:53:50.319	Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
A	08:53:50.332	"Notifications enabled" sent
V	08:53:50.360	Notifications enabled for 00000003-0000-1000-8000-00805f9b34fb
I	08:53:51.294	Notification received from 00000003-0000-1000-8000-00805f9b34fb, value: (0x) 80-FF-00-00-80-1E
...
V	08:53:52.846	Disabling notifications for 00000003-0000-1000-8000-00805f9b34fb
D	08:53:52.867	gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x00-00)
I	08:53:52.952	Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 00-00
A	08:53:52.967	"Notifications and indications disabled" sent
V	08:53:52.999	Notifications and indications disabled for 00000003-0000-1000-8000-00805f9b34fb
 ... x3
V	08:54:05.765	Enabling notifications for 00000003-0000-1000-8000-00805f9b34fb
D	08:54:05.782	gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
E	08:54:25.833	Error (0x85): GATT ERROR
D	08:54:25.874	[Callback] Connection state changed with status: 8 and new state: 0 (DISCONNECTED)
E	08:54:25.891	Error (0x8): GATT INSUF AUTHORIZATION
D	08:54:25.910	gatt.refresh()

I also got this error with another device for the same situation:

V	14:05:28.239	Enabling notifications for 00000003-0000-1000-8000-00805f9b34fb 
D	14:05:28.255	gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00) 
E	14:05:35.309	Error (0x85): GATT ERROR 
D	14:05:35.339	[Callback] Connection state changed with status: 0 and new state: 0 (DISCONNECTED) 
I	14:05:35.365	Disconnected

EDIT:

I call the notification in the timer handler like:

void timer_handler(void * p_context)
{
    uint32_t err_code;
    err_code = value_change(&p_lbs, mData);
        if (err_code != NRF_SUCCESS && err_code != BLE_ERROR_INVALID_CONN_HANDLE && err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }
}

And as you can see it handles the error code with the default APP_ERROR_CHECK. Maybe I should let it handle also the BLE_ERROR_INVALID_CONN_HANDLE and NRF_ERROR_INVALID_STATE with APP_ERROR_CHECK also?

I try to record a sniffer trace and as soon as I have it I post it here.

Thanks in advance for your help!

Best regards,

margabro.

Parents
  • Finally I managed to solve the problem myself. Maybe it will be not usefull for others but I post it anyway.

    The problem was the timer. Due to my low experience with firmware and nRF51288, I was creating a new timer every time I was enabling the notifications. After the 4th time, there was not enough space in the memory to create another timer so it kicked the connection.

    I managed to solve it with a simple flag in the timer creation:

    bool timerCreated = false;
    
    void mTimer() 
    {
       uint32_t err_code=0;				
    
       if(!timerCreated){
    		err_code = app_timer_create(&mTimer, APP_TIMER_MODE_REPEATED, mTimer_handler);
    		
    		if (err_code != NRF_SUCCESS)
    		{
               APP_ERROR_CHECK(err_code);
    		}
    		timerCreated = true;
        }
    
            timerStarted=true;
            err_code = app_timer_start(mTimer, (float)(((float)notif_period/(float)1000)*(float)256) ,NULL); //5940000, NULL);
    		if (err_code != NRF_SUCCESS)
            {
                APP_ERROR_CHECK(err_code);
            }
    }
    
Reply
  • Finally I managed to solve the problem myself. Maybe it will be not usefull for others but I post it anyway.

    The problem was the timer. Due to my low experience with firmware and nRF51288, I was creating a new timer every time I was enabling the notifications. After the 4th time, there was not enough space in the memory to create another timer so it kicked the connection.

    I managed to solve it with a simple flag in the timer creation:

    bool timerCreated = false;
    
    void mTimer() 
    {
       uint32_t err_code=0;				
    
       if(!timerCreated){
    		err_code = app_timer_create(&mTimer, APP_TIMER_MODE_REPEATED, mTimer_handler);
    		
    		if (err_code != NRF_SUCCESS)
    		{
               APP_ERROR_CHECK(err_code);
    		}
    		timerCreated = true;
        }
    
            timerStarted=true;
            err_code = app_timer_start(mTimer, (float)(((float)notif_period/(float)1000)*(float)256) ,NULL); //5940000, NULL);
    		if (err_code != NRF_SUCCESS)
            {
                APP_ERROR_CHECK(err_code);
            }
    }
    
Children
No Data
Related