diff --git a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp index 55d0f99a..1d9b58e8 100644 --- a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp +++ b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp @@ -1,6 +1,7 @@ #include "WchLinkInterface.hpp" #include +#include #include "Commands/Control/GetDeviceInfo.hpp" #include "Commands/Control/AttachTarget.hpp" @@ -79,15 +80,29 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink DebugModule::RegisterValue WchLinkInterface::readDebugModuleRegister(DebugModule::RegisterAddress address) { using DebugModule::DmiOperationStatus; - const auto response = this->sendCommandAndWaitForResponse( - Commands::DebugModuleInterfaceOperation{DmiOperation::READ, address} - ); + auto attempt = std::uint8_t{0}; + while (attempt < WchLinkInterface::DMI_OP_MAX_RETRY) { + if (attempt > 0) { + std::this_thread::sleep_for(this->dmiOpRetryDelay); + } - if (response.operationStatus != DmiOperationStatus::SUCCESS) { - throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"}; + const auto response = this->sendCommandAndWaitForResponse( + Commands::DebugModuleInterfaceOperation{DmiOperation::READ, address} + ); + + if (response.operationStatus == DmiOperationStatus::SUCCESS) { + return response.value; + } + + if (response.operationStatus == DmiOperationStatus::FAILED) { + throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"}; + } + + // Busy response... + ++attempt; } - return response.value; + throw Exceptions::DeviceCommunicationFailure{"DMI operation timed out"}; } void WchLinkInterface::writeDebugModuleRegister( @@ -96,13 +111,29 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink ) { using DebugModule::DmiOperationStatus; - const auto response = this->sendCommandAndWaitForResponse( - Commands::DebugModuleInterfaceOperation{DmiOperation::WRITE, address, value} - ); + auto attempt = std::uint8_t{0}; + while (attempt < WchLinkInterface::DMI_OP_MAX_RETRY) { + if (attempt > 0) { + std::this_thread::sleep_for(this->dmiOpRetryDelay); + } - if (response.operationStatus != DmiOperationStatus::SUCCESS) { - throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"}; + const auto response = this->sendCommandAndWaitForResponse( + Commands::DebugModuleInterfaceOperation{DmiOperation::WRITE, address, value} + ); + + if (response.operationStatus == DmiOperationStatus::SUCCESS) { + return; + } + + if (response.operationStatus == DmiOperationStatus::FAILED) { + throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"}; + } + + // Busy response... + ++attempt; } + + throw Exceptions::DeviceCommunicationFailure{"DMI operation timed out"}; } void WchLinkInterface::writeFlashMemory( diff --git a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp index e82ba1f7..cabe2548 100644 --- a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp +++ b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -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_DATA_ENDPOINT_IN = 0x82; static constexpr std::uint8_t USB_DATA_ENDPOINT_OUT = 0x02; + static constexpr std::uint8_t DMI_OP_MAX_RETRY = 10; Usb::UsbInterface& usbInterface; std::uint16_t commandEndpointMaxPacketSize = 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.