Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE5 - Make payload size 200 bytes - the right way

Hello,

I try to configure two nrf52832 devices work with payload of 200 bytes (data should be 200 bytes, not the all ble packet).

I took ble_app_uart_c peripheral and central examples - for 20 bytes everything looks ok.

After that, I tried to understand and implement in my code the ble_app_att_mtu_throughput example, but without luck.

Where can I find the exact algorithm for the increasing the payload size?

My algorithm now:

Common definitions:

NRF_SDH_BLE_GATT_MAX_MTU_SIZE             defined for 247 bytes (in sdk_config.h)

BLE_GATT_ATT_MTU_DEFAULT                         defined to 204 bytes (in ble_gatt.h)

Central:

in function ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) - the function handles all BLE events

- in event BLE_GAP_EVT_PHY_UPDATE_REQUEST

-- I define the 2MBPS speed:

ble_gap_phys_t const phys =
 {
       .rx_phys = BLE_GAP_PHY_2MBPS,
       .tx_phys = BLE_GAP_PHY_2MBPS,
};
sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);

in function gatt_init() - the function initiates the gatt library

- nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);

- nrf_ble_gatt_att_mtu_central_set(&m_gatt, BLE_GATT_ATT_MTU_DEFAULT); //to 204 bytes

in function data_len_ext_set() - the function should set the new MTU size. the function placed in main() function, after all initializations, but before scan_start() call

- nrf_ble_gatt_data_length_set(&m_gatt, BLE_CONN_HANDLE_INVALID, 200 + L2CAP_HDR_LEN);  - according to example. 200 - needed payload, L2CAP_HDR_LEN - defined as 4

in function conn_evt_len_ext_set() - not sure, but looks that the function enables length increasing option in the stack, called just after the data_len_ext_set() function

- memset(&opt, 0x00, sizeof(opt));
- opt.common_opt.conn_evt_ext.enable = 1;
- sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);

Peripheral

in ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) - the function handles all BLE events

- I define the 2MBPS speed:

ble_gap_phys_t const phys =
 {
       .rx_phys = BLE_GAP_PHY_2MBPS,
       .tx_phys = BLE_GAP_PHY_2MBPS,
};

- in event BLE_GAP_EVT_CONNECTED

-- sd_ble_gap_phy_update(p_gap_evt->conn_handle, &phys); //request for 2MBPS

- in event BLE_GAP_EVT_PHY_UPDATE_REQUEST

-- sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);

- in event BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST

-- memset(&dl_params, 0, sizeof(ble_gap_data_length_params_t));

-- sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dl_params, NULL);

in function gatt_init() - the function initiates the gatt library

- nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);

- nrf_ble_gatt_att_mtu_periph_set(&m_gatt, BLE_GATT_ATT_MTU_DEFAULT); //to 204 bytes

in function data_len_ext_set() - the function should set the new MTU size. the function placed in main() function, after all initializations, but before ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); call

- nrf_ble_gatt_data_length_set(&m_gatt, BLE_CONN_HANDLE_INVALID, 200 + L2CAP_HDR_LEN);  - according to example. 200 - needed payload, L2CAP_HDR_LEN - defined as 4

in function conn_evt_len_ext_set() - not sure, but looks that the function enables length increasing option in the stack, called just after the data_len_ext_set() function

- memset(&opt, 0x00, sizeof(opt));
- opt.common_opt.conn_evt_ext.enable = 1;
- sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);

So, is it looks ok? Some mistakes that you could point me on? Something is missing?

Thanks a lot!

  • It is used already when peripheral is setting up the GATT database in one of the BLE modules, you should find it by searching for 'sd_ble_gatts_characteristic_add' throught the project.

  • Difficult to do first time, but easy to implement once it's working; looking at a diff between SDK14.2.0 and my code I see the minimum changes required below, note pretty much as kenneth describes in his post as only gatt_init() length change is required, if I remember. I also include a graphic I wrote to clarify the packet format. Note using SDv5.1.0 and both central and Peripheral use same SDK version and SD. Some deices - eg older iPhone - will of course not allow a packet size increase, hence the addition of the trace.

    // |<-------------------------------------------- Slave -> Master Data Packet -------------------------------------->|
    // |                                                                                                                 |
    // +-----------------------------------------------------------------------------------------------------------------+
    // |                                            BLE Data Packet Min/Max                                              |
    // +-----------------------------------------------------------------------------------------------------------------+
    // |                                         1MHz: 10/265 octets, 2MHz: 11/266 octets                                |
    // +----------+--------+--------------------------------------------------------------------------------------+------+
    // |          | Access |                                                                                      |      |
    // | Preamble | Address|         Protocol Data Unit PDU                                                       | CRCC |
    // +----------+--------+--------------------------------------------------------------------------------------+------+
    // |   1 (2)  |    4   |                                                   2-257                              |  3   |
    // |          |        +-----------+------------------------------------------------------------------+-------+      |
    // |          |        | LL Header |  Payload                                                         |  MIC  |      |
    // |          |        +-----------+------------------------------------------------------------------+ (opt) |      |
    // |          |        |   2       |                                       0-251                      |   4   |      |
    // |          |        |           +--------+---------------------------------------------------------+       |      |
    // |          |        |           | L2CAP  |                                                         |       |      |
    // |          |        |           | Header |  ATT Data                                               |       |      |
    // |          |        |           +--------+---------------------------------------------------------+       |      |
    // |          |        |           |   4    |                              0-247                      |       |      |
    // |          |        |           |        +-----+-------+-------------------------------------------+       |      |
    // |          |        |           |        | ATT | ATT   |                                           |       |      |
    // |          |        |           |        | Op  | Attrib|  ATT Payload                              |       |      |
    // |          |        |           |        +-----+-------+-------------------------------------------+       |      |
    // |  1 (2)   |   4    |  2        |   4    |  1  |  2    |                0-244                      |  (4)  |  3   |
    // +----------+--------+-----------+--------+-----+-------+-------------------------------------------+-------+------+
    //                                                        |                                           |
    //                                                        |<------ Actual Payload 0-244 bytes ------->|
    //
    //
    // Preamble is 1 byte for LE 1MHz (BLE 4.2) and 2 bytes for 2MHz (BLE 5.0). If the first bit of the ADDRESS is 0 the preamble
    // will be 0xAA otherwise 0x55.
    // The MIC field is optional used when we are using an encrypted connection
    
    /**@brief Function for handling events from the GATT library. */
    void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    {
        if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
        {
            m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
            NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    
            {
                char     InfoPacket[120];
                // Report
                snprintf(InfoPacket, sizeof(InfoPacket), "\r\nData len is set to 0x%X(%d)\r\n", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
                SendViaHardwareUart(InfoPacket);
            }
        }
        NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
                      p_gatt->att_mtu_desired_central,
                      p_gatt->att_mtu_desired_periph);
    }
    
    /**@brief Function for initializing the GATT library. */
    void gatt_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
        APP_ERROR_CHECK(err_code);
    }
    
    
    

  • Hello,

    Thank you for your answer!

    When I'm increasing the NRF_SDH_BLE_GAP_EVENT_LENGTH to 5 or more I get a NRF_ERROR_NO_MEM at nrf_sdh_ble_enable function (please see the attached image)

    How I should to increase the memory?

    Error in the J-Link RTT Viewer

  • Hello,

    Thank you for your answer! Slight smile

    When I do it, as I wrote to Kenneth, I get the limitation of 101 bytes (please, see one of the comments above)

  • Presuming you are using Keil you can for instance open 'Options for Target' and modify the IRAM1 Start and Size required by the softdevice, if you enable logging you should be able to find the recommended settings for both parameters in nrf_sdh_ble_enable().

Related