Retry DMI operations when BUSY status returned in WCH-Link driver
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#include "WchLinkInterface.hpp"
|
#include "WchLinkInterface.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "Commands/Control/GetDeviceInfo.hpp"
|
#include "Commands/Control/GetDeviceInfo.hpp"
|
||||||
#include "Commands/Control/AttachTarget.hpp"
|
#include "Commands/Control/AttachTarget.hpp"
|
||||||
@@ -79,15 +80,29 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
|||||||
DebugModule::RegisterValue WchLinkInterface::readDebugModuleRegister(DebugModule::RegisterAddress address) {
|
DebugModule::RegisterValue WchLinkInterface::readDebugModuleRegister(DebugModule::RegisterAddress address) {
|
||||||
using DebugModule::DmiOperationStatus;
|
using DebugModule::DmiOperationStatus;
|
||||||
|
|
||||||
|
auto attempt = std::uint8_t{0};
|
||||||
|
while (attempt < WchLinkInterface::DMI_OP_MAX_RETRY) {
|
||||||
|
if (attempt > 0) {
|
||||||
|
std::this_thread::sleep_for(this->dmiOpRetryDelay);
|
||||||
|
}
|
||||||
|
|
||||||
const auto response = this->sendCommandAndWaitForResponse(
|
const auto response = this->sendCommandAndWaitForResponse(
|
||||||
Commands::DebugModuleInterfaceOperation{DmiOperation::READ, address}
|
Commands::DebugModuleInterfaceOperation{DmiOperation::READ, address}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.operationStatus != DmiOperationStatus::SUCCESS) {
|
if (response.operationStatus == DmiOperationStatus::SUCCESS) {
|
||||||
|
return response.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.operationStatus == DmiOperationStatus::FAILED) {
|
||||||
throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"};
|
throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"};
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.value;
|
// Busy response...
|
||||||
|
++attempt;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Exceptions::DeviceCommunicationFailure{"DMI operation timed out"};
|
||||||
}
|
}
|
||||||
|
|
||||||
void WchLinkInterface::writeDebugModuleRegister(
|
void WchLinkInterface::writeDebugModuleRegister(
|
||||||
@@ -96,13 +111,29 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
|||||||
) {
|
) {
|
||||||
using DebugModule::DmiOperationStatus;
|
using DebugModule::DmiOperationStatus;
|
||||||
|
|
||||||
|
auto attempt = std::uint8_t{0};
|
||||||
|
while (attempt < WchLinkInterface::DMI_OP_MAX_RETRY) {
|
||||||
|
if (attempt > 0) {
|
||||||
|
std::this_thread::sleep_for(this->dmiOpRetryDelay);
|
||||||
|
}
|
||||||
|
|
||||||
const auto response = this->sendCommandAndWaitForResponse(
|
const auto response = this->sendCommandAndWaitForResponse(
|
||||||
Commands::DebugModuleInterfaceOperation{DmiOperation::WRITE, address, value}
|
Commands::DebugModuleInterfaceOperation{DmiOperation::WRITE, address, value}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.operationStatus != DmiOperationStatus::SUCCESS) {
|
if (response.operationStatus == DmiOperationStatus::SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.operationStatus == DmiOperationStatus::FAILED) {
|
||||||
throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"};
|
throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Busy response...
|
||||||
|
++attempt;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Exceptions::DeviceCommunicationFailure{"DMI operation timed out"};
|
||||||
}
|
}
|
||||||
|
|
||||||
void WchLinkInterface::writeFlashMemory(
|
void WchLinkInterface::writeFlashMemory(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <chrono>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -61,11 +62,14 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
|||||||
static constexpr std::uint8_t USB_COMMAND_ENDPOINT_OUT = 0x01;
|
static constexpr std::uint8_t USB_COMMAND_ENDPOINT_OUT = 0x01;
|
||||||
static constexpr std::uint8_t USB_DATA_ENDPOINT_IN = 0x82;
|
static constexpr std::uint8_t USB_DATA_ENDPOINT_IN = 0x82;
|
||||||
static constexpr std::uint8_t USB_DATA_ENDPOINT_OUT = 0x02;
|
static constexpr std::uint8_t USB_DATA_ENDPOINT_OUT = 0x02;
|
||||||
|
static constexpr std::uint8_t DMI_OP_MAX_RETRY = 10;
|
||||||
|
|
||||||
Usb::UsbInterface& usbInterface;
|
Usb::UsbInterface& usbInterface;
|
||||||
|
|
||||||
std::uint16_t commandEndpointMaxPacketSize = 0;
|
std::uint16_t commandEndpointMaxPacketSize = 0;
|
||||||
std::uint16_t dataEndpointMaxPacketSize = 0;
|
std::uint16_t dataEndpointMaxPacketSize = 0;
|
||||||
|
// TODO: Move this into a config param
|
||||||
|
std::chrono::microseconds dmiOpRetryDelay = std::chrono::microseconds{10};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 'target activation' command returns a payload of 5 bytes.
|
* The 'target activation' command returns a payload of 5 bytes.
|
||||||
|
|||||||
Reference in New Issue
Block a user