strange packet loss with ESS service

Hello,

I need your help to understand better why I see packet loss even on the bench.

I have two Telit BlueMod+S50 chips (based on nRF52382) as central and peripheral. The peripheral uses a custom firmware based on SDK v17.1.0, with SoftDevice S132; the central is running a pre-compiled firmware provided by Telit itself

The peripheral every 50 ms collects data from an ADC and an accelerometer, creates a frame of 47 bytes and stored it in an application queue; then it tries to send as much packets as possible from the queue to SoftDevice, until sd_ble_gatts_hvx() returns an error or no resource available. packets are sent as Notifications

The main MCU talks with the central via AT interface based on UART. The data are passed from the central to the main MCU as serial LENOTI messages .

ideally every 50ms a packet is created and sent immediately, so I have a rate of 1 packet/50ms. in reality on the field packets can't be sent out immediately, due to interferences the central is not acknowledging immediately the Notifications, so the rate is much lower, hence the need to store packets in the queue.

on the bench I have modified the firmware so it first saves 50 packets in the queue and then tries to send as much packets as possible on each 50ms connection. in this way I can see that for each connection around 13-15 packets are sent until the queue is empty.

the problem is, on the main MCU, every 30 packets (LENOTI messages received) there are 3-4 packets lost (LENOTI messages without any payload).

the interesting thing is that if I manually limit the transmission to maximum 3 packets per connection , no packet is lost!

this makes me thing that it could be a configuration issue and some packets are actually discarded and not transmitted.

these are my configuration settings:

 

#define APP_ADV_INTERVAL 400 

#define APP_ADV_DURATION 0

#define GATT_QUEUE_MAX_SIZE 4

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(45, UNIT_1_25_MS) 


#define MAX_CONN_INTERVAL MSEC_TO_UNITS(50, UNIT_1_25_MS) 

#define SLAVE_LATENCY 3 


#define CONN_SUP_TIMEOUT BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX


#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) 


#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) 


#define MAX_CONN_PARAMS_UPDATE_COUNT 9 

the function which is sending packets is the follow:

#define OPCODE_LENGTH 1 
#define HANDLE_LENGTH 2 
#define MAX_TPM_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH)

#define CC_TPM_FRAME_LENGTH 47


uint32_t ble_ess_temperature_measurement_send(ble_ess_t * p_ess, uint8_t *temperature)
{
    uint32_t err_code;

    // Send value if connected and notifying
    if (p_ess->conn_handle != BLE_CONN_HANDLE_INVALID)
    {
        uint8_t                encoded_tpm[MAX_TPM_LEN];
        uint16_t               len;
        uint16_t               hvx_len;
        ble_gatts_hvx_params_t hvx_params;

        len     = CC_TPM_FRAME_LENGTH;
        hvx_len = len;

        memset(&hvx_params, 0, sizeof(hvx_params));

        hvx_params.handle = p_ess->tpm_handles.value_handle;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset = 0;
        hvx_params.p_len  = &hvx_len;
        hvx_params.p_data = temperature;

        err_code = sd_ble_gatts_hvx(p_ess->conn_handle, &hvx_params);
        if ((err_code == NRF_SUCCESS) && (hvx_len != len))
        {
            err_code = NRF_ERROR_DATA_SIZE;
        }
    }
    else
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }

    return err_code;
}

on startup these messages are displayed:

debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
<debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
<info> tm_ble: Connected
<debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 158 bytes.
<debug> nrf_ble_gatt: Updating ATT MTU to 158 bytes (desired: 247) on connection 0x0.
<debug> nrf_ble_gatt: ATT MTU updated to 158 bytes on connection 0x0 (response).
<info> tm_ble: GATT ATT MTU on connection 0x0 changed to 158.
<debug> nrf_ble_gatt: Data length updated to 162 on connection 0x0.
<debug> nrf_ble_gatt: max_rx_octets: 162
<debug> nrf_ble_gatt: max_tx_octets: 162
<debug> nrf_ble_gatt: max_rx_time: 1408
<debug> nrf_ble_gatt: max_tx_time: 1408

can you please help me understand why I'm losing packet and how to change configuration settings in order to achieve the transmission of the maximum number of packets per connection?

Parents
  • Hello,

    Notification packets should not become lost as long as they are successfully added to the Softevice's output queue (i.e. when sd_ble_gatts_hvx() returns NRF_SUCCESS). 

    on the bench I have modified the firmware so it first saves 50 packets in the queue and then tries to send as much packets as possible on each 50ms connection. in this way I can see that for each connection around 13-15 packets are sent until the queue is empty.

    Could you please try queueing these packets in the Softdevice instead of the application? You can increase the Softdevice's internal HVN queue through the sd_ble_cfg_set() API.

    e.g.,

    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
        
        
        // Increase HVN Queue size in Softdevice
        ble_cfg_t ble_cfg;
    
        memset(&ble_cfg, 0, sizeof(ble_cfg));
        ble_cfg.conn_cfg.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
        ble_cfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = 30; // Number of packets in queue
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);
        ...

    Best regards,

    Vidar

  • Hi Vidar,

    I have increased the hvn_queue_size but it didn't work.

    I have asked Telit about the configuration of the central and this is their response:

    BLE modules as the MTU Size of 158. The ATT layer has 1 byte opcode and 2 bytes ATT handle overload , hence the actual application payload will be ATTMTUMAX-(1+2). So the actual payload will be 155. With the 2M phy rate, the notification is 4 times with the data transfer of 20 bytes per notification

    so if I have a payload of 47 byte, how many notifications I can send in a 50ms interval?

  • Hi,

    RoccoBr said:
    I have increased the hvn_queue_size but it didn't work.

    Did you remove the queueing in the app as well, or did you only increase the HVN queue of the Softdevice?

    RoccoBr said:
    so if I have a payload of 47 byte, how many notifications I can send in a 50ms interval?

    To calculate the theoretical number of notifications you can send per connection, I need to know the precise connection parameters for the link. Additionally, please note that the overall link quality will impact the actual results you achieve.

    However, the problem here is that you get some packets without any payload. This points to an issue with the buffer handling in the application. 

  • hi Vidar,

    I'm still using the queue in the app because one of my requirement is to start reading sensor values (and create frames) as soon as the peripheral wakes up and I can't send the frames to the SoftDevice queue until the central has connected and enabled Notifications.

    As application buffer I'm using the nrf_queue:

    typedef struct
    {
      uint8_t elem[47];
    } frame_t;
    
    NRF_QUEUE_DEF(frame_t, m_byte_queue, 200, NRF_QUEUE_MODE_OVERFLOW); 
    NRF_QUEUE_INTERFACE_DEC(frame_t, app_queue);
    NRF_QUEUE_INTERFACE_DEF(frame_t, app_queue, &m_byte_queue)

    one of the field of my frame_t struct is the frame_id. for debug purpose I'm checking that when I pop a frame from the queue and sending it to SoftDevice, the frame_id field has the expected sequence

    To calculate the theoretical number of notifications you can send per connection, I need to know the precise connection parameters for the link

    #define APP_ADV_INTERVAL 400 //64                            /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
    
    #define APP_ADV_DURATION 0 //18000                           /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    
    #define GATT_QUEUE_MAX_SIZE 30
    
    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(45, UNIT_1_25_MS) 
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(50, UNIT_1_25_MS) 
    #define SLAVE_LATENCY 3                                   
    #define CONN_SUP_TIMEOUT BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX 
    #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) 
    #define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) 
    #define MAX_CONN_PARAMS_UPDATE_COUNT 9   

    phy is set to BLE_GAP_PHY_2MBPS

    MTU size is 158

  • Hi,

    RoccoBr said:
    I'm still using the queue in the app because one of my requirement is to start reading sensor values (and create frames) as soon as the peripheral wakes up and I can't send the frames to the SoftDevice queue until the central has connected and enabled Notifications.

    I see, that makes sense. 

    RoccoBr said:
    one of the field of my frame_t struct is the frame_id. for debug purpose I'm checking that when I pop a frame from the queue and sending it to SoftDevice, the frame_id field has the expected sequence

    Can you also add a check to see if the payload data and length is correct? 

    RoccoBr said:

    phy is set to BLE_GAP_PHY_2MBPS

    MTU size is 158

    The actual connection parameters are negotiated between the central and peripheral after the connection is established, and we don't know what the RADIO packet length is here. You can use the nRF Sniffer for Bluetooth LE to see how many packets are sent per connection event if you have an extra nRF52840 Dongle or DK laying around.

  • hi Vidar.

    I have created a static dummy frame that is transmitted instead of the frame from the nrf_queue and I still have empty packets in reception.

    I will set up the sniffer using the DK that I have  

  • Hi,

    I will set up the sniffer using the DK that I have  

    Is this one of the new ones where the nRF5340 is used as the interface chip (i.e. Jlink programmer)? Reason for asking is that there is an issue with the J-link FW used on this chip that prevents it from being used with the nRF Sniffer plug-in.

     WireShark Error with BLE Sniffer at nRF52DK (PCA10040 v3.0.0) - Could not find interface, FIFO does not exist  

Reply Children
Related