Skip to content

Commit

Permalink
PR #12948 from remibettan: d500_dfu
Browse files Browse the repository at this point in the history
D500 dfu
  • Loading branch information
remibettan authored May 26, 2024
2 parents 10a8784 + 4e26e93 commit 009bb25
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 19 deletions.
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;

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());

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));

auto curr = std::chrono::system_clock::now();
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)
throw std::invalid_argument("Avoid division by zero");
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 @@ -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);
}
}

// 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

0 comments on commit 009bb25

Please sign in to comment.