MTU between BLE_NUS & BLE_NUS_C is not exchanged, but BLE_NUS & iOS nRF Connect App is exchanged?

Hi,

  I am implementing NUS which is based on example BLE_NUS & BLE_NUS_C.

  The connection is not 1-to-1 but 1-to-7. i.e. 1 Central connects to 7 Peripherals.
  Although ultimate goal is 7 peripherals, I am just testing with 2 peripherals in the current phase.

  So far I have implemented:
  Peripheral side (BLE_NUS) is sending 78 Bytes data every 3 seconds.
  Central side (BLE_NUS_C) can accept 7 device (

NRF_SDH_BLE_CENTRAL_LINK_COUNT = 7
).
  Both NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 300 in config.h.
  In gatt_init(void), I have added a log to print out the NRF_SDH_BLE_GATT_MAX_MTU_SIZE to confirm.
 
NRF_LOG_INFO("NRF_SDH_BLE_GATT_MAX_MTU_SIZE = %u", NRF_SDH_BLE_GATT_MAX_MTU_SIZE)
and confirmed it is 300 in log.

  What is the problem:
  When peripheral sends the data, let's say the conent is: "ABCDEFGHIJKLMNOPQRSTUVWXYZ......." (78 Bytes in total).
  On Central side (BLE_NUS_C_EVT_NUS_TX_EVT), the received data is only 20 Bytes.
  i.e. p_ble_nus_evt->p_data is "ABCDEFGHIJKLMNOPQRST" and p_ble_nus_evt->data_len is 20.

  I am quite sure that the Peripheral side is sending out whole 78 Bytes datas because if I connect to iOS nRF Connect App. I can see the whole 78 Bytes data and it keeps updating every 3 seconds.
  According from the RTT Log from Peripheral, I found that if the Peripheral connect with iOS nrfConnect, the log has printed out a message "ATT MTU exchange completed. central 0x12C peripheral 0x12C", where this log does not show up if it is connect to BLE_NUS_C (Central)

  Is there any hint how could I fix it?
  Or can I force update the MTU after connected?

  Thank you very much.
Joe

Parents
  • Hi Joe

    Unless you are using a very old version of the SDK it sounds odd that the MTU and data length exchange shouldn't occur, as long as you have set the data length and max MTU parameters correctly in sdk_config.h

    Can you let me know which version of the SDK you are using?

    Also, did you make a lot of changes to the ble_app_nus_c example in order to support multilink?
    I believe it doesn't support this out of the box. 

    Best regards
    Torbjørn

Reply
  • Hi Joe

    Unless you are using a very old version of the SDK it sounds odd that the MTU and data length exchange shouldn't occur, as long as you have set the data length and max MTU parameters correctly in sdk_config.h

    Can you let me know which version of the SDK you are using?

    Also, did you make a lot of changes to the ble_app_nus_c example in order to support multilink?
    I believe it doesn't support this out of the box. 

    Best regards
    Torbjørn

Children
  • Hi Torbjørn

    Thank you for your reply.

    1a. According to documentation/release_notes.txt, My SDK version is nRF5 SDK v16.0.0 Release Date: October, 2019. I believe this is not very old version. :)

    1b. About the max MTU in sdk_config.h, both ble_app_uart_c and ble_app_uart are set to 247. (I tested with 300 at first, and later on I changed to 247, but the problem is still occur.) In gatt_init(void), i have tried to print out the setting to confirm as follow and its value is 247.

    NRF_LOG_INFO("NRF_SDH_BLE_GATT_MAX_MTU_SIZE = %u", NRF_SDH_BLE_GATT_MAX_MTU_SIZE);

    2. Yes I have changed the ble_app_nus_c to support multilink. 
    Here is the highlight of what I have changed:

    ...
    
    // BLE_NUS_C_DEF(m_ble_nus_c);
    BLE_NUS_C_ARRAY_DEF(m_ble_nus_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT);
    
    // BLE_DB_DISCOVVERY_DEF(m_db_disc);
    BLE_DB_DISCOVERY_ARRAY_DEF(m_db_disc, NRF_SDH_BLE_CENTRAL_LINK_COUNT);
    
    ...
    
    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
      // ble_nus_c_on_db_disc_evt(&m_ble_nus_c, p_evt);
      ble_nus_c_on_db_disc_evt(&m_ble_nus_c[p_evt->conn_handle], p_evt);
    }
    
    ...
    
    static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
    {
      ...
      switch (p_ble_nus_evt->evt_type)
      {
        case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
          // err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles);
          err_code = ble_nus_c_handles_assign(&m_ble_nus_c[p_ble_nus_evt->conn_handle], p_ble_nus_evt->conn_handle, & p_ble_nus_evt->handles);
          ...
          //err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);
          err_code = ble_nus_c_tx_notif_enable(&m_ble_nus_c[p_ble_nus_evt->conn_handle]);
      }
    }
    
    ...
    
    static void nus_c_init(void)
    {
      ...
      // err_code = ble_nus_c_init(&m_ble_nus_c, &init);
      // APP_ERROR_CHECK(err_code);
      for (uint32_t i = 0; i < NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
      {
        err_code = ble_nus_c_init(&m_ble_nus_c[i], &init);
        APP_ERROR_CHECK(err_code);
      }
    }

    After searching about how to exchange MTU on the internet, looks like that I only have to set the MTU size in gatt_init like the code below, and both devices will exchange it automatically when connection starts? Do I understand correctly? (Although it does not work as expected with my code right now)

    static void gatt_init(void)
    {
      ...
      ret_code_t err = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
      APP_ERROR_CHECK(err_code);
      
      NRF_LOG_INFO("NRF_SDH_BLE_GATT_MAX_MTU_SIZE = %u", NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
      
      // On Central side
      err_code = nrf_ble_gatt_att_mtu_central_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
      // On Peripheral side
      err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
      
      APP_ERROR_CHECK(err_code);
    }

    Best regards
    Joe

  • Hi Torbjørn

      Finally I have figure out what have gone wrong and it is extremely stupid. Slight smile

      After a full file diff between a newly downloaded nRF5 SDK v16.0.0 and my project code, I found that the "Begin an ATT MTU exchange if necessary" (Line 150 to 173) part in nrf_ble_gatt.c (components/ble_nrf_ble_gatt/nrf/ble_gatt.c) is being commented out. Thats why the devices does not exchange the MTU (both Central and Peripheral uses the same SDK so they share the same mistake).

      It is fixed after bringing back that part of code.

      Thank you for your help.
      Have a good day!

    Joe

  • Hi Joe

    It is good to hear that you found the issue at last. I will consider the case resolved then Slight smile

    Best regards
    Torbjørn

Related