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!

  • Hello,

    You should basically only need to add gatt_init() and this will be automatically handled for you, something like:

    void nrf_ble_gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    {
    	if(p_evt->evt_id == NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED)
    	{
    		// p_evt->params.data_length is the max length on-air
    	}	
    	if(p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)
    	{
    		// p_evt->params.att_mtu_effective is the max attribute mtu size		
    	}	
    	
    	// Once both are updated, then you can start sending data that is longer than 20bytes effectively.
        // Though you should also make sure attr_char_value.max_len is set to 
        // more than 20bytes when calling sd_ble_gatts_characteristic_add().
    }
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, nrf_ble_gatt_evt_handler);
        APP_ERROR_CHECK(err_code);
    }

  • Hello Kenneth,

    I don't understand where I can define that the payload data in the packet should be 200 bytes.

    In addition I cannot understand where I should use the sd_ble_gatts_characteristic_add function? My code is based on ble_app_uart example and I don't see usage of this function.

    Thnaks a lot!

  • I try to extend the MTU size and get the next prints:

    : Trying to set length
    
    -max_rx_octest: 251
    
    -max_tx_octets: 251
    
    sd_ble_gap_data_length_update() (request) on connection 0x0 returned unexpected value 0x13.
    
    Error NRF_ERROR_RESOURCES
    
    -tx_payload_limited_octets: 101
    
    -rx_payload_limited_octets: 101

    What is payload? Is it L2CAP+OpCode+AttributeHandle+AttPayload or just AttPayload?

    Why the payload is limited to 101 bytes?

  • In path of {Infocenter}/nRF52 Series/SoftDevices/S132 SoftDevice/S132 SoftDevice API/S132 SoftDevice 5.0.0.0 API/API Reference/Generic Access Profile (GAP)/Message Sequence Charts/Data Length Update Procedure - we can find the diagram where explained how to perform the data length update (do you really think that this length of the path it is ok?).

    We can see APP, SD and PEER - I have two NRF52 DK boards - one is central, the second is peripheral - in this case what is APP, what is SD and what is PEER?

    Thanks!

  • You will likely need to adjust NRF_SDH_BLE_GAP_EVENT_LENGTH = 5 (or more) to allow longer packets, because this will reserve more time for the radio event. I expect '101' message you get to be the max with NRF_SDH_BLE_GAP_EVENT_LENGTH = 3.  Also, with max octets = 251 the max used by the application is 247, the remaining 4 is L2CAP header.

    APP +  SD is the local firmware running on the nRF52832, while PEER is whoever is on the other side of the connection.

Related