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

MAX MTU Size using Serialization SDK 17.0.2

We are using NRF52832 with STM32L4A6 using serialization.  We have the serialization working properly, but having an issue with the MAX MTU size.  We can set the NRF_SDH_BLE_GATT_MAX_MTU_SIZE between 23 to 48 and serialization works fine.  When we increase to 49 or later, the serialization hangs.  Further investigation shows that in the on_connected_evt method, calling sd_ble_gattc_exchange_mtu_request method ultimately calls the ser_phy_tx_pkt_send which checks for the mp_tx_buffer and this buffer pointer is not NULL.  Our guess is that previous serialization call did not complete properly (thus does not reset the mp_tx_buffer).  It seems very odd that changing the NRF_SDH_BLE_GATT_MAX_MTU_SIZE causes the serialization issue.

In the SDK17.0.2 example project, ble_peripheral | ble_app_hrs | pca10040 | SER_132_spi, we noticed that the NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 23.  However, in the non serialized example of the ble peripheral, the NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 247 and works properly.  The NRF_SDH_BLE_GAP_DATA_LENGTH is set to 27.

Has anyone had success setting the NRF_SDH_BLE_GATT_MAX_MTU_SIZE to larger than 48 using the serialization?  If so, what was the test setup and the values for the NRF_SDH_BLE_GATT_MAX_MTU_SIZE.

We are using SDK 17.0.2 with softdevice s132_nrf52_7.2.0 on PCA10040 as connectivity module.

Parents
  • Nordic is BLE Peripheral and communicating with iOS and Android as BLE Central.  iOS and Android both have the same issue.  I was trying to debug what was the previous serialization call was but it is really hard to debug it.  I can try to add some delay, but my guess is that it won't help.  I set a break point on on_connected_evt and step through the calls and and it hangs due to mp_tx_buffer not being NULL.  For NRF_SDH_BLE_GATT_MAX_MTU_SIZE of 23, it does not hang (mp_tx_buffer is NULL).  I see that pc-ble-driver example softdevice is not the same as what we are using s132_nrf52_7.2.0.  Not sure if I can use it as is.

    We will be getting two PCA10040 soon, so I will use the examples from SDK 17.0.2 from ble_peripheral | ble_app_hrs | pca10040 | SER_132_spi and see if we can get NRF_SDH_BLE_GATT_MAX_MTU_SIZE larger than 23 consistently only using the Nordic code.  Has anyone already tried using SDK 17.0.2 using s132_nrf52_7.2.0 to see if serialization works for NRF_SDH_BLE_GATT_MAX_MTU_SIZE greater than 23?

  • jkim said:
    mp_tx_buffer not being NULL

     But does ser_phy_tx_pkt_send() not return NRF_ERROR_BUSY in this case?

    uint32_t ser_phy_tx_pkt_send(const uint8_t * p_buffer, uint16_t num_of_bytes)
    {
        uint32_t status = NRF_SUCCESS;
    
        if ( p_buffer == NULL || num_of_bytes == 0)
        {
            return NRF_ERROR_NULL;
        }
    
        ser_phy_interrupts_disable();
    
        if ( m_p_tx_buffer == NULL)
        {
            m_tx_packet_length = num_of_bytes;
            m_p_tx_buffer      = p_buffer;
            set_request_line();
        }
        else
        {
            status = NRF_ERROR_BUSY;
        }
        ser_phy_interrupts_enable();
    
        return status;
    }

Reply
  • jkim said:
    mp_tx_buffer not being NULL

     But does ser_phy_tx_pkt_send() not return NRF_ERROR_BUSY in this case?

    uint32_t ser_phy_tx_pkt_send(const uint8_t * p_buffer, uint16_t num_of_bytes)
    {
        uint32_t status = NRF_SUCCESS;
    
        if ( p_buffer == NULL || num_of_bytes == 0)
        {
            return NRF_ERROR_NULL;
        }
    
        ser_phy_interrupts_disable();
    
        if ( m_p_tx_buffer == NULL)
        {
            m_tx_packet_length = num_of_bytes;
            m_p_tx_buffer      = p_buffer;
            set_request_line();
        }
        else
        {
            status = NRF_ERROR_BUSY;
        }
        ser_phy_interrupts_enable();
    
        return status;
    }

Children
  • It appears that adding 250ms delay before calling sd_ble_gattc_exchange_mtu_request in on_connected_evt helps with the m_p_tx_buffer != NULL issue.  We can change the logic regarding the APP_ERROR_CHECK implementation to not to generate exception on NRF_ERROR_BUSY and allow retry logic to work.

    I now have related issue that I mentioned earlier.  With the NRF_SDH_BLE_GATT_MAX_MTU_SIZE set to 83 (43 appears OK), I now get the following error:

    In tx_buf_alloc, calling ser_hal_transport_tx_pkt_alloc returns err_code of NRF_ERROR_NO_MEM because the m_tx_state is set to 28 (which is invalid), thus results in NRF_ERROR_NO_MEM.  We do have quite a few characteristics, but as far as I know, I did not get NRF_ERROR_NO_MEM when creating the characteristics (I can double check).  What conditions will result in NRF_ERROR_NO_MEM when calling ser_hal_transport_tx_pkt_alloc?  I could not see where m_tx_state set to invalid value of 28.

    uint32_t _sd_ble_gattc_exchange_mtu_request(uint16_t conn_handle,
    uint16_t client_rx_mtu)
    {
    uint8_t * p_buffer;
    uint32_t buffer_length = 0;

    tx_buf_alloc(&p_buffer, (uint16_t *)&buffer_length);

    const uint32_t err_code = ble_gattc_exchange_mtu_request_req_enc(conn_handle,
    client_rx_mtu,
    &(p_buffer[1]),
    &buffer_length);
    APP_ERROR_CHECK(err_code);

    //@note: Increment buffer length as internally managed packet type field must be included.
    return ser_sd_transport_cmd_write(p_buffer,
    (++buffer_length),
    gattc_exchange_mtu_request_rsp_dec);
    }

  • jkim said:
    We can change the logic regarding the APP_ERROR_CHECK implementation to not to generate exception on NRF_ERROR_BUSY and allow retry logic to work.

     Yes, this is the correct way to handle this. Take a look at how this is handled in e.g. components\ble\nrf_ble_gatt\nrf_ble_gatt.c (att_mtu_exchange_pending/att_mtu_exchange_requested)

    jkim said:
    In tx_buf_alloc, calling ser_hal_transport_tx_pkt_alloc returns err_code of NRF_ERROR_NO_MEM

     Hmm, so it's stuck in this loop? or does it exit the loop after a while?

    static void tx_buf_alloc(uint8_t * * p_data, uint16_t * p_len)
    {
        uint32_t err_code;
    
        do
        {
            err_code = ser_sd_transport_tx_alloc(p_data, p_len);
        }
        while (err_code != NRF_SUCCESS);
        *p_data[0] = SER_PKT_TYPE_CMD;
        *p_len    -= 1;
    }

     

  • Yes, when I get NRF_ERROR_NO_MEM from tx_buf_alloc, calling ser_hal_transport_tx_pkt_alloc, it is stuck in this loop.  Since there are so many inconsistent behavior with this implementation, we have decided to try to use Nordic version of serialization only (and not use our version of serialization).  Once we get the two PCA10040 boards and try the Nordic example with iOS and Android, I will update our findings.  I will be out of office for several days, so I will probably have update late next week.  In the meantime, if you can keep this open that would be great.

  • Finally had chance to use two PCA10040 boards with Android as BLE Central.  Using the ser_s132_spi example from HRS, I was able to get the MTU size of 247 to work without any issues.  This confirms that the Nordic version of the serialization code supports MTU greater than 23.  Unfortunately, this means that our implementation of the serialization on STM32 board has issues.  We will use the Nordic example code and compare with our implementation to see what the difference is that is causing the issue.  We can close this post.

Related