Skip to content

Commit

Permalink
PR IntelRealSense#12964 from remibettan: d500-dfu
Browse files Browse the repository at this point in the history
D500 DFU - cleaning d400 fw update code, avoid stucking of d500 w/o dfu monitoring
  • Loading branch information
remibettan authored May 28, 2024
2 parents 1f167f8 + 9e5c5a1 commit 41c47c6
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 20 deletions.
2 changes: 1 addition & 1 deletion common/fw-update-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ namespace rs2
if ( !log_backup_status.empty() )
log(log_backup_status);

next_progress = _progress + 10;
next_progress = static_cast<int>(_progress) + 10;

if (_is_signed)
{
Expand Down
59 changes: 57 additions & 2 deletions src/ds/d500/d500-fw-update-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<platform::usb_messenger> messenger, const rs2_dfu_state state,
Expand All @@ -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);
Expand All @@ -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()) {
Expand All @@ -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<float>(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<float>(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<int>(iteration_sleep_time_ms)));
}
}
else
std::this_thread::sleep_for(std::chrono::seconds(required_dfu_time));
}
}
11 changes: 9 additions & 2 deletions src/ds/d500/d500-fw-update-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@ namespace librealsense

virtual bool check_fw_compatibility(const std::vector<uint8_t>& 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<platform::usb_messenger> 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<platform::usb_messenger> 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<uint8_t>& 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;
};
}
17 changes: 4 additions & 13 deletions src/fw-update/fw-update-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<platform::usb_messenger> 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 )
Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/fw-update/fw-update-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ namespace librealsense
rs2_dfu_state get_dfu_state(std::shared_ptr<platform::usb_messenger> messenger) const;
void detach(std::shared_ptr<platform::usb_messenger> messenger) const;
bool wait_for_state(std::shared_ptr<platform::usb_messenger> messenger, const rs2_dfu_state state, size_t timeout = 1000) const;
virtual bool wait_for_manifest_completion(std::shared_ptr<platform::usb_messenger> 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<platform::usb_messenger> messenger);

const std::string & get_name() const { return _name; }
Expand Down

0 comments on commit 41c47c6

Please sign in to comment.