Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add D500 DFU progress monitoring support #12948

Merged
merged 8 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions common/fw-update-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,8 @@ namespace rs2

if ( !log_backup_status.empty() )
log(log_backup_status);




next_progress = 40;
next_progress = _progress + 10;

if (_is_signed)
{
Expand Down
70 changes: 59 additions & 11 deletions src/ds/d500/d500-fw-update-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,65 @@ 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 );

static constexpr float D500_FW_DFU_TIME = 180.0; // [sec]
// We calculate the sleep time needed for each cycle to get to 100% progress bar
// On D500 devices after transferring the FW image the internal DFU progress start on the device
float iteration_sleep_time_ms = (static_cast<float>(D500_FW_DFU_TIME) / 100.0f) * 1000.0f;
for(int i = 1; i <= 100; i++)
{
update_device::update( fw_image, fw_image_size, update_progress_callback );
}

bool ds_d500_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
{
std::chrono::seconds elapsed_seconds;
auto start = std::chrono::system_clock::now();
rs2_dfu_state dfu_state = RS2_DFU_STATE_APP_IDLE;
dfu_status_payload status;
int percentage_of_transfer = 0;
int iteration = 0;
// progress should start increase even in the 2nd iteration,
// when this DFU progress is enabled by FW
int max_iteration_number_for_progress_start = 10;
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved

do {
uint32_t transferred = 0;
auto sts = messenger->control_transfer(0xa1 /*DFU_GETSTATUS_PACKET*/, RS2_DFU_GET_STATUS, 0, 0, (uint8_t*)&status, sizeof(status), transferred, 5000);
dfu_state = status.get_state();
percentage_of_transfer = static_cast<int>(status.iString);

// 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 &&
++iteration == max_iteration_number_for_progress_start)
return true;

std::stringstream ss;
ss << "DFU_GETSTATUS called, state is: " << to_string(dfu_state);
ss << ", iString equals: " << percentage_of_transfer << ", and bwPollTimeOut equals: " << status.bwPollTimeout << std::endl;
LOG_DEBUG(ss.str().c_str());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use stringstream here and not just do the output inside the LOG_DEBUG?


if (update_progress_callback)
update_progress_callback->on_update_progress( i / 100.f );
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(iteration_sleep_time_ms)));
}
{
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);
}

if (sts != platform::RS2_USB_STATUS_SUCCESS)
LOG_DEBUG("control xfer error: " << platform::usb_status_to_string[sts]);

//test for dfu error state
if (status.is_error_state()) {
return false;
}

// FW doesn't set the bwPollTimeout value, therefore it is wrong to use status.bwPollTimeout
std::this_thread::sleep_for(std::chrono::seconds(1));
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved

auto curr = std::chrono::system_clock::now();
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved
elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>(curr - start);
if (elapsed_seconds > timeout_seconds)
{
LOG_ERROR("DFU in MANIFEST STATUS Timeout");
return false;
}
} while (percentage_of_transfer < 100 && dfu_state == RS2_DFU_STATE_DFU_MANIFEST);

return true;
}
}
2 changes: 2 additions & 0 deletions src/ds/d500/d500-fw-update-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ 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;

private:
std::string parse_serial_number(const std::vector<uint8_t>& buffer) const;
Expand Down
57 changes: 54 additions & 3 deletions src/fw-update/fw-update-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#include <algorithm>
#include <thread>

#define DEFAULT_TIMEOUT 100
#define FW_UPDATE_INTERFACE_NUMBER 0
namespace librealsense
{
std::string get_formatted_fw_version(uint32_t fw_last_version)
Expand Down Expand Up @@ -81,6 +79,35 @@ namespace librealsense
LOG_INFO("DFU status: " << lock_status << " , DFU version is: " << payload.dfu_version);
}

std::string update_device::to_string(rs2_dfu_state state) const
{
switch (state)
{
case(RS2_DFU_STATE_APP_IDLE):
return "APP_IDLE";
case(RS2_DFU_STATE_APP_DETACH):
return "APP_DETACH";
case(RS2_DFU_STATE_DFU_DOWNLOAD_SYNC):
return "DFU_DOWNLOAD_SYNC";
case(RS2_DFU_STATE_DFU_DOWNLOAD_BUSY):
return "DFU_DOWNLOAD_BUSY";
case(RS2_DFU_STATE_DFU_DOWNLOAD_IDLE):
return "DFU_DOWNLOAD_IDLE";
case(RS2_DFU_STATE_DFU_MANIFEST_SYNC):
return "DFU_MANIFEST_SYNC";
case(RS2_DFU_STATE_DFU_MANIFEST):
return "DFU_MANIFEST";
case(RS2_DFU_STATE_DFU_MANIFEST_WAIT_RESET):
return "DFU_MANIFEST_WAIT_RESET";
case(RS2_DFU_STATE_DFU_UPLOAD_IDLE):
return "DFU_UPLOAD_IDLE";
case(RS2_DFU_STATE_DFU_ERROR):
return "DFU_ERROR";
default:
return "DFU_STATE_???";
}
}

bool update_device::wait_for_state(std::shared_ptr<platform::usb_messenger> messenger, const rs2_dfu_state state, size_t timeout) const
{
std::chrono::milliseconds elapsed_milliseconds;
Expand Down Expand Up @@ -112,6 +139,21 @@ namespace librealsense
return false;
}

float update_device::compute_progress(float progress, float start, float end, float threshold) const
{
if (threshold < 1.f && threshold > -1.f)
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved
throw std::invalid_argument("Avoid division by zero");
return start + (ceil(progress * threshold) / threshold) * (end - start) / 100.f;
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved
}

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;
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved
}

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 @@ -195,7 +237,10 @@ namespace librealsense
float progress = (float)block_number / (float)blocks_count;
LOG_DEBUG("fw update progress: " << progress);
if (update_progress_callback)
update_progress_callback->on_update_progress(progress);
{
auto progress_for_bar = compute_progress(progress, 0.f, 20.f, 5.f) / 100.f;
update_progress_callback->on_update_progress(progress_for_bar);
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved
}
}

// After the final block of firmware has been sent to the device and the status solicited, the host sends a
Expand All @@ -206,6 +251,12 @@ namespace librealsense
if (sts != platform::RS2_USB_STATUS_SUCCESS)
throw std::runtime_error("Failed to send final FW packet");


// 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
Expand Down
8 changes: 7 additions & 1 deletion src/fw-update/fw-update-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,19 @@ 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;
void read_device_info(std::shared_ptr<platform::usb_messenger> messenger);

const std::string & get_name() const { return _name; }
const std::string & get_product_line() const { return _product_line; }
const std::string & get_serial_number() const { return _serial_number; }
std::string to_string(platform::usb_status state) const;
std::string to_string(rs2_dfu_state state) const;
float compute_progress(float progress, float start, float end, float threshold) const;


const int DEFAULT_TIMEOUT = 100;
const int FW_UPDATE_INTERFACE_NUMBER = 0;
const std::shared_ptr< const device_info > _dev_info;
const platform::rs_usb_device _usb_device;
std::vector<uint8_t> _serial_number_buffer;
Expand Down
Loading