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

How to interpret first 8 bytes of ble_l2cap_evt_t.rx.data (SDK v11 SD130 v2)

Hello

I'm trying to track lost packets in a connection by showing the sequence number of each packet received. Specifically it's about an application that sends new measurements in 3 packets each connection interval. Some measurements are divided over 2 packets so if a packet is lost, it is very important that the central application is aware of this. I think the sequence number is somewhere inside the ble_l2cap_evt_t.rx.data array of a received notification event but I'm not getting what I would expect. The code below tries to illustrate what I mean. Inside the for loop I print the first 7 bytes of the array. The rest of the data array gives the real payload (as expected):

static void on_hvx(ble_nus_c_t * p_ble_nus_c, const ble_evt_t * p_ble_evt)
{
// HVX can only occur from client sending.
if ( (p_ble_nus_c->handles.nus_rx_handle != BLE_GATT_HANDLE_INVALID)
        &&(p_ble_evt->evt.gattc_evt.params.hvx.handle==p_ble_nus_c->handles.nus_rx_handle)
        && (p_ble_nus_c->evt_handler != NULL)
    )
  {
    //After index 7 you get data payload
    for (int8_t i = 0; i < 8; i++)
    {
				
				printf("%d\t",p_ble_evt->evt.l2cap_evt.params.rx.data[i]);
    }
			ble_nus_c_evt_t ble_nus_c_evt;

    ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_RX_EVT;
    ble_nus_c_evt.p_data   = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
    ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;

    p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
  }
}

But I see that those first 7 bytes are always the same for all packets... So I guess the sequence number is not in there. My question is, if it is in there, how should I interpret it? And if it's not (what most likely will be the case) how can I get the sequence number out of a received notification event related to a received packet (or is this not possible?) ?

Kind regards

Mathias

EDIT 1 Picture of sniffing receiving side + sniffing file

image description

image description

Sniffing file

EDIT 2 Including of code files

I put together some code files with parts of my code, representing what you asked. The first two are peripheral code, the other one is central code.

This one contains the method that handles the measures made and puts them ready to send. It also contains the method of my custom service and characteristic that handles the real sending of a notification. Sending of packets with measurements.cpp

This one contains the method that handles an ACTIVE & NACTIVE, where on the end of each radio event, the measuring and setting data ready to send is started again (which is already done before the following radio event starts, this is already validated through GPIO testing). Initialising the sending of measurements each interval.cpp

This one contains the event handler where also the notifications are handled. There the printing of the notifications is showcased. Receiving notifications and printing them.cpp

EDIT 3 Including of sniff

The sniff is made using Perytons protocol analyzer. I already tried see that sometimes an err packet is sniffed (instead of a normal packet). If I check the order for the packet before and after this red packet, there should be a packet in between there so there's a packet missing there. But this could (and will be probably be) the sniffer's fault. Petter.anlb

  • That data is only valid if you get a BLE_L2CAP_EVT* event, seems like you are getting a BLE_GATTC_EVT* event.

    The L2CAP frame is not made available when BLE_GATT* and BLE_GAP* events are received.

    You shouldn't lose any packets, BLE is a reliable protocol, it will retransmit packet until supervision timeout is hit and the link is disconnected. So I think you should look for the culprit somewhere else.

    How are you sending the packets? Are you checking the returned error code of sd_ble_gatts_hvx()? Is it always returning NRF_SUCCESS?

  • I'm sending the packets continuously which consist of sending 3 packets with NRF_SUCCESS and the sending of a 4th giving a buffer overflow, ensuring that on the next interval the same process will be repeated (sending of 3 packets and trying of a 4th). Each time the sending completes (on TX_COMPLETE) the peripheral does measures again and sends them to the central. In 99 % of the time I see on central side (via toggling of GPIO pins) that three packets are received in one interval. But sometimes only 2, 1 or even none are received. Apart from full measurements, most packets also contain parts of measurement, divided over two packets. That's why the receiving order is very important to me. I thought it had something to do with lost packets but I've been looking into other options as well now. On peripheral side there are no delays to my knowledge to the sending that could delay the receiving of a full three packet interval on central side.

    The peripheral is configured with HIGH tx and rx bandwidth while the central is configured with MID tx and rx bandwidth (hence the three packets per interval). I first tried my implementation with 6 packets per interval and thus a HIGH bw also on central side but that didn't work because of memory constraints on central side...

    Do you maybe have any idea what is going on here?

    Thanks, Mathias

  • I also thought that notifications are not ACK and thus not resend? Am I wrong this assumption?

  • What kind of memory constraints? You probably just have to modify how much RAM is reserved for the SoftDevice. Inside softdevice_enable() you can see what application RAM base and size should be set to.

    The receiving order should be the same as the transmit order. I'm not sure why you sometimes you only receive 2, 1 or none, maybe the central device have full buffers? And it can't receive until you have handled some more events? It is a bit difficult to say without a sniffer trace. What are you doing on the central side when you receive a notification? You could do a test where you just discard the packets, to see if that helps (just as a test).

    The notifications are acked at the link level, but they are not acked at the application level (like indications)

  • Sorry for the late reply, I was home on Friday.

    I'm printing out the results. I thought this maybe had something to do with it so I only printed out the first measure in each packet instead (which is much less processing work). But this also gave the same problem that suddenly the printed out measures aren't in the order they should be (not each packets starts with x-axis measurements, sometimes it's a z-axis measurement. x should be close to 0 while z should be close to 1. Normally the receiving order should be: x x z x x z ... for each first measurement in a packet. But suddenly it become x z x or z x x or ... instead of x x z which means that the order of the packets is not as it is at sending side. I already debugged the sending order and their everything is normal ( x x z x x z ...). I sniffed the receiving side as you requested and added the sniff to my original question.

Related