Device: Allow skipping of device state refreshing on call to open

This commit is contained in:
Max Brombach
2026-11-03 11:20:04 -05:00
committed by Kyle Schwarz
parent dffb0bcefb
commit 645549193d
21 changed files with 124 additions and 166 deletions
+13 -13
View File
@@ -111,7 +111,7 @@ static bool runPipeline(
icsneo::Device& device,
const BootloaderPipeline& pipeline,
const FWRepo& fw,
const Logger& logger,
const StatusHandler& statusHandler,
bool alreadyInBootloader,
bool forceFlash
) {
@@ -167,7 +167,7 @@ static bool runPipeline(
auto com = getCommunication(device, flashPhase, info);
if(!withCommunication(com.get(), info, "FlashPhase", [&](Bootloader::Communication& opened) {
if(!opened.flash(fw, logger)) {
if(!opened.flash(fw, statusHandler)) {
Log::Error("FlashPhase", "failed to flash " + chipString(flashPhase.chip));
return false;
}
@@ -257,13 +257,13 @@ static bool runPipeline(
}
}
}
return exitBootloader(device, logger, !chipsFlashed.empty());
return exitBootloader(device, statusHandler, !chipsFlashed.empty());
}
bool Bootloader::update(
icsneo::Device& device,
const FWRepo& fw,
Logger logger,
StatusHandler statusHandler,
bool alreadyInBootloader,
bool forceFlash
) {
@@ -273,7 +273,7 @@ bool Bootloader::update(
return false;
}
if(!runPipeline(device, pipeline, fw, logger, alreadyInBootloader, forceFlash)) {
if(!runPipeline(device, pipeline, fw, statusHandler, alreadyInBootloader, forceFlash)) {
device.getEventHandler()(APIEvent::Type::FirmwareUpdateFailed, APIEvent::Severity::Error);
return false;
}
@@ -287,19 +287,19 @@ bool Bootloader::enterBootloader(icsneo::Device& device) {
return device.reconnect(std::chrono::milliseconds(30000));
}
bool Bootloader::exitBootloader(icsneo::Device& device, Logger logger, bool updatedChips) {
bool Bootloader::exitBootloader(icsneo::Device& device, StatusHandler statusHandler, bool updatedChips) {
if(!updatedChips) {
return true;
}
logger(icsneo::Device::OpenStatusType::Progress, "Connecting to the device...", std::nullopt);
return verifyConnection(device, logger);
statusHandler(StatusType::Progress, "Connecting to the device...", std::nullopt);
return verifyConnection(device, statusHandler);
}
/**
* Toggle network communication and wait up to 5 seconds for a reset status confirming the change.
* Like icsneo::Device::goOnline(), a timeout is not an error.
*/
static bool setCommunicationEnabled(icsneo::Device& device, const Logger& logger, bool enable, double progressStart) {
static bool setCommunicationEnabled(icsneo::Device& device, const StatusHandler& statusHandler, bool enable, double progressStart) {
static constexpr std::chrono::seconds Timeout(5);
const auto filter = std::make_shared<MessageFilter>(Message::Type::ResetStatus);
@@ -329,16 +329,16 @@ static bool setCommunicationEnabled(icsneo::Device& device, const Logger& logger
}
// Each call covers half of the overall progress
logger(icsneo::Device::OpenStatusType::Progress, "Connecting to the device...", progressStart + (elapsedTime / Timeout) / 2.0);
statusHandler(StatusType::Progress, "Connecting to the device...", progressStart + (elapsedTime / Timeout) / 2.0);
elapsedTime = std::chrono::steady_clock::now() - startTime;
}
logger(icsneo::Device::OpenStatusType::Progress, "Connecting to the device...", progressStart + 0.5);
statusHandler(StatusType::Progress, "Connecting to the device...", progressStart + 0.5);
return true;
}
bool Bootloader::verifyConnection(icsneo::Device& device, Logger logger) {
bool Bootloader::verifyConnection(icsneo::Device& device, StatusHandler statusHandler) {
// Firmware needs to confirm the update by verifying that it can enable/disable the connection on the device
return setCommunicationEnabled(device, logger, true, 0.0) && setCommunicationEnabled(device, logger, false, 0.5);
return setCommunicationEnabled(device, statusHandler, true, 0.0) && setCommunicationEnabled(device, statusHandler, false, 0.5);
}
bool Bootloader::isSFPChip(const icsneo::Bootloader::Chip& chip) {
@@ -38,7 +38,7 @@ bool Application::finalize() {
return ok;
}
bool Application::flash(const FWRepo& fw, const icsneo::Device::OpenStatusHandler& handler) {
bool Application::flash(const FWRepo& fw, const icsneo::Bootloader::StatusHandler& handler) {
Log::Info(__func__, "starting flash for " + targetChip.getName());
const auto& srcVer = fw.getVersion();
@@ -55,7 +55,7 @@ bool Application::flash(const FWRepo& fw, const icsneo::Device::OpenStatusHandle
}
auto currentString = "Preparing to update " + targetChip.getName() + "...";
handler(icsneo::Device::OpenStatusType::Progress, currentString, std::nullopt);
handler(StatusType::Progress, currentString, std::nullopt);
// The supplied IEF is not for this product
if(ief.getVersion().prodId != static_cast<uint8_t>(device.getProductID())) {
@@ -132,10 +132,10 @@ bool Application::validateFirmware(const DeviceAppVersion& chipSrcVer) {
return sendCommand(Update::CheckComponentVersion, [](double) {}, 0, {chipSrcVer.major, chipSrcVer.minor});
}
bool Application::sendSoftware(const std::vector<uint8_t>& bin, const icsneo::Device::OpenStatusHandler& handler) {
bool Application::sendSoftware(const std::vector<uint8_t>& bin, const icsneo::Bootloader::StatusHandler& handler) {
Log::Debug(__func__, "starting for " + targetChip.getName() + " (" + std::to_string(bin.size()) + " bytes)");
auto currentString = "Preparing to update " + targetChip.getName() + "...";
handler(icsneo::Device::OpenStatusType::Progress, currentString, std::nullopt);
handler(StatusType::Progress, currentString, std::nullopt);
if(bin.empty() || bin.size() > std::numeric_limits<uint32_t>::max()) {
Log::Error(__func__, "invalid firmware size for " + targetChip.getName());
return false;
@@ -144,14 +144,14 @@ bool Application::sendSoftware(const std::vector<uint8_t>& bin, const icsneo::De
Log::Debug(__func__, "erasing " + targetChip.getName());
if(!sendCommand(Update::Erase, 0, totalSize, [&](double progress) {
handler(icsneo::Device::OpenStatusType::Progress, currentString, progress);
handler(StatusType::Progress, currentString, progress);
}, std::chrono::milliseconds(45000))) {
Log::Error(__func__, "erase failed for " + targetChip.getName());
return false;
}
currentString = "Updating " + targetChip.getName() + "...";
handler(icsneo::Device::OpenStatusType::Progress, currentString, std::nullopt);
handler(StatusType::Progress, currentString, std::nullopt);
const uint32_t stepSize = std::min<uint32_t>(totalSize, 2048);
uint32_t bytesTransferred = 0;
@@ -163,7 +163,7 @@ bool Application::sendSoftware(const std::vector<uint8_t>& bin, const icsneo::De
}
bytesTransferred += bytesToSend;
handler(icsneo::Device::OpenStatusType::Progress, currentString, double(bytesTransferred) / totalSize);
handler(StatusType::Progress, currentString, double(bytesTransferred) / totalSize);
}
Log::Debug(__func__, "write complete, validating " + targetChip.getName());
if(!validateComponent()) {
@@ -174,7 +174,7 @@ bool Application::sendSoftware(const std::vector<uint8_t>& bin, const icsneo::De
return true;
}
bool Application::sendSoftware(const std::vector<IEF::Sector>& sectorPairs, uint32_t blockSize, const icsneo::Device::OpenStatusHandler& handler) {
bool Application::sendSoftware(const std::vector<IEF::Sector>& sectorPairs, uint32_t blockSize, const icsneo::Bootloader::StatusHandler& handler) {
if(sectorPairs.empty()) {
Log::Error(__func__, "no sectors to flash for " + targetChip.getName());
return false;
@@ -182,7 +182,7 @@ bool Application::sendSoftware(const std::vector<IEF::Sector>& sectorPairs, uint
Log::Debug(__func__, "starting for " + targetChip.getName() + " (" + std::to_string(sectorPairs.size()) + " sectors)");
auto currentString = "Preparing to update " + targetChip.getName() + "...";
handler(icsneo::Device::OpenStatusType::Progress, currentString, std::nullopt);
handler(StatusType::Progress, currentString, std::nullopt);
uint64_t totalSize = 0;
for(const auto& sector : sectorPairs) {
totalSize += sector.second.size();
@@ -199,7 +199,7 @@ bool Application::sendSoftware(const std::vector<IEF::Sector>& sectorPairs, uint
Log::Debug(__func__, "erasing " + targetChip.getName() + " (" + std::to_string(totalSize) + " bytes)");
if(!sendCommand(Update::Erase, 0, static_cast<uint32_t>(totalSize), [&](double progress) {
handler(icsneo::Device::OpenStatusType::Progress, currentString, progress);
handler(StatusType::Progress, currentString, progress);
}, std::chrono::milliseconds(45000))) {
Log::Error(__func__, "erase failed for " + targetChip.getName());
return false;
@@ -212,7 +212,7 @@ bool Application::sendSoftware(const std::vector<IEF::Sector>& sectorPairs, uint
}
currentString = "Updating " + targetChip.getName() + "...";
handler(icsneo::Device::OpenStatusType::Progress, currentString, std::nullopt);
handler(StatusType::Progress, currentString, std::nullopt);
uint32_t bytesTransferred = 0;
for(const auto& pair : sectorPairs) {
@@ -233,7 +233,7 @@ bool Application::sendSoftware(const std::vector<IEF::Sector>& sectorPairs, uint
}
bytesTransferred += static_cast<uint32_t>(rawData.size());
handler(icsneo::Device::OpenStatusType::Progress, currentString, double(bytesTransferred) / double(totalSize));
handler(StatusType::Progress, currentString, double(bytesTransferred) / double(totalSize));
}
Log::Debug(__func__, "write complete, validating " + targetChip.getName());
bool ok = validateComponent();
@@ -264,7 +264,7 @@ bool Application::validateComponent() {
* passes. Progress replies are OperationPending with a SoftwareUpdateCommandHeader whose
* commandSizeOrProgress holds the progress so far, or a GenericReturn with no progress.
*/
bool Application::sendCommand(Update command, uint32_t offset, uint32_t length, const StatusHandler& handler, std::chrono::milliseconds timeout, std::vector<uint8_t> args) {
bool Application::sendCommand(Update command, uint32_t offset, uint32_t length, const CommandStatusHandler& handler, std::chrono::milliseconds timeout, std::vector<uint8_t> args) {
bool finishedResponse = false;
std::condition_variable finishedResponseCV;
std::mutex finishedResponseMutex;
@@ -323,8 +323,8 @@ bool RADCommunication::sendSoftware(const std::vector<uint8_t>& chipSoftware) {
size_t remainingBytes = chipSoftware.size();
size_t currentlyReading = 0;
logger(
icsneo::Device::OpenStatusType::Progress,
statusHandler(
StatusType::Progress,
"Flashing " + targetChip.getName() + "...",
std::nullopt
);
@@ -332,8 +332,8 @@ bool RADCommunication::sendSoftware(const std::vector<uint8_t>& chipSoftware) {
while(remainingBytes > 0) {
const double progress = static_cast<double>(currentlyReading) / static_cast<double>(chipSoftware.size());
logger(
icsneo::Device::OpenStatusType::Progress,
statusHandler(
StatusType::Progress,
"Flashing " + targetChip.getName() + "...",
progress
);
@@ -407,8 +407,8 @@ bool RADCommunication::sendSoftware(const std::vector<uint8_t>& chipSoftware) {
}
}
logger(
icsneo::Device::OpenStatusType::Progress,
statusHandler(
StatusType::Progress,
"Flashing " + targetChip.getName() + "...",
1.0
);
@@ -431,8 +431,8 @@ bool RADCommunication::getProgrammingStatus(size_t sizeToValidate) {
uint32_t status = 0;
const auto beginTime = std::chrono::steady_clock::now();
logger(
icsneo::Device::OpenStatusType::Progress,
statusHandler(
StatusType::Progress,
"Programming " + targetChip.getName() + "...",
std::nullopt
);
@@ -440,8 +440,8 @@ bool RADCommunication::getProgrammingStatus(size_t sizeToValidate) {
while(status < static_cast<uint32_t>(sizeToValidate)) {
const double progress = static_cast<double>(status) / static_cast<double>(sizeToValidate);
logger(
icsneo::Device::OpenStatusType::Progress,
statusHandler(
StatusType::Progress,
"Programming " + targetChip.getName() + "...",
progress
);
@@ -457,8 +457,8 @@ bool RADCommunication::getProgrammingStatus(size_t sizeToValidate) {
}
}
logger(
icsneo::Device::OpenStatusType::Progress,
statusHandler(
StatusType::Progress,
"Programming " + targetChip.getName() + "...",
1.0
);
@@ -510,7 +510,7 @@ bool RADCommunication::loadZips(const FWRepo& fw, std::vector<uint8_t>& chipSoft
return false;
}
bool RADCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusHandler& handler) {
bool RADCommunication::flash(const FWRepo& fw, const icsneo::Bootloader::StatusHandler& handler) {
Log::Info(__func__, "starting flash for " + targetChip.getName());
auto chipSrcVer = fw.getChipVersion(targetChip.getIEFName());
if(!chipSrcVer) {
@@ -524,7 +524,7 @@ bool RADCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusH
return false;
}
logger = handler;
statusHandler = handler;
if(!validateChipVersion(*chipSrcVer)) {
Log::Error(__func__, "validateChipVersion failed for " + targetChip.getName());
return false;
@@ -41,7 +41,7 @@ bool RADMultiChipCommunication::authenticate() {
return true;
}
bool RADMultiChipCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusHandler& handler) {
bool RADMultiChipCommunication::flash(const FWRepo& fw, const icsneo::Bootloader::StatusHandler& handler) {
Log::Info(__func__, "starting flash for " + targetChip.getName());
auto chipSrcVer = fw.getChipVersion(targetChip.getIEFName());
if(!chipSrcVer) {
@@ -56,7 +56,7 @@ bool RADMultiChipCommunication::flash(const FWRepo& fw, const icsneo::Device::Op
if(!standardComm->validateFirmware(*chipSrcVer)) {
Log::Error(__func__, "firmware validation failed for " + targetChip.getName());
handler(icsneo::Device::OpenStatusType::Failed, "Failed to validate firmware", std::nullopt);
handler(StatusType::Failed, "Failed to validate firmware", std::nullopt);
return false;
}
@@ -103,7 +103,7 @@ bool RADMultiChipCommunication::flash(const FWRepo& fw, const icsneo::Device::Op
return false;
}
Log::Debug(__func__, "finalize successful, proceeding to reboot");
handler(icsneo::Device::OpenStatusType::Progress, "Rebooting device...", std::nullopt);
handler(StatusType::Progress, "Rebooting device...", std::nullopt);
return true;
}
@@ -180,7 +180,7 @@ bool RADPeriphCommunication::flashSector(const IEF::Sector& sector) {
return sendRequest(Request::FlashSector, std::move(args), std::chrono::milliseconds(3000));
}
bool RADPeriphCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusHandler& handler) {
bool RADPeriphCommunication::flash(const FWRepo& fw, const icsneo::Bootloader::StatusHandler& handler) {
// Validate the firmware before touching the device so a bad file can not leave it erased
std::vector<uint8_t> bin;
if(!fw.getFW(targetChip.getIEFName(), bin)) {
@@ -228,7 +228,7 @@ bool RADPeriphCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenS
}
handler(
icsneo::Device::OpenStatusType::Progress,
StatusType::Progress,
"Flashing " + targetChip.getName() + "...",
std::nullopt
);
@@ -242,7 +242,7 @@ bool RADPeriphCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenS
sizeFlashed += static_cast<uint32_t>(sector.second.size());
handler(
icsneo::Device::OpenStatusType::Progress,
StatusType::Progress,
"Flashing " + targetChip.getName() + "...",
(double)sizeFlashed / (double)totalSize
);
@@ -113,7 +113,7 @@ bool REDCommunication::getVersion() {
return true;
}
bool REDCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusHandler& handler) {
bool REDCommunication::flash(const FWRepo& fw, const icsneo::Bootloader::StatusHandler& handler) {
const auto& srcVer = fw.getVersion();
std::vector<uint8_t> bin;
@@ -152,7 +152,7 @@ bool REDCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusH
}
}
handler(icsneo::Device::OpenStatusType::Progress,
handler(StatusType::Progress,
"Preparing to update " + targetChip.getName() + "...", std::nullopt);
Log::Debug(__func__, "Erasing " + targetChip.getName());
if(!sendCommand(uint8_t(Command::Erase), std::chrono::seconds(45))) {
@@ -164,7 +164,7 @@ bool REDCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusH
size_t sectorsFlashed = 0;
for(const auto& [id, sector] : sectorPairs) {
Log::Trace(__func__, "Flashing sector " + std::to_string(id));
handler(icsneo::Device::OpenStatusType::Progress,
handler(StatusType::Progress,
"Updating " + targetChip.getName() + "...",
double(sectorsFlashed++) / sectorPairs.size());
@@ -205,11 +205,11 @@ bool REDCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusH
}
// Tell the application that we flashed 100%
handler(icsneo::Device::OpenStatusType::Progress,
handler(StatusType::Progress,
"Updating " + targetChip.getName() + "...",
1.0);
handler(icsneo::Device::OpenStatusType::Progress, "Finalizing update...", std::nullopt);
handler(StatusType::Progress, "Finalizing update...", std::nullopt);
if(!sendCommand(uint8_t(Command::ValidateFirmware))) {
Log::Error(__func__, "Firmware validation failed for " + targetChip.getName());
return false;
@@ -9,7 +9,7 @@ namespace icsneo {
namespace Bootloader {
bool REDCoreCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenStatusHandler& handler) {
bool REDCoreCommunication::flash(const FWRepo& fw, const icsneo::Bootloader::StatusHandler& handler) {
constexpr const size_t MaxSectorSize = 0x600;
std::vector<uint8_t> bin;
@@ -31,7 +31,7 @@ bool REDCoreCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenSta
std::vector<uint8_t> sector;
for(size_t i = 0; i < fileSize; i += MaxSectorSize) {
Log::Trace(__func__, "Sending sector " + std::to_string(sectorsFlashed));
handler(icsneo::Device::OpenStatusType::Progress, message, double(sectorsFlashed++) / sectorCount);
handler(StatusType::Progress, message, double(sectorsFlashed++) / sectorCount);
sector.assign(bin.begin() + i, bin.begin() + i + std::min<size_t>(MaxSectorSize, fileSize - i));
if(!sendCommand(uint8_t(Command::SendFirmware), sector)) {
@@ -42,7 +42,7 @@ bool REDCoreCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenSta
// Then flash it
Log::Debug(__func__, "Starting core flash for " + targetChip.getName());
handler(icsneo::Device::OpenStatusType::Progress, message, std::nullopt);
handler(StatusType::Progress, message, std::nullopt);
// There is a long timeout on the StartFirmwareFlash because the bootloader may block here,
// potentially for the entire duration of the flash
@@ -92,7 +92,7 @@ bool REDCoreCommunication::flash(const FWRepo& fw, const icsneo::Device::OpenSta
Log::Trace(__func__, "Flashed " + std::to_string(flashed) + " of " + std::to_string(fileSize));
if(flashed != oldFlashed)
handler(icsneo::Device::OpenStatusType::Progress, message, std::min(double(flashed) / fileSize, 1.0));
handler(StatusType::Progress, message, std::min(double(flashed) / fileSize, 1.0));
}
return flashed == fileSize;