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

Loss of notifications when sending them from peripheral to central as bulk transfer

Hi,

I have read this thread Notification_Loss but could not understand my problem.

On peripheral side, I am making sure that error events are properly handled while doing the bulk transfer. Please see my code below:

uint32_t temp_data_burst_xfer(uint32_t* read_buffer_temp)
{
	 static uint8_t cnt = 0;			//Counting the chunks transfered 
   uint32_t        err_code;
	
	while (cnt < TTL_CHUNKS_TEMP && burst_xfer_process)
  {
			  cnt++;		// Next 20 byte block to send
        err_code =  Burst_characteristic_update(&m_our_service, read_buffer_temp, cnt);		//Sending 20 bytes [cnt represents which block]
				if (err_code == BLE_ERROR_NO_TX_PACKETS ||
            err_code == NRF_ERROR_INVALID_STATE || 
            err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING)
        {
					if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING)		//Special handling of BLE_ERROR_GATTS_SYS_ATTR_MISSING
					{
							 SEGGER_RTT_printf(0,"\n\r***  BLE_ERROR_GATTS_SYS_ATTR_MISSING ***\n\r");
					}
					else if(err_code == NRF_ERROR_INVALID_STATE)
					{
							SEGGER_RTT_printf(0,"Burst transfer halted due to error NRF_ERROR_INVALID_STATE \n\r");
					}
				break;
        }
				else if (err_code != NRF_SUCCESS) 
        {
						SEGGER_RTT_printf (0, "\r\n Error # 0x%x in 'mag_data_burst_xfer'\r\n",err_code);
            APP_ERROR_HANDLER(err_code);											//Unhandled
        }
	}
	if(cnt == TTL_CHUNKS_TEMP)
	{
		burst_xfer_process=0;			//Burst transfer stopped
		cnt = 0 ;									//Reset for next record transfer
		return NRF_SUCCESS;
	}
}

Where TTL_CHUNKS_TEMP == 25. So I am sending 25 notifications. I have verified that peripheral completes the process without any error (otherwise the peripheral would stop at APP_ERR_HANDLER).

However on server side, I receive only 15 or sometimes 10 notifications, please see the log below:

Connecting to our Service UUID 101
 0> Connection request sent to SenseaFlash	 
 0> our Service UUID Find Status = 0
 0> try to find Sensea_Tag service on conn_handle 0x0
 0> BLE DB Discovery just started
 0> 
 0> *** Notification process started ***
 0> [0] = 0x1A 	[1] = 0x1A 	[2] = 0x1A 	[3] = 0x1B 	[4] = 0x1B 	
 0> *** Burst = 0 ***
 0> [5] = 0x1C 	[6] = 0x1D 	[7] = 0x1D 	[8] = 0x1D 	[9] = 0x1E 	
 0> *** Burst = 1 ***
 0> [10] = 0x1E 	[11] = 0x1F 	[12] = 0x1F 	[13] = 0x1F 	[14] = 0x1E 	
 0> *** Burst = 2 ***
 0> [15] = 0x1E 	[16] = 0x1E 	[17] = 0x1E 	[18] = 0x1D 	[19] = 0x1D 	
 0> *** Burst = 3 ***
 0> [20] = 0x1D 	[21] = 0x1D 	[22] = 0x1D 	[23] = 0x1D 	[24] = 0x1D 	
 0> *** Burst = 4 ***
 0> [25] = 0x1D 	[26] = 0x1D 	[27] = 0x1D 	[28] = 0x1C 	[29] = 0x1D 	
 0> *** Burst = 5 ***
 0> [30] = 0x1D 	[31] = 0x1D 	[32] = 0x1E 	[33] = 0x1E 	[34] = 0x20 	
 0> *** Burst = 6 ***
 0> [35] = 0x23 	[36] = 0x25 	[37] = 0x25 	[38] = 0x26 	[39] = 0x26 	
 0> *** Burst = 7 ***
 0> [40] = 0x29 	[41] = 0x29 	[42] = 0x29 	[43] = 0x27 	[44] = 0x28 	
 0> *** Burst = 8 ***
 0> [45] = 0x26 	[46] = 0x26 	[47] = 0x26 	[48] = 0x25 	[49] = 0x25 	
 0> *** Burst = 9 ***
 0> [50] = 0x25 	[51] = 0x24 	[52] = 0x26 	[53] = 0x27 	[54] = 0x28 	
 0> *** Burst = 10 ***
 0> [55] = 0x2C 	[56] = 0x2C 	[57] = 0x2C 	[58] = 0x2B 	[59] = 0x2D 	
 0> *** Burst = 11 ***
 0> [60] = 0x30 	[61] = 0x30 	[62] = 0x30 	[63] = 0x30 	[64] = 0x2F 	
 0> *** Burst = 12 ***
 0> [65] = 0x2D 	[66] = 0x2D 	[67] = 0x2D 	[68] = 0x2C 	[69] = 0x2C 	
 0> *** Burst = 13 ***
 0> [70] = 0x2B 	[71] = 0x2B 	[72] = 0x2B 	[73] = 0x2B 	[74] = 0x2B 	
 0> *** Burst = 14 ***
 0> [75] = 0xFF 	[76] = 0xFF 	[77] = 0xFF 	[78] = 0xFF 	[79] = 0xFF 	
 0> *** EOD detected at notif # 15 *** 

Can anyone help me figuring out why I am not receiving the full no. of notifications?

I know there is ACK on link layer, is not that working? OR there is any overflow in the receiver (central)?

Please help.

  • Hello,

    My guess is that your Burst_characteristic_update() returns BLE_ERROR_NO_TX_PACKETS() meaning your buffer is full. When it returns this, it also means that the softdevice didn't queue the packet that returned this. 

    I see that you just filter out this return value. I bet that if you add the extra check like you do with BLE_ERROR_GATTS_SYS_ATTR_MISSING and NRF_ERROR_INVALID_STATE, you will see that it is printed.

    since you increase your counter, cnt++ regardless if Burst_characteristic_update() returns NRF_SUCCESS or BLE_ERROR_NO_TX_PACKETS, these packets are never sent.

    I suggest that you increase the count only if err_code == NRF_SUCCESS.

    Something like this:

    uint32_t temp_data_burst_xfer(uint32_t* read_buffer_temp)
    {
    	 static uint8_t cnt = 0;			//Counting the chunks transfered 
       uint32_t        err_code;
    	
    	while (cnt < TTL_CHUNKS_TEMP && burst_xfer_process)
      {
    			  //cnt++;		// Next 20 byte block to send
            err_code =  Burst_characteristic_update(&m_our_service, read_buffer_temp, cnt);		//Sending 20 bytes [cnt represents which block]
    				if (err_code == BLE_ERROR_NO_TX_PACKETS ||
                err_code == NRF_ERROR_INVALID_STATE || 
                err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING)
            {
                        if(err_code == NRF_SUCCESS)
                        {
                            cnt++;  // <-- add this
                        }
    					else if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING)		//Special handling of BLE_ERROR_GATTS_SYS_ATTR_MISSING
    					{
    							 SEGGER_RTT_printf(0,"\n\r***  BLE_ERROR_GATTS_SYS_ATTR_MISSING ***\n\r");
    					}
    					else if(err_code == NRF_ERROR_INVALID_STATE)
    					{
    							SEGGER_RTT_printf(0,"Burst transfer halted due to error NRF_ERROR_INVALID_STATE \n\r");
    					}
    					else if(err_code == BLE_ERROR_NO_TX_PACKETS)
    					{
    					        SEGGER_RTT_printf(0,"BLE_ERROR_NO_TX_PACKETS. Don't increase cnt++");
    					}
    				break;
            }
    				else if (err_code != NRF_SUCCESS) 
            {
    						SEGGER_RTT_printf (0, "\r\n Error # 0x%x in 'mag_data_burst_xfer'\r\n",err_code);
                APP_ERROR_HANDLER(err_code);											//Unhandled
            }
    	}
    	if(cnt == TTL_CHUNKS_TEMP)
    	{
    		burst_xfer_process=0;			//Burst transfer stopped
    		cnt = 0 ;									//Reset for next record transfer
    		return NRF_SUCCESS;
    	}
    }

    I also noted that you increment your counter before you start sending. I believe this means that you skip your first measurement.

    If you receive BLE_ERROR_NO_TX_PACKETS, and you want to save some battery, you can, instead of just keep trying to send until it receives NRF_SUCCESS, wait until you receive the BLE_GATTS_EVT_HVN_TX_COMPLETE event, and then continue sending notifications after this. This is described in the sd_ble_gatts_hvx() softdevice call.

    Best regards,

    Edvin

  • Oh, what an obvious mistake I made.

    Thanks Edvin for the correction. The issue has been resolved with the following implementation of the code.

    uint32_t temp_data_burst_xfer(uint32_t* read_buffer_temp)
    {
    	 static uint8_t cnt = 0;			//Counting the chunks transfered 
       uint32_t        err_code;
    	
    	while (cnt < TTL_CHUNKS_TEMP && burst_xfer_process)
      {
            err_code =  Burst_characteristic_update(&m_our_service, read_buffer_temp, cnt);		//Sending 20 bytes [cnt represents which block]
    				if(err_code == NRF_SUCCESS)
    				{
    					cnt++;
    				}
    				else if (err_code == BLE_ERROR_NO_TX_PACKETS ||
                err_code == NRF_ERROR_INVALID_STATE || 
                err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING)
            {
    					if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING)		//Special handling of BLE_ERROR_GATTS_SYS_ATTR_MISSING
    					{
    							 SEGGER_RTT_printf(0,"\n\r***  BLE_ERROR_GATTS_SYS_ATTR_MISSING ***\n\r");
    					}
    					else if(err_code == NRF_ERROR_INVALID_STATE)
    					{
    							SEGGER_RTT_printf(0,"NRF_ERROR_INVALID_STATE \n\r");
    					}
    					else if (err_code == NRF_ERROR_INVALID_STATE)
    					{
    							SEGGER_RTT_printf(0,"BLE_ERROR_NO_TX_PACKETS\n\r");
    					}
    					break;
            }
    				else if (err_code != NRF_SUCCESS) 
            {
    						SEGGER_RTT_printf (0, "\r\n Error # 0x%x in 'mag_data_burst_xfer'\r\n",err_code);
                APP_ERROR_HANDLER(err_code);											//Unhandled
            }
    	}
    	if(cnt == TTL_CHUNKS_TEMP)
    	{
    		burst_xfer_process=0;			//Burst transfer stopped
    		cnt = 0 ;									//Reset for next record transfer
    		return NRF_SUCCESS;
    	}
    }
    

Related