Firmware transfer over BLE for another MCU

Hi,

For our application, we need to transfer binary (.bin) file from Phone and nRF5340 over BLE and store it into the SD card. Later, another MCU will read the file and update its firmware.

I went through two other queries query_1 and query_2, but those are for transferring data over UART. However, I want to store the file first on an external SD card connected to the SoC, rather than directly transmitting over UART.

I cannot find any example for the same in nRF Connect SDK V2.0.0. Please let me know if I can use any example or a can follow a procedure.

Thanks

Parents
  • Take a look at the samples peripheral_uart and central_uart. These samples demonstrates how to transfer data between two devices using Bluetooth and the RX and TX characteristics.

    Best regards,

    Simon

  • Hi Simon,

    I have tried these examples before. However, the transmission speed is very slow for me (1 - 1.5 KBps). Please suggest how to increase the transmission speed.

    Thanks

  • So it is either the BLE, the SD card writing or the combination of these.
    Can you try to write dummy data without BLE to the SD card some thousand times and see if this happens?
    Then receive data from BLE the same amount and not write data to SD card, but discard it instead, and see if this happens?

    With this, we can find if it is an SD Card or BLE specific issue.

    Edit: A collegua also suggests this:
    " Sounds a bit like a flow control issue, yes. Ideally you should stop processing packets from the Bluetooth stack if your local buffers fill up, then the SDC will start NAKing incoming data. "

  • " Sounds a bit like a flow control issue, yes. Ideally you should stop processing packets from the Bluetooth stack if your local buffers fill up, then the SDC will start NAKing incoming data. "

    Is there a method to let mobile application tell that nRF5340 side local buffers already filled and it has to wait?

  • As I see it you have two alternatives:

    • Doing some "trick" in BLE to give the mobile a callback for something. For example time the send out and react on that. I could ask our BLE experts about this if you want?
    •  The more structured method would be to implement a notification service in the nRF5340 which tells the mobile application when it is ready for data and how much data it is ready for. This way the mobile always knows how much it can send. I beleive this is more or less the method we use for DFU.
  • As I see it you have two alternatives:

    I will check these alternatives and update in case any issue is observed.


    One more observation I have which is related to the mobile app when update_ble_file_tx_params() function is triggered from nRF5340 the result is different for our mobile app and nrf connect mobile app

    Code for triggering update_ble_file_tx_params():

    static void conn_params_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency, uint16_t timeout)
    {
    	uint32_t interval_int= interval*1.25;
    	LOG_INF("Conn params updated: interval %d ms, latency %d, timeout: %d0 ms",interval_int, latency, timeout);
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval,
    			     uint16_t latency, uint16_t timeout)
    {
    	LOG_INF("Connection parameters updated.\n"
    	       " interval: %d, latency: %d, timeout: %d\n",
    	       interval, latency, timeout);
    }
    
    static void le_phy_updated(struct bt_conn *conn,
    			   struct bt_conn_le_phy_info *param)
    {
    	struct bt_conn_info info = { 0 };
    	int err;
    
    	LOG_INF("LE PHY updated: TX PHY %s, RX PHY %s\n",
    	       phy2str(param->tx_phy), phy2str(param->rx_phy));
    
    	err = bt_conn_get_info(conn, &info);
    	if (err) {
    		LOG_INF("Failed to get connection info %d\n", err);
    		return;
    	}
    }
    
    static void le_data_length_updated(struct bt_conn *conn,
    				   struct bt_conn_le_data_len_info *info)
    {
    	if (!data_length_req) {
    		return;
    	}
    
    	LOG_INF("LE data len updated: TX (len: %d time: %d)"
    	       " RX (len: %d time: %d)\n", info->tx_max_len,
    	       info->tx_max_time, info->rx_max_len, info->rx_max_time);
    
    	data_length_req = false;
    }
    
    static int update_connection_parameters(void)
    {	
    	int err;
    	err = bt_conn_le_param_update(current_conn, conn_param);
    		if (err) {
    			LOG_ERR("Cannot update connection parameter (err: %d)", err);
    			return err;
    		}
    	LOG_INF("Connection parameters update requested");
    	return 0;
    }
    
    static void MTU_exchange_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
    {
    	if (!err) {
    		LOG_INF("MTU exchange done. "); 
    	} else {
    		LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err);
    	}
    }
    static void request_mtu_exchange(void)
    {	int err;
    	static struct bt_gatt_exchange_params exchange_params;
    	exchange_params.func = MTU_exchange_cb;
    	err = bt_gatt_exchange_mtu(current_conn, &exchange_params);
    	if (err) {
    		LOG_WRN("MTU exchange failed (err %d)", err);
    	} else {
    		LOG_INF("MTU exchange pending");
    	}
    }
    
    static void request_data_len_update(void)
    {
    	int err;
    	struct bt_conn_info info = {0};
    
    	err = bt_conn_get_info(current_conn, &info);
    	if (err) {
    		LOG_ERR("Failed to get connection info %d\n", err);
    		return;
    	}
    
    	if (info.le.data_len->tx_max_len != BT_LE_DATA_LEN_PARAM_MAX) {
    		data_length_req = true;
    
    		err = bt_conn_le_data_len_update(current_conn, BT_LE_DATA_LEN_PARAM_MAX);
    		if (err) {
    			LOG_ERR("LE data length update request failed: %d",  err);
    		}
    	}
    	else LOG_INF("Already info.le.data_len->tx_max_len = BT_LE_DATA_LEN_PARAM_MAX");
    }
    
    static void request_phy_update(void)
    {
    	int err;
    	err = bt_conn_le_phy_update(current_conn, BT_CONN_LE_PHY_PARAM_2M);
    	if (err) {
    		LOG_ERR("Phy update request failed: %d",  err);
    	}
    }
    
    void update_ble_file_tx_params(void)
    {
    	update_connection_parameters();
    	request_mtu_exchange();
    	request_data_len_update();
    	request_phy_update();
    	return;
    }

    When using nRF connect mobile app, below logs appear

    However, when using our mobile app, below logs appear

    Why is it so? As from the nRF5340 side similar functions are triggered.

    And as LE data len is not updating and MTU exchange is failing, the transmission speed is very low.

    -Shubham

  • https://github.com/nrfconnect/sdk-zephyr/blob/ff85910bf8ed1aac0571bca0e7f206782234efbb/include/zephyr/bluetooth/gatt.h#L1340:

     *  @retval -EALREADY The MTU exchange procedure has been already performed.

    Does your application do the MTU exchange procedure more than once?

Reply Children
  • I will check with the app developer once and will update here.

    However, I need to use below configuration in nRF5340 to be able to communicate with mobile app. If I disable it then communication doesn't happen. 

    CONFIG_BT_GATT_AUTO_UPDATE_MTU=y

    Does that mean that MTU exchange is being done even before update_ble_file_tx_params() is triggered from nRF5340? 


    Also why the LE data length extension doesn't occur when using our mobile app but it works when using nRF connect mobile application?
    So, does the DLE support depend upon MTU exchange procedure too or there's any other configuration required on mobile app side which is present in nRF connect mobile app but not in ours.

    Is there any option in nRF connect mobile app to test large amount of data transfer over NUS ? Because for testing purpose I need to manually send the data one by one by putting data in the highlighted section.
    -Shubham
Related