Difference between MTU Size and Data Length for indications/notifications

When I am sending notifications or indications using the Nordic SDK, what do I need to be concerned about, the MTU size or the PDU Data length or both?

I negotiate both with the client (well the client asks for 512 Mtu so I settle on Mtu  of 253). But I negotiate for a data length and get

Data length update: max_rx_octets 27, max_rx_time 328, max_tx_octets 27, max_tx_time 328

I am not sure how these value affect me. I am only concerned about the size of the PDU when I notify or indicate.

Should I use Mtu - overhead or max_tx_octets? I am guessing it is Mtu. However, I am getting an a size error with a packet size of 246 but not of size 111. Maybe I set up the extra room for SoftDevice incorrectly? I am trying to figure out how that was done and I don't recall.

Also it is not clear how to use the method sd_ble_gap_data_length_update

I invoke the method on a connection. I get the BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event. Then I am supposed to respond with sd_ble_gap_data_length_update but that might only be the case if the client initiates the request. How can I tell if the event is from my request or a client-initiated request?

Very confusing!!!! The documentation is not helpful here.

Parents
  • Hi,

    I am not sure how these value affect me. I am only concerned about the size of the PDU when I notify or indicate.

    ATT is at a higher layer than GAP. It is not fundamentally wrong to have an ATT MTU configured to 247 and a GAP data length configured to 27, but this means that large GATT packets will be split across several GAP packets. for maximum throughput/efficiency, and if both peers support it, it would make sense to also increase the AP data length (using data length extension).

    Should I use Mtu - overhead or max_tx_octets? I am guessing it is Mtu. However, I am getting an a size error with a packet size of 246 but not of size 111. Maybe I set up the extra room for SoftDevice incorrectly? I am trying to figure out how that was done and I don't recall.

    If you are making a peripheral I suggest you take a look at the UART/Serial Port Emulation over BLE example for reference on how to use long packets. In the sdk_config.h file it has NRF_SDH_BLE_GAP_DATA_LENGTH set to 251 and NRF_SDH_BLE_GATT_MAX_MTU_SIZE set to 247 (because that would fit in the 251 byte GAP packet).

    Also it is not clear how to use the method sd_ble_gap_data_length_update

    In practice, I would recommend that you let the SDK GATT module handle it for you, as is the case in most examples (including the one I just mentioned).

    I invoke the method on a connection. I get the BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event. Then I am supposed to respond with sd_ble_gap_data_length_update but that might only be the case if the client initiates the request. How can I tell if the event is from my request or a client-initiated request?

    If you are using the GATT module this event is handled by the module, and you can ignore it. If you want do not use the GATT module for some reason (though that would generally mean that you would have to re-implement parts of what the SDK gives you for free, which may not be sensible), then you reply to a BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST with a call to sd_ble_gap_data_length_update(). If you initiate the update you will not get a BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST, but you still use sd_ble_gap_data_length_update() to initiate the update. See the API doc for sd_ble_gap_data_length_update() and the implementation in the GATT module in components/ble/nrf_ble_gatt/nrf_ble_gatt.c for an example of how to do this (though again, I would recommend using what we provide for you instead).

  • There are several reasons I stick with SoftDevice -

    • porting between different versions of SoftDevice across the different platforms (nRF51 and nRF52) is far simpler than with the SDK. The SoftDevice API changes are small, whereas the SDK changes can be unrecognizable.
    • The size of the complied code is much smaller which made use of the free version of the Keil compiler possible on the nRF51 platform
    • I am testing a new BT SIG spec called GHS (Generic Health Sensor) which is a work in progress and there is, of course, no support for this profile in the SDK.
    • The pc-ble-driver ONLY supports SoftDevice and I started all my development there, making a BTLE client test suite for BT-SIG health devices.

    As far as long packets being indicated/notified BT SIG has defined a spec for how to do that when they are longer than the Mtu plus overhead size. It is being used in the GHS. So I am, of course, following that specification in the handling of long packets.

    I found my problem was that I had NRF_SDH_BLE_GATT_MAX_MTU_SIZE set to 253 with a note to make it a multiple of 23. I do not know where that came from. Setting it to 247 solved my error. But I was still unclear as to the difference between the mtu size and the data length.

    I still don't recall how to set the start location and size for SoftDevice in Segger Embedded Studio. The logging tells me what the start address should be and what the size should be when it is wrong. After reducing the mtu size from 253 to 247 I get new start addresses and size values that are smaller than what I had set. However, I don't know how to reset them to the smaller values, so I am wasting some space.

    On the other hand, GHS required that I add a characteristic and when I did so, I got an out of memory error and the characteristic did not get added. I have to make my database larger but I don't know by how much.

Reply
  • There are several reasons I stick with SoftDevice -

    • porting between different versions of SoftDevice across the different platforms (nRF51 and nRF52) is far simpler than with the SDK. The SoftDevice API changes are small, whereas the SDK changes can be unrecognizable.
    • The size of the complied code is much smaller which made use of the free version of the Keil compiler possible on the nRF51 platform
    • I am testing a new BT SIG spec called GHS (Generic Health Sensor) which is a work in progress and there is, of course, no support for this profile in the SDK.
    • The pc-ble-driver ONLY supports SoftDevice and I started all my development there, making a BTLE client test suite for BT-SIG health devices.

    As far as long packets being indicated/notified BT SIG has defined a spec for how to do that when they are longer than the Mtu plus overhead size. It is being used in the GHS. So I am, of course, following that specification in the handling of long packets.

    I found my problem was that I had NRF_SDH_BLE_GATT_MAX_MTU_SIZE set to 253 with a note to make it a multiple of 23. I do not know where that came from. Setting it to 247 solved my error. But I was still unclear as to the difference between the mtu size and the data length.

    I still don't recall how to set the start location and size for SoftDevice in Segger Embedded Studio. The logging tells me what the start address should be and what the size should be when it is wrong. After reducing the mtu size from 253 to 247 I get new start addresses and size values that are smaller than what I had set. However, I don't know how to reset them to the smaller values, so I am wasting some space.

    On the other hand, GHS required that I add a characteristic and when I did so, I got an out of memory error and the characteristic did not get added. I have to make my database larger but I don't know by how much.

Children
  • Hi,

    brianreinhold said:
    between the mtu size and the data length.

    This points to the different layers (the GATT packet size, and the GAP packet size).

    brianreinhold said:
    I still don't recall how to set the start location and size for SoftDevice in Segger Embedded Studio.

    The SoftDevice always starts at 0x1000 (with the MBR starting at 0x0) in flash, and the size is specified in the release notes of the specific SoftDevice version you are using (this includes the MBR page). The application needs to start in the first flash page after the SoftDevice. So for instance. So, for instance, if the SoftDevice sizes is 0x27000, the application start address should be 0x27000. For RAM it is different. The SoftDevice and application RAM cannot overlap, and the SoftDevice use RAM at the bottom of the address space. When the SoftDevice is initialized, it will let you know how much RAM it requires based on the configuration, and you need to ensure that the application RAM start address is at that address or higher (if higher, the RAM in between will never be used). This guide describes how this is handled with the SDK, ans also how to set the addresses in Segger Embedded Studio.

    brianreinhold said:
    After reducing the mtu size from 253 to 247 I get new start addresses and size values that are smaller than what I had set. However, I don't know how to reset them to the smaller values, so I am wasting some space.

    As there is a reduction, you can really just ignore it. It just means that you are wasting the RAM in between, but if your application is not RAM constrained it does not matter. Alternatively, adjust to the new sizes as explained in the guide under Change start addresses in Segger Embedded Studio.

    brianreinhold said:
    On the other hand, GHS required that I add a characteristic and when I did so

    If this is a problem, you may need to increase the attribute table size, and also potentially increase the RAM reserved for the SoftDevice (by increasing the application RAM start address and lowering the size) in the same way as already discussed (and which you will see from the log when you adjust the attribute table size). If you are making a GATT server, and as you are using the SoftDevice directly, that would mean calling sd_ble_cfg_set() with a larger attribute table size. See how the SDK does it for reference (from nrf_sdk_ble.c):

        // Configure the GATTS attribute table.
        memset(&ble_cfg, 0x00, sizeof(ble_cfg));
        ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE;
    
        ret_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, *p_ram_start);
        if (ret_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GATTS_CFG_ATTR_TAB_SIZE.",
                          nrf_strerror_get(ret_code));
        }
    

    where NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE is the table size, which you would adjust. It must be a multiple of 4.

  • I set the table size in sdk_config.h. The problem is I don't know how much extra memory to add. It's hit or miss. Try something and see if I get the error. Not sure what is stored in that table.

  • The attribute table holds everything about all attributes, including the data, but also permissions, handle and type. In practice it does not matter much, just set it large enough. If you need to optimize, the simplest is to do it experimentally to see how low you can set it without getting any out of memory errors.

Related