diff --git a/common/fw-update-helper.cpp b/common/fw-update-helper.cpp index 104d134981..ff1c538758 100644 --- a/common/fw-update-helper.cpp +++ b/common/fw-update-helper.cpp @@ -272,7 +272,7 @@ namespace rs2 if ( !log_backup_status.empty() ) log(log_backup_status); - next_progress = _progress + 10; + next_progress = static_cast(_progress) + 10; if (_is_signed) { diff --git a/src/ds/d500/d500-fw-update-device.cpp b/src/ds/d500/d500-fw-update-device.cpp index 7687a2e977..aa20914dfd 100644 --- a/src/ds/d500/d500-fw-update-device.cpp +++ b/src/ds/d500/d500-fw-update-device.cpp @@ -38,6 +38,13 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info void ds_d500_update_device::update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr update_progress_callback) const { update_device::update( fw_image, fw_image_size, update_progress_callback ); + + if (!_is_dfu_monitoring_enabled) + { + LOG_DEBUG("Waiting for the FW to be burnt"); + static constexpr int D500_FW_DFU_TIME = 120; // [sec] + report_progress_and_wait_for_fw_burn(update_progress_callback, D500_FW_DFU_TIME); + } } bool ds_d500_update_device::wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, @@ -61,9 +68,12 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info // the below code avoids process stuck when using a d5XX device, // which has a fw version without the DFU progress feature - if (percentage_of_transfer == 0 && + if (percentage_of_transfer == 0 && ++iteration == max_iteration_number_for_progress_start) + { + _is_dfu_monitoring_enabled = false; return true; + } std::stringstream ss; ss << "DFU_GETSTATUS called, state is: " << to_string(dfu_state); @@ -77,7 +87,7 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info } if (sts != platform::RS2_USB_STATUS_SUCCESS) - LOG_DEBUG("control xfer error: " << platform::usb_status_to_string[sts]); + LOG_ERROR("control xfer error: " << platform::usb_status_to_string[sts]); //test for dfu error state if (status.is_error_state()) { @@ -98,4 +108,49 @@ ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info return true; } + + void ds_d500_update_device::dfu_manifest_phase(const platform::rs_usb_messenger& messenger, rs2_update_progress_callback_sptr update_progress_callback) const + { + // measuring the progress of the writing to flash (when enabled by FW) + if (!wait_for_manifest_completion(messenger, RS2_DFU_STATE_DFU_MANIFEST, std::chrono::seconds(200), update_progress_callback)) + throw std::runtime_error("Firmware manifest completion failed"); + + + // After the zero length DFU_DNLOAD request terminates the Transfer + // phase, the device is ready to manifest the new firmware. As described + // previously, some devices may accumulate the firmware image and perform + // the entire reprogramming operation at one time. Others may have only a + // small amount remaining to be reprogrammed, and still others may have + // none. Regardless, the device enters the dfuMANIFEST-SYNC state and + // awaits the solicitation of the status report by the host. Upon receipt + // of the anticipated DFU_GETSTATUS, the device enters the dfuMANIFEST + // state, where it completes its reprogramming operations. + + // WaitForDFU state sends several DFU_GETSTATUS requests, until we hit + // either RS2_DFU_STATE_DFU_MANIFEST_WAIT_RESET or RS2_DFU_STATE_DFU_ERROR status. + // This command also reset the device + if (_is_dfu_monitoring_enabled) + { + if (!wait_for_state(messenger, RS2_DFU_STATE_DFU_MANIFEST_WAIT_RESET, 20000)) + throw std::runtime_error("Firmware manifest failed"); + } + } + + void ds_d500_update_device::report_progress_and_wait_for_fw_burn(rs2_update_progress_callback_sptr update_progress_callback, int required_dfu_time) const + { + // We calculate the sleep time needed for each cycle to get to 100% progress bar + if (update_progress_callback) + { + float iteration_sleep_time_ms = (static_cast(required_dfu_time) / 100.0f) * 1000.0f; + for (int i = 1; i <= 100; i++) + { + auto percentage_of_transfer = i; + auto progress_for_bar = compute_progress(static_cast(percentage_of_transfer), 20.f, 100.f, 5.f) / 100.f; + update_progress_callback->on_update_progress(progress_for_bar); + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(iteration_sleep_time_ms))); + } + } + else + std::this_thread::sleep_for(std::chrono::seconds(required_dfu_time)); + } } diff --git a/src/ds/d500/d500-fw-update-device.h b/src/ds/d500/d500-fw-update-device.h index 48b18b9952..61f5f79f09 100644 --- a/src/ds/d500/d500-fw-update-device.h +++ b/src/ds/d500/d500-fw-update-device.h @@ -16,10 +16,17 @@ namespace librealsense virtual bool check_fw_compatibility(const std::vector& image) const override; virtual void update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const override; - virtual bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, - std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const override; + bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, + std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const; + virtual void dfu_manifest_phase(const platform::rs_usb_messenger& messenger, rs2_update_progress_callback_sptr update_progress_callback) const override; private: std::string parse_serial_number(const std::vector& buffer) const; + void report_progress_and_wait_for_fw_burn(rs2_update_progress_callback_sptr update_progress_callback, int required_dfu_time) const; + // The following data member _is_dfu_monitoring_enabled is needed to perform DFU when + // the DFU monitoring is not enabled by FW, for D500 device. + // Its value may be changed to false after the process starts as if the DFU monitoring was + // enabled and the progress feedback that should come from the FW remains 0 after few iterations. + mutable bool _is_dfu_monitoring_enabled = true; }; } diff --git a/src/fw-update/fw-update-device.cpp b/src/fw-update/fw-update-device.cpp index 75141fa3c8..cfa86a3b95 100644 --- a/src/fw-update/fw-update-device.cpp +++ b/src/fw-update/fw-update-device.cpp @@ -146,14 +146,6 @@ namespace librealsense return start + (ceil(progress * threshold) / threshold) * (end - start) / 100.f; } - bool update_device::wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, - std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const - { - // used for devices which get the progress percentage in the GET_DFU_STATUS call - - return true; - } - update_device::update_device( std::shared_ptr< const device_info > const & dev_info, std::shared_ptr< platform::usb_device > const & usb_device, const std::string & product_line ) @@ -251,12 +243,11 @@ namespace librealsense if (sts != platform::RS2_USB_STATUS_SUCCESS) throw std::runtime_error("Failed to send final FW packet"); + dfu_manifest_phase(messenger, update_progress_callback); + } - // measuring the progress of the writing to flash (when enabled by FW) - if (!wait_for_manifest_completion(messenger, RS2_DFU_STATE_DFU_MANIFEST, std::chrono::seconds(200), update_progress_callback)) - throw std::runtime_error("Firmware manifest completion failed"); - - + void update_device::dfu_manifest_phase(const platform::rs_usb_messenger& messenger, rs2_update_progress_callback_sptr update_progress_callback) const + { // After the zero length DFU_DNLOAD request terminates the Transfer // phase, the device is ready to manifest the new firmware. As described // previously, some devices may accumulate the firmware image and perform diff --git a/src/fw-update/fw-update-device.h b/src/fw-update/fw-update-device.h index ac27eab822..6bd18099bb 100644 --- a/src/fw-update/fw-update-device.h +++ b/src/fw-update/fw-update-device.h @@ -146,8 +146,7 @@ namespace librealsense rs2_dfu_state get_dfu_state(std::shared_ptr messenger) const; void detach(std::shared_ptr messenger) const; bool wait_for_state(std::shared_ptr messenger, const rs2_dfu_state state, size_t timeout = 1000) const; - virtual bool wait_for_manifest_completion(std::shared_ptr messenger, const rs2_dfu_state state, - std::chrono::seconds timeout_seconds, rs2_update_progress_callback_sptr update_progress_callback) const; + virtual void dfu_manifest_phase(const platform::rs_usb_messenger& messenger, rs2_update_progress_callback_sptr update_progress_callback) const; void read_device_info(std::shared_ptr messenger); const std::string & get_name() const { return _name; }