Massive refactor to accommodate RISC-V targets
- Refactored entire codebase (excluding the Insight component) to accommodate multiple target architectures (no longer specific to AVR) - Deleted 'generate SVD' GDB monitor command - I will eventually move this functionality to the Bloom website - Added unit size property to address spaces - Many other changes which I couldn't be bothered to describe here
This commit is contained in:
@@ -43,7 +43,7 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink::Commands
|
||||
|
||||
rawCommand[0] = 0x81;
|
||||
rawCommand[1] = this->commandId;
|
||||
rawCommand[2] = static_cast<std::uint8_t >(this->payload.size());
|
||||
rawCommand[2] = static_cast<std::uint8_t>(this->payload.size());
|
||||
|
||||
if (!this->payload.empty()) {
|
||||
std::copy(this->payload.begin(), this->payload.end(), rawCommand.begin() + 3);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/Command.hpp"
|
||||
#include "src/DebugToolDrivers/WCH/Protocols/WchLink/Responses/DebugModuleInterfaceOperationResponse.hpp"
|
||||
|
||||
#include "src/Targets/RiscV/DebugModule/DebugModule.hpp"
|
||||
#include "src/DebugToolDrivers/Protocols/RiscVDebugSpec/DebugModule/DebugModule.hpp"
|
||||
|
||||
namespace DebugToolDrivers::Wch::Protocols::WchLink::Commands
|
||||
{
|
||||
@@ -16,9 +16,9 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink::Commands
|
||||
using ExpectedResponseType = Responses::DebugModuleInterfaceOperationResponse;
|
||||
|
||||
DebugModuleInterfaceOperation(
|
||||
Targets::RiscV::DebugModule::DmiOperation operation,
|
||||
Targets::RiscV::DebugModule::RegisterAddress address,
|
||||
std::optional<Targets::RiscV::DebugModule::RegisterValue> value = std::nullopt
|
||||
DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::DmiOperation operation,
|
||||
DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterAddress address,
|
||||
std::optional<DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterValue> value = std::nullopt
|
||||
)
|
||||
: Command(0x08)
|
||||
{
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/Targets/RiscV/DebugModule/DebugModule.hpp"
|
||||
#include "src/Helpers/BiMap.hpp"
|
||||
#include "src/DebugToolDrivers/Protocols/RiscVDebugSpec/DebugModule/DebugModule.hpp"
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
@@ -13,32 +12,33 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink::Responses
|
||||
class DebugModuleInterfaceOperationResponse
|
||||
{
|
||||
public:
|
||||
Targets::RiscV::DebugModule::DmiOperationStatus operationStatus;
|
||||
Targets::RiscV::DebugModule::RegisterAddress address;
|
||||
Targets::RiscV::DebugModule::RegisterValue value;
|
||||
DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::DmiOperationStatus operationStatus;
|
||||
DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterAddress address;
|
||||
DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterValue value;
|
||||
|
||||
explicit DebugModuleInterfaceOperationResponse(const std::vector<unsigned char>& payload) {
|
||||
using DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::DmiOperationStatus;
|
||||
|
||||
explicit DebugModuleInterfaceOperationResponse(const std::vector<unsigned char>& payload)
|
||||
{
|
||||
if (payload.size() != 6) {
|
||||
throw Exceptions::DeviceCommunicationFailure(
|
||||
throw Exceptions::DeviceCommunicationFailure{
|
||||
"Unexpected response payload size for DMI operation command"
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const auto status = payload[5];
|
||||
if (
|
||||
status != static_cast<unsigned char>(Targets::RiscV::DebugModule::DmiOperationStatus::SUCCESS)
|
||||
&& status != static_cast<unsigned char>(Targets::RiscV::DebugModule::DmiOperationStatus::FAILED)
|
||||
&& status != static_cast<unsigned char>(Targets::RiscV::DebugModule::DmiOperationStatus::BUSY)
|
||||
status != static_cast<unsigned char>(DmiOperationStatus::SUCCESS)
|
||||
&& status != static_cast<unsigned char>(DmiOperationStatus::FAILED)
|
||||
&& status != static_cast<unsigned char>(DmiOperationStatus::BUSY)
|
||||
) {
|
||||
throw Exceptions::DeviceCommunicationFailure(
|
||||
throw Exceptions::DeviceCommunicationFailure{
|
||||
"Unknown DMI operation status returned: 0x" + Services::StringService::toHex(status)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
this->operationStatus = static_cast<Targets::RiscV::DebugModule::DmiOperationStatus>(status);
|
||||
this->operationStatus = static_cast<DmiOperationStatus>(status);
|
||||
this->address = payload[0];
|
||||
this->value = static_cast<Targets::RiscV::DebugModule::RegisterValue>(
|
||||
this->value = static_cast<DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterValue>(
|
||||
(payload[1] << 24) | (payload[2] << 16) | (payload[3] << 8) | (payload[4])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
{
|
||||
using namespace ::DebugToolDrivers::Protocols::RiscVDebugSpec;
|
||||
using namespace Exceptions;
|
||||
|
||||
using Targets::RiscV::DebugModule::DmiOperation;
|
||||
using DebugModule::DmiOperation;
|
||||
|
||||
WchLinkInterface::WchLinkInterface(Usb::UsbInterface& usbInterface, Usb::UsbDevice& usbDevice)
|
||||
: usbInterface(usbInterface)
|
||||
@@ -29,34 +30,32 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
{}
|
||||
|
||||
DeviceInfo WchLinkInterface::getDeviceInfo() {
|
||||
const auto response = this->sendCommandAndWaitForResponse(Commands::Control::GetDeviceInfo());
|
||||
|
||||
const auto response = this->sendCommandAndWaitForResponse(Commands::Control::GetDeviceInfo{});
|
||||
if (response.payload.size() < 3) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Cannot construct DeviceInfo response - invalid payload");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Cannot construct DeviceInfo response - invalid payload"};
|
||||
}
|
||||
|
||||
static const auto variantsById = BiMap<std::uint8_t, WchLinkVariant>({
|
||||
static const auto variantsById = BiMap<std::uint8_t, WchLinkVariant>{
|
||||
{0x01, WchLinkVariant::LINK_CH549},
|
||||
{0x02, WchLinkVariant::LINK_E_CH32V307},
|
||||
{0x12, WchLinkVariant::LINK_E_CH32V307},
|
||||
{0x03, WchLinkVariant::LINK_S_CH32V203},
|
||||
});
|
||||
};
|
||||
|
||||
return DeviceInfo(
|
||||
WchFirmwareVersion(response.payload[0], response.payload[1]),
|
||||
WchFirmwareVersion{response.payload[0], response.payload[1]},
|
||||
response.payload.size() >= 4
|
||||
? std::optional(variantsById.valueAt(response.payload[2]).value_or(WchLinkVariant::UNKNOWN))
|
||||
? std::optional{variantsById.valueAt(response.payload[2]).value_or(WchLinkVariant::UNKNOWN)}
|
||||
: std::nullopt
|
||||
);
|
||||
}
|
||||
|
||||
void WchLinkInterface::activate(const Targets::RiscV::TargetParameters& targetParameters) {
|
||||
void WchLinkInterface::activate() {
|
||||
this->setClockSpeed(WchLinkTargetClockSpeed::CLK_6000_KHZ);
|
||||
|
||||
const auto response = this->sendCommandAndWaitForResponse(Commands::Control::AttachTarget());
|
||||
|
||||
const auto response = this->sendCommandAndWaitForResponse(Commands::Control::AttachTarget{});
|
||||
if (response.payload.size() != 5) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Unexpected response payload size for AttachTarget command");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Unexpected response payload size for AttachTarget command"};
|
||||
}
|
||||
|
||||
this->cachedTargetId = static_cast<WchTargetId>(
|
||||
@@ -67,10 +66,9 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
}
|
||||
|
||||
void WchLinkInterface::deactivate() {
|
||||
const auto response = this->sendCommandAndWaitForResponse(Commands::Control::DetachTarget());
|
||||
|
||||
const auto response = this->sendCommandAndWaitForResponse(Commands::Control::DetachTarget{});
|
||||
if (response.payload.size() != 1) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Unexpected response payload size for DetachTarget command");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Unexpected response payload size for DetachTarget command"};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,34 +76,32 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
return "0x" + Services::StringService::toHex(this->cachedTargetId.value());
|
||||
}
|
||||
|
||||
Targets::RiscV::DebugModule::RegisterValue WchLinkInterface::readDebugModuleRegister(
|
||||
Targets::RiscV::DebugModule::RegisterAddress address
|
||||
) {
|
||||
using Targets::RiscV::DebugModule::DmiOperationStatus ;
|
||||
DebugModule::RegisterValue WchLinkInterface::readDebugModuleRegister(DebugModule::RegisterAddress address) {
|
||||
using DebugModule::DmiOperationStatus;
|
||||
|
||||
const auto response = this->sendCommandAndWaitForResponse(
|
||||
Commands::DebugModuleInterfaceOperation(DmiOperation::READ, address)
|
||||
Commands::DebugModuleInterfaceOperation{DmiOperation::READ, address}
|
||||
);
|
||||
|
||||
if (response.operationStatus != DmiOperationStatus::SUCCESS) {
|
||||
throw Exceptions::DeviceCommunicationFailure("DMI operation failed");
|
||||
throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"};
|
||||
}
|
||||
|
||||
return response.value;
|
||||
}
|
||||
|
||||
void WchLinkInterface::writeDebugModuleRegister(
|
||||
Targets::RiscV::DebugModule::RegisterAddress address,
|
||||
Targets::RiscV::DebugModule::RegisterValue value
|
||||
DebugModule::RegisterAddress address,
|
||||
DebugModule::RegisterValue value
|
||||
) {
|
||||
using Targets::RiscV::DebugModule::DmiOperationStatus ;
|
||||
using DebugModule::DmiOperationStatus;
|
||||
|
||||
const auto response = this->sendCommandAndWaitForResponse(
|
||||
Commands::DebugModuleInterfaceOperation(DmiOperation::WRITE, address, value)
|
||||
Commands::DebugModuleInterfaceOperation{DmiOperation::WRITE, address, value}
|
||||
);
|
||||
|
||||
if (response.operationStatus != DmiOperationStatus::SUCCESS) {
|
||||
throw Exceptions::DeviceCommunicationFailure("DMI operation failed");
|
||||
throw Exceptions::DeviceCommunicationFailure{"DMI operation failed"};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,36 +115,35 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
std::ceil(static_cast<float>(bufferSize) / static_cast<float>(packetSize))
|
||||
);
|
||||
|
||||
for (std::uint32_t i = 0; i < packetsRequired; ++i) {
|
||||
for (auto i = std::uint32_t{0}; i < packetsRequired; ++i) {
|
||||
const auto segmentSize = static_cast<std::uint8_t>(std::min(bufferSize - (i * packetSize), packetSize));
|
||||
const auto response = this->sendCommandAndWaitForResponse(
|
||||
Commands::PreparePartialFlashPageWrite(startAddress + (packetSize * i), segmentSize)
|
||||
Commands::PreparePartialFlashPageWrite{startAddress + (packetSize * i), segmentSize}
|
||||
);
|
||||
|
||||
if (response.payload.size() != 1) {
|
||||
throw Exceptions::DeviceCommunicationFailure(
|
||||
throw Exceptions::DeviceCommunicationFailure{
|
||||
"Unexpected response payload size for PreparePartialFlashPageWrite command"
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
this->usbInterface.writeBulk(
|
||||
WchLinkInterface::USB_DATA_ENDPOINT_OUT,
|
||||
std::vector<unsigned char>(
|
||||
std::vector<unsigned char>{
|
||||
buffer.begin() + (packetSize * i),
|
||||
buffer.begin() + (packetSize * i) + segmentSize
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
const auto rawResponse = this->usbInterface.readBulk(WchLinkInterface::USB_DATA_ENDPOINT_IN);
|
||||
|
||||
if (rawResponse.size() != 4) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Unexpected response size for partial flash page write");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Unexpected response size for partial flash page write"};
|
||||
}
|
||||
|
||||
/*
|
||||
* I have no idea what any of these bytes mean. There's no documentation available for this.
|
||||
*
|
||||
* All I know is that these values indicate a successful write.
|
||||
* I have no idea what any of these bytes mean. I've not been a le to find any documentation for
|
||||
* this. All I know is that these values indicate a successful write.
|
||||
*/
|
||||
if (
|
||||
rawResponse[0] != 0x41
|
||||
@@ -156,28 +151,28 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
|| rawResponse[2] != 0x01
|
||||
|| rawResponse[3] != 0x02
|
||||
) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Partial flash page write failed");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Partial flash page write failed"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WchLinkInterface::setClockSpeed(WchLinkTargetClockSpeed speed) {
|
||||
const auto speedIdsBySpeed = BiMap<WchLinkTargetClockSpeed, std::uint8_t>({
|
||||
const auto speedIdsBySpeed = BiMap<WchLinkTargetClockSpeed, std::uint8_t>{
|
||||
{WchLinkTargetClockSpeed::CLK_6000_KHZ, 0x01},
|
||||
{WchLinkTargetClockSpeed::CLK_4000_KHZ, 0x02},
|
||||
{WchLinkTargetClockSpeed::CLK_400_KHZ, 0x03},
|
||||
});
|
||||
};
|
||||
|
||||
const auto response = this->sendCommandAndWaitForResponse(
|
||||
Commands::SetClockSpeed(this->cachedTargetGroupId.value_or(0x01), speedIdsBySpeed.at(speed))
|
||||
Commands::SetClockSpeed{this->cachedTargetGroupId.value_or(0x01), speedIdsBySpeed.at(speed)}
|
||||
);
|
||||
|
||||
if (response.payload.size() != 1) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Unexpected response payload size for SetClockSpeed command");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Unexpected response payload size for SetClockSpeed command"};
|
||||
}
|
||||
|
||||
if (response.payload[0] != 0x01) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Unexpected response for SetClockSpeed command");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Unexpected response for SetClockSpeed command"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,16 @@
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
|
||||
#include "src/DebugToolDrivers/Protocols/RiscVDebugSpec/DebugTransportModuleInterface.hpp"
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVProgramInterface.hpp"
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVIdentificationInterface.hpp"
|
||||
|
||||
#include "src/DebugToolDrivers/USB/UsbInterface.hpp"
|
||||
#include "src/DebugToolDrivers/USB/UsbDevice.hpp"
|
||||
|
||||
#include "src/DebugToolDrivers/WCH/WchGeneric.hpp"
|
||||
#include "Commands/Command.hpp"
|
||||
|
||||
#include "src/Targets/RiscV/DebugModule/DebugModule.hpp"
|
||||
#include "src/DebugToolDrivers/WCH/DeviceInfo.hpp"
|
||||
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
@@ -21,30 +22,33 @@
|
||||
namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
{
|
||||
/**
|
||||
* The WchLinkInterface implements the WCH-Link protocol.
|
||||
* Implementation of the WCH-Link protocol, which provides an implementation of a RISC-V DTM interface, a
|
||||
* programming interface and a target identification interface.
|
||||
*
|
||||
* WCH debug tools cannot write to program memory via the target's RISC-V debug module, so we cannot program the
|
||||
* target via the tool's RISC-V DTM interface. Instead, the WCH-Link protocol provides a dedicated command for
|
||||
* writing to program memory, which is why this class implements the RISC-V programming interface.
|
||||
* See WchLinkInterface::writeFlashMemory() for more.
|
||||
*/
|
||||
class WchLinkInterface
|
||||
: public TargetInterfaces::RiscV::RiscVDebugInterface
|
||||
: public ::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugTransportModuleInterface
|
||||
, public TargetInterfaces::RiscV::RiscVProgramInterface
|
||||
, public TargetInterfaces::RiscV::RiscVIdentificationInterface
|
||||
{
|
||||
public:
|
||||
WchLinkInterface(Usb::UsbInterface& usbInterface, Usb::UsbDevice& usbDevice);
|
||||
|
||||
DeviceInfo getDeviceInfo();
|
||||
|
||||
void activate(const Targets::RiscV::TargetParameters& targetParameters) override;
|
||||
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
std::string getDeviceId() override;
|
||||
|
||||
Targets::RiscV::DebugModule::RegisterValue readDebugModuleRegister(
|
||||
Targets::RiscV::DebugModule::RegisterAddress address
|
||||
::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterValue readDebugModuleRegister(
|
||||
::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterAddress address
|
||||
) override;
|
||||
|
||||
void writeDebugModuleRegister(
|
||||
Targets::RiscV::DebugModule::RegisterAddress address,
|
||||
Targets::RiscV::DebugModule::RegisterValue value
|
||||
::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterAddress address,
|
||||
::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::RegisterValue value
|
||||
) override;
|
||||
|
||||
void writeFlashMemory(
|
||||
@@ -85,9 +89,9 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
auto rawCommand = command.getRawCommand();
|
||||
|
||||
if (rawCommand.size() > this->commandEndpointMaxPacketSize) {
|
||||
throw Exceptions::DeviceCommunicationFailure(
|
||||
throw Exceptions::DeviceCommunicationFailure{
|
||||
"Raw command size exceeds maximum packet size for command endpoint"
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
this->usbInterface.writeBulk(WchLinkInterface::USB_COMMAND_ENDPOINT_OUT, std::move(rawCommand));
|
||||
@@ -95,30 +99,30 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
|
||||
const auto rawResponse = this->usbInterface.readBulk(WchLinkInterface::USB_COMMAND_ENDPOINT_IN);
|
||||
|
||||
if (rawResponse.size() < 3) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Invalid response size from device");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Invalid response size from device"};
|
||||
}
|
||||
|
||||
// The first byte of the response should be 0x82 (for success) or 0x81 (for failure)
|
||||
if ((rawResponse[0] != 0x81 && rawResponse[0] != 0x82)) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Invalid response code from device");
|
||||
if (rawResponse[0] != 0x81 && rawResponse[0] != 0x82) {
|
||||
throw Exceptions::DeviceCommunicationFailure{"Invalid response code from device"};
|
||||
}
|
||||
|
||||
if (rawResponse[0] == 0x81) {
|
||||
// TODO: Create ErrorResponse exception class and throw an instance of it here.
|
||||
throw Exceptions::DeviceCommunicationFailure("Error response");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Error response"};
|
||||
}
|
||||
|
||||
if (rawResponse[1] != command.commandId) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Missing/invalid command ID in response from device");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Missing/invalid command ID in response from device"};
|
||||
}
|
||||
|
||||
if ((rawResponse.size() - 3) != rawResponse[2]) {
|
||||
throw Exceptions::DeviceCommunicationFailure("Actual response payload size mismatch");
|
||||
throw Exceptions::DeviceCommunicationFailure{"Actual response payload size mismatch"};
|
||||
}
|
||||
|
||||
return typename CommandType::ExpectedResponseType(
|
||||
std::vector<unsigned char>(rawResponse.begin() + 3, rawResponse.end())
|
||||
);
|
||||
return typename CommandType::ExpectedResponseType{
|
||||
std::vector<unsigned char>{rawResponse.begin() + 3, rawResponse.end()}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "WchLinkBase.hpp"
|
||||
|
||||
#include "Protocols/WchLink/WchLinkInterface.hpp"
|
||||
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
@@ -37,19 +39,25 @@ namespace DebugToolDrivers::Wch
|
||||
);
|
||||
|
||||
if (this->getDeviceInfo().variant != this->variant) {
|
||||
throw DeviceInitializationFailure(
|
||||
throw DeviceInitializationFailure{
|
||||
"WCH-Link variant mismatch - device returned variant ID that doesn't match the " + this->getName()
|
||||
+ " variant ID"
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
this->setInitialised(true);
|
||||
this->initialised = true;
|
||||
}
|
||||
|
||||
void WchLinkBase::close() {
|
||||
if (this->wchLinkUsbInterface) {
|
||||
this->wchLinkUsbInterface->close();
|
||||
}
|
||||
|
||||
this->initialised = false;
|
||||
}
|
||||
|
||||
bool WchLinkBase::isInitialised() const {
|
||||
return this->initialised;
|
||||
}
|
||||
|
||||
std::string WchLinkBase::getSerialNumber() {
|
||||
@@ -60,6 +68,36 @@ namespace DebugToolDrivers::Wch
|
||||
return "v" + this->getDeviceInfo().firmwareVersion.toString();
|
||||
}
|
||||
|
||||
::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugTranslator* WchLinkBase::getRiscVDebugInterface(
|
||||
const Targets::RiscV::TargetDescriptionFile& targetDescriptionFile,
|
||||
const Targets::RiscV::RiscVTargetConfig& targetConfig
|
||||
) {
|
||||
using ::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugTranslator;
|
||||
|
||||
if (!this->wchRiscVTranslator) {
|
||||
this->wchRiscVTranslator = std::make_unique<DebugTranslator>(
|
||||
*(this->wchLinkInterface.get()),
|
||||
targetDescriptionFile,
|
||||
targetConfig
|
||||
);
|
||||
}
|
||||
return this->wchRiscVTranslator.get();
|
||||
}
|
||||
|
||||
Protocols::WchLink::WchLinkInterface* WchLinkBase::getRiscVProgramInterface(
|
||||
const Targets::RiscV::TargetDescriptionFile& targetDescriptionFile,
|
||||
const Targets::RiscV::RiscVTargetConfig& targetConfig
|
||||
) {
|
||||
return this->wchLinkInterface.get();
|
||||
}
|
||||
|
||||
Protocols::WchLink::WchLinkInterface* WchLinkBase::getRiscVIdentificationInterface(
|
||||
const Targets::RiscV::TargetDescriptionFile& targetDescriptionFile,
|
||||
const Targets::RiscV::RiscVTargetConfig& targetConfig
|
||||
) {
|
||||
return this->wchLinkInterface.get();
|
||||
}
|
||||
|
||||
const DeviceInfo& WchLinkBase::getDeviceInfo() const {
|
||||
if (!this->cachedDeviceInfo.has_value()) {
|
||||
this->cachedDeviceInfo = this->wchLinkInterface->getDeviceInfo();
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
|
||||
#include "src/DebugToolDrivers/DebugTool.hpp"
|
||||
#include "src/DebugToolDrivers/USB/UsbDevice.hpp"
|
||||
#include "src/DebugToolDrivers/USB/UsbInterface.hpp"
|
||||
|
||||
#include "Protocols/WchLink/WchLinkInterface.hpp"
|
||||
#include "src/DebugToolDrivers/Protocols/RiscVDebugSpec/DebugTranslator.hpp"
|
||||
|
||||
#include "WchGeneric.hpp"
|
||||
#include "DeviceInfo.hpp"
|
||||
@@ -28,13 +30,16 @@ namespace DebugToolDrivers::Wch
|
||||
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] bool isInitialised() const override;
|
||||
|
||||
std::string getSerialNumber() override;
|
||||
|
||||
std::string getFirmwareVersionString() override;
|
||||
|
||||
DebugToolDrivers::TargetInterfaces::RiscV::RiscVDebugInterface* getRiscVDebugInterface() override {
|
||||
return this->wchLinkInterface.get();
|
||||
}
|
||||
::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugTranslator* getRiscVDebugInterface(
|
||||
const Targets::RiscV::TargetDescriptionFile& targetDescriptionFile,
|
||||
const Targets::RiscV::RiscVTargetConfig& targetConfig
|
||||
) override;
|
||||
|
||||
/**
|
||||
* WCH-Link debug tools cannot write to flash memory via the RISC-V debug interface (RiscVDebugInterface).
|
||||
@@ -46,20 +51,27 @@ namespace DebugToolDrivers::Wch
|
||||
* target driver forwards any flash memory writes to this implementation (instead of relying on the debug
|
||||
* interface).
|
||||
*
|
||||
* The WchLinkInterface implements both the RiscVDebugInterface and the RiscVProgramInterface.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
DebugToolDrivers::TargetInterfaces::RiscV::RiscVProgramInterface* getRiscVProgramInterface() override {
|
||||
return this->wchLinkInterface.get();
|
||||
}
|
||||
Protocols::WchLink::WchLinkInterface* getRiscVProgramInterface(
|
||||
const Targets::RiscV::TargetDescriptionFile& targetDescriptionFile,
|
||||
const Targets::RiscV::RiscVTargetConfig& targetConfig
|
||||
) override;
|
||||
|
||||
Protocols::WchLink::WchLinkInterface* getRiscVIdentificationInterface(
|
||||
const Targets::RiscV::TargetDescriptionFile& targetDescriptionFile,
|
||||
const Targets::RiscV::RiscVTargetConfig& targetConfig
|
||||
) override;
|
||||
|
||||
protected:
|
||||
bool initialised = false;
|
||||
|
||||
WchLinkVariant variant;
|
||||
|
||||
std::uint8_t wchLinkUsbInterfaceNumber;
|
||||
std::unique_ptr<Usb::UsbInterface> wchLinkUsbInterface = nullptr;
|
||||
std::unique_ptr<Protocols::WchLink::WchLinkInterface> wchLinkInterface = nullptr;
|
||||
std::unique_ptr<::DebugToolDrivers::Protocols::RiscVDebugSpec::DebugTranslator> wchRiscVTranslator = nullptr;
|
||||
|
||||
mutable std::optional<DeviceInfo> cachedDeviceInfo = std::nullopt;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user