Target driver passthrough commands

Added `pm` commands to manage the program mode of WCH targets
This commit is contained in:
Nav
2024-12-15 17:32:58 +00:00
parent 1392cda74f
commit 40859201e4
16 changed files with 243 additions and 3 deletions

View File

@@ -3,12 +3,13 @@
#include <utility>
#include <cassert>
#include "src/Targets/DynamicRegisterValue.hpp"
#include "src/Exceptions/InvalidConfig.hpp"
#include "src/Exceptions/Exception.hpp"
#include "src/EventManager/EventManager.hpp"
#include "src/Services/StringService.hpp"
#include "src/Logger/Logger.hpp"
@@ -350,6 +351,95 @@ namespace Targets::RiscV::Wch
return programCounter;
}
std::optional<PassthroughResponse> WchRiscV::invokePassthroughCommand(const PassthroughCommand& command) {
using Services::StringService;
const auto& arguments = command.arguments;
if (arguments.empty()) {
return std::nullopt;
}
auto response = PassthroughResponse{};
try {
if (arguments[0] == "pm") {
const auto &actualAliasedSegment = this->resolveAliasedMemorySegment();
if (arguments.size() == 1) {
response.output = "Program mode: \"" + StringService::applyTerminalColor(
actualAliasedSegment == this->bootProgramSegmentDescriptor ? "boot mode" : "user mode",
StringService::TerminalColor::DARK_YELLOW
) + "\"\n";
response.output += "Aliased memory segment key: \""
+ StringService::applyTerminalColor(
actualAliasedSegment.key,
StringService::TerminalColor::DARK_YELLOW
) + "\"\n";
response.output += "Mapped address -> aliased address: " + StringService::applyTerminalColor(
"0x" + StringService::asciiToUpper(
StringService::toHex(this->mappedSegmentDescriptor.addressRange.startAddress)
),
StringService::TerminalColor::BLUE
) + " -> " + StringService::applyTerminalColor(
"0x" + StringService::asciiToUpper(
StringService::toHex(actualAliasedSegment.addressRange.startAddress)
),
StringService::TerminalColor::BLUE
) + "\n";
response.output += "Program counter: " + StringService::applyTerminalColor(
"0x" + StringService::asciiToUpper(StringService::toHex(this->getProgramCounter())),
StringService::TerminalColor::BLUE
) + "\n";
return response;
}
if (arguments[1] == "boot") {
if (actualAliasedSegment == this->bootProgramSegmentDescriptor) {
response.output += "Target is already in \"boot mode\"\n";
response.output += "Proceeding, anyway...\n\n";
}
this->enableBootMode();
EventManager::triggerEvent(std::make_shared<Events::TargetReset>());
response.output += "Boot mode has been enabled\n";
response.output += "Program counter: " + StringService::applyTerminalColor(
"0x" + StringService::asciiToUpper(StringService::toHex(this->getProgramCounter())),
StringService::TerminalColor::BLUE
) + "\n";
return response;
}
if (arguments[1] == "user") {
if (actualAliasedSegment == this->mainProgramSegmentDescriptor) {
response.output += "Target is already in \"user mode\"\n";
response.output += "Proceeding, anyway...\n\n";
}
this->enableUserMode();
EventManager::triggerEvent(std::make_shared<Events::TargetReset>());
response.output += "User mode has been enabled\n";
response.output += "Program counter: " + StringService::applyTerminalColor(
"0x" + StringService::asciiToUpper(StringService::toHex(this->getProgramCounter())),
StringService::TerminalColor::BLUE
) + "\n";
return response;
}
}
} catch (const Exceptions::Exception& exception) {
Logger::error("Passthrough command error: " + exception.getMessage());
response.output = "Error: " + exception.getMessage();
return response;
}
return std::nullopt;
}
const TargetMemorySegmentDescriptor& WchRiscV::resolveAliasedMemorySegment() {
/*
* To determine the aliased segment, we probe the boundary of the boot segment via the mapped segment.

View File

@@ -43,6 +43,8 @@ namespace Targets::RiscV::Wch
TargetMemoryAddress getProgramCounter() override;
std::optional<PassthroughResponse> invokePassthroughCommand(const PassthroughCommand& command) override;
protected:
WchRiscVTargetConfig targetConfig;
TargetDescriptionFile targetDescriptionFile;