Target driver passthrough commands
Added `pm` commands to manage the program mode of WCH targets
This commit is contained in:
@@ -335,6 +335,14 @@ namespace Targets::Microchip::Avr8
|
||||
}
|
||||
}
|
||||
|
||||
// Make RAM, FLASH and EEPROM available for inspection the Insight GUI.
|
||||
descriptor.getMemorySegmentDescriptor("data", "internal_ram").inspectionEnabled = true;
|
||||
descriptor.getMemorySegmentDescriptor("prog", "internal_program_memory").inspectionEnabled = true;
|
||||
descriptor.getMemorySegmentDescriptor(
|
||||
descriptor.getFirstAddressSpaceDescriptorContainingMemorySegment("internal_eeprom").key,
|
||||
"internal_eeprom"
|
||||
).inspectionEnabled = true;
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@@ -683,6 +691,11 @@ namespace Targets::Microchip::Avr8
|
||||
return this->activeProgrammingSession.has_value();
|
||||
}
|
||||
|
||||
std::optional<PassthroughResponse> Avr8::invokePassthroughCommand(const PassthroughCommand& command) {
|
||||
// AVR targets do not currently support any passthrough commands
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::map<TargetPadId, GpioPadDescriptor> Avr8::generateGpioPadDescriptorMapping(
|
||||
const std::vector<TargetPeripheralDescriptor>& portPeripheralDescriptors
|
||||
) {
|
||||
|
||||
@@ -105,11 +105,11 @@ namespace Targets::Microchip::Avr8
|
||||
void setGpioPadState(const TargetPadDescriptor& padDescriptor, const TargetGpioPadState& state) override;
|
||||
|
||||
void enableProgrammingMode() override;
|
||||
|
||||
void disableProgrammingMode() override;
|
||||
|
||||
bool programmingModeEnabled() override;
|
||||
|
||||
std::optional<PassthroughResponse> invokePassthroughCommand(const PassthroughCommand& command) override;
|
||||
|
||||
protected:
|
||||
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* targetPowerManagementInterface = nullptr;
|
||||
DebugToolDrivers::TargetInterfaces::Microchip::Avr8::Avr8DebugInterface* avr8DebugInterface = nullptr;
|
||||
|
||||
12
src/Targets/PassthroughCommand.hpp
Normal file
12
src/Targets/PassthroughCommand.hpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
struct PassthroughCommand
|
||||
{
|
||||
std::vector<std::string> arguments;
|
||||
};
|
||||
}
|
||||
11
src/Targets/PassthroughResponse.hpp
Normal file
11
src/Targets/PassthroughResponse.hpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
struct PassthroughResponse
|
||||
{
|
||||
std::string output;
|
||||
};
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -43,6 +43,8 @@ namespace Targets::RiscV::Wch
|
||||
|
||||
TargetMemoryAddress getProgramCounter() override;
|
||||
|
||||
std::optional<PassthroughResponse> invokePassthroughCommand(const PassthroughCommand& command) override;
|
||||
|
||||
protected:
|
||||
WchRiscVTargetConfig targetConfig;
|
||||
TargetDescriptionFile targetDescriptionFile;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
#include "src/ProjectConfig.hpp"
|
||||
|
||||
@@ -19,6 +20,9 @@
|
||||
#include "TargetPadDescriptor.hpp"
|
||||
#include "TargetGpioPadState.hpp"
|
||||
|
||||
#include "PassthroughCommand.hpp"
|
||||
#include "PassthroughResponse.hpp"
|
||||
|
||||
#include "src/DebugToolDrivers/DebugTool.hpp"
|
||||
|
||||
namespace Targets
|
||||
@@ -150,5 +154,7 @@ namespace Targets
|
||||
virtual void enableProgrammingMode() = 0;
|
||||
virtual void disableProgrammingMode() = 0;
|
||||
virtual bool programmingModeEnabled() = 0;
|
||||
|
||||
virtual std::optional<PassthroughResponse> invokePassthroughCommand(const PassthroughCommand& command) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user