Skip to content

Commit

Permalink
PR IntelRealSense#12395 from Nir-Az: FW update aligned for D400/D500
Browse files Browse the repository at this point in the history
  • Loading branch information
Nir-Az authored Nov 15, 2023
2 parents 4bc7e21 + c59029c commit 8f8b01b
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 196 deletions.
36 changes: 14 additions & 22 deletions common/fw-update-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ namespace rs2

_progress = 30;

// Write signed firmware to appropriate file descritptor
// Write signed firmware to appropriate file descriptor
std::ofstream fw_path_in_device(_dev.get_info(RS2_CAMERA_INFO_DFU_DEVICE_PATH), std::ios::binary);
if (fw_path_in_device)
{
Expand Down Expand Up @@ -245,7 +245,7 @@ namespace rs2
}
else
{
log_backup_status = "Back-up camera flash cannot be saved";
log_backup_status = "Backup flash is not supported";
}
}
catch( const std::exception& e )
Expand All @@ -268,7 +268,9 @@ namespace rs2
}
}

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




Expand Down Expand Up @@ -297,6 +299,7 @@ namespace rs2
{
if (serial == d.get_info(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID))
{
log( "DFU device '" + serial + "' found" );
dfu = d;
return true;
}
Expand Down Expand Up @@ -332,29 +335,17 @@ namespace rs2
{
_progress = float(next_progress);

log("Recovery device connected, starting update");
log("Recovery device connected, starting update..\n"
"Internal write is in progress\n"
"Please DO NOT DISCONNECT the camera");

dfu.update(_fw, [&](const float progress)
{
_progress = ((ceil(progress * 10) / 10 * (90 - next_progress)) + next_progress);
});

// D400 devices takes 3 seconds after image transition until DFU process finish.
// D500 only starts the process after the image is transferred and it takes much time..
if( !_is_d500_device )
{
log( "Firmware Download completed, await DFU transition event" );
std::this_thread::sleep_for( std::chrono::seconds( 3 ) );
}
else
{
log( "Firmware Download completed, await DFU transition event\n"
"Internal write is in progress\n"
"Please DO NOT DISCONNECT the camera (might take a few minutes)");
std::this_thread::sleep_for( std::chrono::seconds( 60 ) );
}

log("Firmware Update completed, waiting for device to reconnect");
log( "Firmware Download completed, await DFU transition event" );
std::this_thread::sleep_for( std::chrono::seconds( 3 ) );
}
else
{
Expand Down Expand Up @@ -389,13 +380,14 @@ namespace rs2
}

return false;
}, cleanup, std::chrono::seconds(_is_d500_device ? 120 : 60))) // TODO: HKR DFU issue - increased timeout from 60 to 120 seconds for HKR to complete FW write to flash
}, cleanup, std::chrono::seconds(60)))
{
fail("Original device did not reconnect in time!");
return;
}

log("Device reconnected succesfully!");
log( "Device reconnected successfully!\n"
"FW update process completed successfully" );

_progress = 100;

Expand Down
6 changes: 2 additions & 4 deletions include/librealsense2/h/rs_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ extern "C" {
/**
* Firmware size constants
*/
const int signed_fw_size = 0x18031C;
const int signed_sr300_size = 0x0C025C;
const int unsigned_fw_size = 0x200000;
const int unsigned_sr300_size = 0x100000;
const unsigned int signed_fw_size = 0x18031C;
const unsigned int unsigned_fw_size = 0x200000;

/**
* librealsense Recorder is intended for effective unit-testing
Expand Down
6 changes: 6 additions & 0 deletions src/ds/d400/d400-device.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2016 Intel Corporation. All Rights Reserved.

#include <librealsense2/h/rs_internal.h>
#include <src/device.h>
#include <src/image.h>
#include <src/metadata-parser.h>
Expand Down Expand Up @@ -116,6 +117,11 @@ namespace librealsense

bool d400_device::check_fw_compatibility( const std::vector< uint8_t > & image ) const
{
// check if the given FW size matches the expected FW size
if( ( image.size() != signed_fw_size ) )
throw librealsense::invalid_value_exception(
rsutils::string::from() << "Unsupported firmware binary image provided - " << image.size() << " bytes" );

std::string fw_version = firmware_check_interface::extract_firmware_version_string( image );

auto it = ds::d400_device_to_fw_min_version.find( _pid );
Expand Down
27 changes: 15 additions & 12 deletions src/ds/d400/d400-fw-update-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,28 @@
#include "d400-fw-update-device.h"
#include "d400-private.h"

#include <librealsense2/h/rs_internal.h>

namespace librealsense
{
ds_update_device::ds_update_device( std::shared_ptr< const device_info > const & dev_info,
std::shared_ptr< platform::usb_device > const & usb_device )
: update_device( dev_info, usb_device )
, _product_line( "D400" )
ds_d400_update_device::ds_d400_update_device(
std::shared_ptr< const device_info > const & dev_info,
std::shared_ptr< platform::usb_device > const & usb_device )
: update_device( dev_info, usb_device, "D400" )
{
auto info = usb_device->get_info();
_name = ds::rs400_sku_names.find(info.pid) != ds::rs400_sku_names.end() ? ds::rs400_sku_names.at(info.pid) : "unknown";
auto info = usb_device->get_info();
_name = ds::rs400_sku_names.find(info.pid) != ds::rs400_sku_names.end() ? ds::rs400_sku_names.at(info.pid) : "unknown";
_serial_number = parse_serial_number(_serial_number_buffer);
}

void ds_update_device::update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr callback) const
{
update_device::update(fw_image, fw_image_size, callback);
}

bool ds_update_device::check_fw_compatibility(const std::vector<uint8_t>& image) const
bool ds_d400_update_device::check_fw_compatibility(const std::vector<uint8_t>& image) const
{
// check if the given FW size matches the expected FW size
if( image.size() != signed_fw_size )
throw librealsense::invalid_value_exception(
rsutils::string::from() << "Unsupported firmware binary image provided - " << image.size() << " bytes" );

std::string fw_version = extract_firmware_version_string(image);
auto it = ds::d400_device_to_fw_min_version.find(_usb_device->get_info().pid);
if (it == ds::d400_device_to_fw_min_version.end())
Expand All @@ -36,7 +39,7 @@ ds_update_device::ds_update_device( std::shared_ptr< const device_info > const &
return result;
}

std::string ds_update_device::parse_serial_number(const std::vector<uint8_t>& buffer) const
std::string ds_d400_update_device::parse_serial_number(const std::vector<uint8_t>& buffer) const
{
if (buffer.size() != sizeof(serial_number_data))
throw std::runtime_error("DFU - failed to parse serial number!");
Expand Down
19 changes: 5 additions & 14 deletions src/ds/d400/d400-fw-update-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,16 @@

namespace librealsense
{
class ds_update_device : public update_device
class ds_d400_update_device : public update_device
{
public:
ds_update_device( std::shared_ptr< const device_info > const &,
std::shared_ptr< platform::usb_device > const & usb_device );
virtual ~ds_update_device() = default;
ds_d400_update_device( std::shared_ptr< const device_info > const &,
std::shared_ptr< platform::usb_device > const & usb_device );
virtual ~ds_d400_update_device() = default;

void update(const void* fw_image, int fw_image_size, rs2_update_progress_callback_sptr = nullptr) const override;
virtual bool check_fw_compatibility(const std::vector<uint8_t>& image) const override;

protected:
virtual const std::string& get_name() const override { return _name; }
virtual const std::string& get_product_line() const override { return _product_line; }
virtual const std::string& get_serial_number() const override { return _serial_number; }
std::string parse_serial_number(const std::vector<uint8_t>& buffer) const;

private:
std::string _name;
std::string _product_line;
std::string _serial_number;
std::string parse_serial_number(const std::vector<uint8_t>& buffer) const;
};
}
12 changes: 6 additions & 6 deletions src/ds/d400/d400-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ namespace librealsense
const uint16_t RS430_PID = 0x0ad4; // AWG
const uint16_t RS430_MM_PID = 0x0ad5; // AWGT
const uint16_t RS_USB2_PID = 0x0ad6; // USB2
const uint16_t RS_RECOVERY_PID = 0x0adb;
const uint16_t RS_USB2_RECOVERY_PID = 0x0adc;
const uint16_t RS_D400_RECOVERY_PID = 0x0adb;
const uint16_t RS_D400_USB2_RECOVERY_PID = 0x0adc;
const uint16_t RS400_IMU_PID = 0x0af2; // IMU
const uint16_t RS420_PID = 0x0af6; // PWG
const uint16_t RS420_MM_PID = 0x0afe; // PWGT
Expand Down Expand Up @@ -111,8 +111,8 @@ namespace librealsense
{ RS430_PID, "Intel RealSense D430"},
{ RS430_MM_PID, "Intel RealSense D430 with Tracking Module"},
{ RS_USB2_PID, "Intel RealSense USB2" },
{ RS_RECOVERY_PID, "Intel RealSense D4XX Recovery"},
{ RS_USB2_RECOVERY_PID, "Intel RealSense D4XX USB2 Recovery"},
{ RS_D400_RECOVERY_PID, "Intel RealSense D4XX Recovery"},
{ RS_D400_USB2_RECOVERY_PID, "Intel RealSense D4XX USB2 Recovery"},
{ RS400_IMU_PID, "Intel RealSense IMU" },
{ RS420_PID, "Intel RealSense D420"},
{ RS420_MM_PID, "Intel RealSense D420 with Tracking Module"},
Expand All @@ -139,8 +139,8 @@ namespace librealsense
{RS430_PID, "5.8.15.0"},
{RS430_MM_PID, "5.8.15.0"},
{RS_USB2_PID, "5.8.15.0"},
{RS_RECOVERY_PID, "5.8.15.0"},
{RS_USB2_RECOVERY_PID, "5.8.15.0"},
{RS_D400_RECOVERY_PID, "5.8.15.0"},
{RS_D400_USB2_RECOVERY_PID, "5.8.15.0"},
{RS400_IMU_PID, "5.8.15.0"},
{RS420_PID, "5.8.15.0"},
{RS420_MM_PID, "5.8.15.0"},
Expand Down
2 changes: 2 additions & 0 deletions src/ds/d500/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ target_sources(${LRS_TARGET}
"${CMAKE_CURRENT_LIST_DIR}/d500-factory.cpp"
"${CMAKE_CURRENT_LIST_DIR}/hw_monitor_extended_buffers.cpp"
"${CMAKE_CURRENT_LIST_DIR}/d500-options.cpp"
"${CMAKE_CURRENT_LIST_DIR}/d500-fw-update-device.cpp"
"${CMAKE_CURRENT_LIST_DIR}/d500-device.h"
"${CMAKE_CURRENT_LIST_DIR}/d500-color.h"
"${CMAKE_CURRENT_LIST_DIR}/d500-motion.h"
Expand All @@ -18,4 +19,5 @@ target_sources(${LRS_TARGET}
"${CMAKE_CURRENT_LIST_DIR}/hw_monitor_extended_buffers.h"
"${CMAKE_CURRENT_LIST_DIR}/d500-options.h"
"${CMAKE_CURRENT_LIST_DIR}/d500-info.h"
"${CMAKE_CURRENT_LIST_DIR}/d500-fw-update-device.h"
)
18 changes: 2 additions & 16 deletions src/ds/d500/d500-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ namespace librealsense

void d500_device::update_flash(const std::vector<uint8_t>& image, rs2_update_progress_callback_sptr callback, int update_mode)
{
_ds_device_common->update_flash(image, callback, update_mode);
throw not_implemented_exception("D500 device does not support unsigned FW update");
}

class d500_depth_sensor : public synthetic_sensor, public video_sensor_interface, public depth_stereo_sensor, public roi_sensor_base
Expand Down Expand Up @@ -583,21 +583,7 @@ namespace librealsense

if ((_device_capabilities & ds_caps::CAP_INTERCAM_HW_SYNC) == ds_caps::CAP_INTERCAM_HW_SYNC)
{
if ((_device_capabilities & ds_caps::CAP_GLOBAL_SHUTTER) == ds_caps::CAP_GLOBAL_SHUTTER)
{
depth_sensor.register_option(RS2_OPTION_INTER_CAM_SYNC_MODE,
std::make_shared<external_sync_mode>(*_hw_monitor, &raw_depth_sensor, 3));
}
else if ((_device_capabilities & ds_caps::CAP_GLOBAL_SHUTTER) == ds_caps::CAP_GLOBAL_SHUTTER)
{
depth_sensor.register_option(RS2_OPTION_INTER_CAM_SYNC_MODE,
std::make_shared<external_sync_mode>(*_hw_monitor, &raw_depth_sensor, 2));
}
else
{
depth_sensor.register_option(RS2_OPTION_INTER_CAM_SYNC_MODE,
std::make_shared<external_sync_mode>(*_hw_monitor, &raw_depth_sensor, 1));
}
// Register RS2_OPTION_INTER_CAM_SYNC_MODE here if needed
}

roi_sensor_interface* roi_sensor = dynamic_cast<roi_sensor_interface*>(&depth_sensor);
Expand Down
59 changes: 59 additions & 0 deletions src/ds/d500/d500-fw-update-device.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2023 Intel Corporation. All Rights Reserved.

#include "d500-fw-update-device.h"
#include "d500-private.h"


namespace librealsense
{
ds_d500_update_device::ds_d500_update_device( std::shared_ptr< const device_info > const & dev_info,
std::shared_ptr< platform::usb_device > const & usb_device )
: update_device( dev_info, usb_device, "D500" )
{
auto info = usb_device->get_info();
_name = ds::rs500_sku_names.find(info.pid) != ds::rs500_sku_names.end() ? ds::rs500_sku_names.at(info.pid) : "unknown";
_serial_number = parse_serial_number(_serial_number_buffer);
}


bool ds_d500_update_device::check_fw_compatibility(const std::vector<uint8_t>& image) const
{
// Currently we cannot extract FW version from HKR FW image
bool result = true;

// TODO::: Once verified we can check against the minimal FW version map
std::string fw_version = extract_firmware_version_string(image);
LOG_INFO( "FW version extracted from the FW image is" + fw_version );

return result;
}

std::string ds_d500_update_device::parse_serial_number(const std::vector<uint8_t>& buffer) const
{
if (buffer.size() != sizeof(serial_number_data))
throw std::runtime_error("DFU - failed to parse serial number!");

std::stringstream rv;
for (auto i = 0; i < ds::module_serial_size; i++)
rv << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(buffer[i]);

return rv.str();
}

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++)
{
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)));
}
}
}
23 changes: 23 additions & 0 deletions src/ds/d500/d500-fw-update-device.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2023 Intel Corporation. All Rights Reserved.

#pragma once

#include "fw-update/fw-update-device.h"

namespace librealsense
{
class ds_d500_update_device : public update_device
{
public:
ds_d500_update_device( std::shared_ptr< const device_info > const &,
std::shared_ptr< platform::usb_device > const & usb_device );
virtual ~ds_d500_update_device() = default;

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;

private:
std::string parse_serial_number(const std::vector<uint8_t>& buffer) const;
};
}
10 changes: 10 additions & 0 deletions src/ds/ds-device-common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "proc/temporal-filter.h"

#include <src/backend.h>
#include <librealsense2/h/rs_internal.h>

namespace librealsense
{
Expand Down Expand Up @@ -256,6 +257,15 @@ namespace librealsense

void ds_device_common::update_flash(const std::vector<uint8_t>& image, rs2_update_progress_callback_sptr callback, int update_mode)
{
// check if the given FW size matches the expected FW size
if( image.size() != unsigned_fw_size )
{
throw librealsense::invalid_value_exception( rsutils::string::from()
<< "Unsupported firmware binary image (unsigned) provided - "
<< image.size() << " bytes" );
}


if (_is_locked)
throw std::runtime_error("this camera is locked and doesn't allow direct flash write, for firmware update use rs2_update_firmware method (DFU)");

Expand Down
Loading

0 comments on commit 8f8b01b

Please sign in to comment.