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
  • Hi

    I updated my last reply with the link I was referring to.

    What function exactly do you refer to in your last reply? Data length should indeed be enabled on the Android side on almost all phones nowadays.

    iOS also supports DLE, but as far as I know iOS only supports MTUs up to 184 bytes or so, and also indeed decides the MTU and won't pay much attention to what the peripheral is requesting.

    Best regards,

    Simon

  • Hi Simon,

    Thanks for the link, it will help our app developer.

    What function exactly do you refer to in your last reply? Data length should indeed be enabled on the Android side on almost all phones nowadays.

    I will first give a brief of what I am doing using  a part of code below to explain the code flow and how I am updating the configurations from peripheral side.

    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;
    }
    
    void write_fs(void *write_data, ssize_t len)
    {
    	fs_seek(&bleRxFilePtr, 0, FS_SEEK_END);
        fs_write(&bleRxFilePtr, write_data, len);
        return;
    }
    
    static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
    {
        LOG_WRN("ble_rx_data: %s",data);
    
        uint8_t *ble_rx_data = (uint8_t *)data;
        uint16_t ble_rx_data_len = len;
    
    
        if('!' == ble_rx_data[0]) {
            /* Write data received to the SD card */
            write_fs(ble_rx_data + 1, len - 3);
        }
        else if('&' == ble_rx_data[0]) {
            update_ble_file_tx_params();
        }
        return;
    }

    In the above code, when nRF5340 receives '&' character from mobile app at  ble_rx_data[0] position, then it triggers below 4 configuration updates.

    update_connection_parameters();
    request_mtu_exchange();
    request_data_len_update();
    request_phy_update();

    The successful update of all these configurations needs some 2-3 seconds time (observed this in nRF connect mobile app). Once they are updated then data transmission starts from mobile app and nrf5340 starts writing into SD card using write_fs(). In this way my idea was to execute the required BLE configurations setup from nRF5340 side and app will only take care to enable these configurations and send data to store into SD card.

    Here, for DLE, from nRF5340 side, the function I was referring to is bt_conn_le_data_len_update() which is triggered inside request_data_len_update(). I hope this clears your query.


    as I know iOS only supports MTUs up to 184 bytes or so, and also indeed decides the MTU and won't pay much attention to what the peripheral is requesting.

    So overall transfer speed will be much lesser than what can be expected from Android? 

    Thanks,

    Shubham

  • Hi again Shubham

    From what I can tell, data length extensions should be enabled here, yes. As long as the configs in your project also enable CONFIG_BT_DATA_LEN_UPDATE data length updates will be enabled. We also have the CONFIG_BT_AUTO_DATA_LEN_UPDATE to initiate a Data Length Update on connection establishments.

    The transfer speeds over iOS shouldn't be much lower, no. But a few bytes per second less must be expected.

    Best regards,

    Simon

Reply Children
  • Hi Simon,

    I haven't added CONFIG_BT_DATA_LEN_UPDATE=y in nrf5340 project prj.conf but  when I checked the .config file at location, \build\hci_rpmsg\zephyr\.config file,  I can see CONFIG_BT_DATA_LEN_UPDATE=y and I think because of this I am able get below logs when I tested with our mobile app.

    Please correct me if I am misunderstanding anything. 


    I just have one more query,

    as I can see while using our mobile app, LE PHY 2 Mbps mode, LE data len as per required length and Connection parameters are updating as per the requirement, then if I trigger MTU request of 498 from mobile app side then will that be a correct approach to be able to get the maximum data transmission throughput (around 1.3 Mbps which we have observed with DK to DK communication using throughput example)?

    The transfer speeds over iOS shouldn't be much lower, no. But a few bytes per second less must be expected.

    We should observe atleast upto 1 Mbps with iOS then.

    Thanks,

    Shubham 

Related