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

Incomplete Data at write to peripheral with ATT_MTU=247 and DATA_LENGTH=251

SDK 15.2, S132 6.1, nRF52832

I have a characteristics to write data to a peripheral, using variable length up to 507 bytes and authorization.

Writing to the peripheral works fine with ATT_MTU=23 and DATA_LENGTH=27

When I establish a connection with ATT_MTU=247 and DATA_LENGTH=251, writing returns bad data after 28 bytes!

Data on wire: 122808021a241a2212200102030405060708091011121314151617181920212223242526272829303132

Data in buffer:122808021A241A22122001020304050607080910111213141516171801000000354D0300D1A90200A5A5

When writing from the central to the peripheral, the data is correct transmitted over the air to the peripheral (logged with wire shark).

In the peripheral, I get the event for receiving the written data. The length of the data is indicated correctly, but the data in the buffer in the BLE stack are incorrect.

The data I copy from the BLE stack to my local buffer are only correct for the first 28 byte! The remaining bytes are in the most cases constant memory garbage.

For me it looks like the BLE stacks doesn't handle all data.

Characteristic:

static uint32_t toolCommandCharAdd(tBlePowerTool * prtToBlePowerTool, const tBlePressGunSrvInit * ptrToBlePressGunSrvInit)
{
    ble_gatts_char_md_t gatts_char_md;
    ble_gatts_attr_t    gatts_attr;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t gatts_attr_md;

    // setup the char attr meta data
    memset(&gatts_char_md, 0, sizeof(gatts_char_md));
    gatts_char_md.char_props.write = true;
    gatts_char_md.char_ext_props.reliable_wr = true; // Queued write operation permmited

    // setup the characteristic attr 
    ble_uuid.type = prtToBlePowerTool->pressGunSrv.uuid_type;
    ble_uuid.uuid = PRESSGUNSRV_UUID_TOOL_COMMAND_CHAR;

    memset(&gatts_attr_md, 0, sizeof(gatts_attr_md));
    gatts_attr_md.read_perm  = ptrToBlePressGunSrvInit->payload_writeonly_attr_md.read_perm;
    gatts_attr_md.write_perm = ptrToBlePressGunSrvInit->payload_writeonly_attr_md.write_perm;
    gatts_attr_md.vlen       = true; // support of variable len 
    gatts_attr_md.vloc       = BLE_GATTS_VLOC_USER;
    gatts_attr_md.rd_auth    = true;
    gatts_attr_md.wr_auth    = true;

    memset(&gatts_attr, 0, sizeof(gatts_attr));
    gatts_attr.p_uuid    = &ble_uuid;
    gatts_attr.p_attr_md = &gatts_attr_md;
    gatts_attr.init_len  = 0;
    gatts_attr.init_offs = 0;
    gatts_attr.max_len   = sizeof BlePwrBrdCommEventDataWrite.dataBuf;
    gatts_attr.p_value   = (uint8_t *) BlePwrBrdCommEventDataWrite.dataBuf;

    return sd_ble_gatts_characteristic_add(prtToBlePowerTool->pressGunSrv.service_handle,
                                           &gatts_char_md,
                                           &gatts_attr,
                                           &prtToBlePowerTool->pressGunSrv.toolCommandHandles);
}

Event for Receiving:

        case BLE_GATTS_OP_WRITE_REQ:
            NRF_LOG_DEBUG("BLE_GATTS_OP_WRITE_REQ: len: %d", p_evt_write->len );
            memset( BlePwrBrdCommEventDataWrite.dataBuf, 0 , sizeof BlePwrBrdCommEventDataWrite.dataBuf );
            memcpy( BlePwrBrdCommEventDataWrite.dataBuf, &p_evt_write->data[0], p_evt_write->len );
            BlePwrBrdCommEventDataWrite.size = p_evt_write->len;

Debug Log:

<debug> nrf_ble_gatt: max_tx_time: 2120
<debug> nrf_sdh_ble: BLE event: 0x51.
<debug> app: BLE_GATTS_AUTHORIZE_TYPE_WRITE with BLE_GATTS_OP_WRITE_REQ
<debug> app: BLE_GATTS_OP_WRITE_REQ: len: 11
<debug> app: BlePwrBrdCommEventBleWrite
<debug> app: DATA BUFFER: 0A0908FA0710021A020816
<debug> nrf_sdh_ble: BLE event: 0x51.
<debug> app: BLE_GATTS_AUTHORIZE_TYPE_WRITE with BLE_GATTS_OP_WRITE_REQ
<debug> app: BLE_GATTS_OP_WRITE_REQ: len: 8
<debug> app: BlePwrBrdCommEventBleWrite
<debug> app: DATA BUFFER: 120608011A025200
<debug> nrf_sdh_ble: BLE event: 0x51.
<debug> app: BLE_GATTS_AUTHORIZE_TYPE_READ
<debug> app: FrameRead reply offset 0 (16 bytes) with SUCCESS.
<debug> nrf_sdh_ble: BLE event: 0x51.
<debug> app: BLE_GATTS_AUTHORIZE_TYPE_WRITE with BLE_GATTS_OP_WRITE_REQ
<debug> app: BLE_GATTS_OP_WRITE_REQ: len: 42
<debug> app: BlePwrBrdCommEventBleWrite
<debug> app: DATA BUFFER: 122808021A241A22122001020304050607080910111213141516171801000000354D0300D1A90200A5A5

Parents Reply Children
  • I see. Can you upload your project (or a minimal example) that runs on the DK so that I can try to reproduce this on my side?

  • I have added my service with 2 characteristic to 2 examples from nordic. You can use "nRf connect" to explore the "unknown" service and send bytes in a byte array to the first characteristic in my service.

    RTE_ble_app_hrs: MTU=247, DATA_LENGTH=251 (original settings), write is working as expected, tested with up to 96 bytes

    RTE_ble_app_hrs_freertos: MTU=23, DATA_LENGTH=27 (original settings), write is working up to 20 bytes, when sending more than 20 data bytes application crashes.

    RTE_ble_app_hrs_freertos: MTU=247, DATA_LENGTH=251 (adapted settings), application crashes when trying to connect.

    Copy the contents of the ZIP to SDK 15.2.0\examples\ble_peripharals and use a PCA10040 to test.
    The received bytes are written to  the debug console.

    RTE_ble_app_hrs-hrs_freertos.zip

  • Some more information to my modified code:

    You can set the define on line 486 in the main.c of the RTE_ble_app_hrs_freeRTOS to zero to have only the original code.

    // RTE_START
    #define PRESSGUN_SERVICE 0

    If the mtu_size and data_length are set to larger values than default, the original code crashes already when connecting. There is a separate case for this issue:

    example-ble_app_hrs_freertos-crashing-with-max_mtu_size-247-and-data_length-251

  • Hi,

    I am sorry for the late reply. You may have spotted it already, but the problem here is that the example (like most SDK examples) use the QWR module. This module handles the BLE_EVT_USER_MEM_REQUEST before your application does, so when you handle the BLE_EVT_USER_MEM_REQUEST event and call sd_ble_user_mem_reply() again it returns NRF_ERROR_INVALID_STATE. To fix this issue you should either use only the QWR module or remove it altogether.

  • Hi Einar

    I have defined away the QWR module, I think it is only used when bonding.

    RTE_ble_app_hrs-hrs_freertos_2019-03-04.zip

    Now the RTE_ble_app_hrs works with maximum length, but with strange reporting:

    It is interchanged a max size of 123, but also longer payloads are exchanged in one telegram. This is strange.

    <debug> nrf_ble_lesc: Initialized nrf_crypto.
    <debug> nrf_ble_lesc: Initialized nrf_ble_lesc.
    <debug> nrf_ble_lesc: Generating ECC key pair
    <info> app: Heart Rate Sensor example started.
    <info> app: Fast advertising.
    <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> app: Connected.
    <debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
    <info> app: GATT ATT MTU on connection 0x0 changed to 247.
    <debug> nrf_ble_gatt: Data length updated to 123 on connection 0x0.
    <debug> nrf_ble_gatt: max_rx_octets: 123
    <debug> nrf_ble_gatt: max_tx_octets: 123
    <debug> nrf_ble_gatt: max_rx_time: 1096
    <debug> nrf_ble_gatt: max_tx_time: 1096
    <debug> nrf_ble_gatt: Peer on connection 0x0 requested a data length of 123 bytes.
    <debug> nrf_ble_gatt: Updating data length to 123 on connection 0x0.
    <debug> nrf_ble_gatt: Data length updated to 123 on connection 0x0.
    <debug> nrf_ble_gatt: max_rx_octets: 123
    <debug> nrf_ble_gatt: max_tx_octets: 123
    <debug> nrf_ble_gatt: max_rx_time: 1096
    <debug> nrf_ble_gatt: max_tx_time: 1096
    <debug> app: BLE_GATTS_AUTHORIZE_TYPE_WRITE with BLE_GATTS_OP_WRITE_REQ
    <debug> app: BLE_GATTS_OP_WRITE_REQ: len: 128
    <debug> app: BlePwrBrdCommEventBleWrite
    <debug> app: DATA BUFFER: 112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00
    <debug> app: BLE_GATTS_AUTHORIZE_TYPE_WRITE with BLE_GATTS_OP_WRITE_REQ
    <debug> app: BLE_GATTS_OP_WRITE_REQ: len: 96
    <debug> app: BlePwrBrdCommEventBleWrite
    <debug> app: DATA BUFFER: 112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00
    <debug> app: BLE_GATTS_AUTHORIZE_TYPE_WRITE with BLE_GATTS_OP_WRITE_REQ
    <debug> app: BLE_GATTS_OP_WRITE_REQ: len: 128
    <debug> app: BlePwrBrdCommEventBleWrite
    <debug> app: DATA BUFFER: 112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00
    <debug> app: BLE_GATTS_AUTHORIZE_TYPE_WRITE with BLE_GATTS_OP_WRITE_REQ
    <debug> app: BLE_GATTS_OP_WRITE_REQ: len: 144
    <debug> app: BlePwrBrdCommEventBleWrite
    <debug> app: DATA BUFFER: 112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00
    

    The example RTE_ble_app_hrs_freertos works fine only with 

    #define NRF_SDH_BLE_GAP_DATA_LENGTH 127 /* */
    #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 123 /* */

    Higher values have crashed the BLE stack on my Android phone and I have to restart the Android phone to get a connection again.

    Please advise!

    Happy coding
    Christian

Related