diff --git a/src/Targets/RiscV/DebugModule/Registers/AbstractCommandRegister.hpp b/src/Targets/RiscV/DebugModule/Registers/AbstractCommandRegister.hpp new file mode 100644 index 00000000..cf5bc888 --- /dev/null +++ b/src/Targets/RiscV/DebugModule/Registers/AbstractCommandRegister.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include "src/Targets/RiscV/DebugModule/DebugModule.hpp" + +namespace Targets::RiscV::DebugModule::Registers +{ + struct AbstractCommandRegister + { + enum CommandType: std::uint8_t + { + REGISTER_ACCESS = 0x00, + QUICK_ACCESS = 0x01, + MEMORY_ACCESS = 0x02, + }; + + std::uint32_t control = 0; + CommandType commandType = CommandType::REGISTER_ACCESS; + + AbstractCommandRegister() = default; + + constexpr explicit AbstractCommandRegister(RegisterValue registerValue) + : control(static_cast(registerValue & 0x00FFFFFF)) + , commandType(static_cast((registerValue >> 24) & 0xFF)) + {} + + constexpr RegisterValue value() const { + assert(this->control <= 0x00FFFFFF); + + return RegisterValue{0} + | static_cast(this->control & 0x00FFFFFF) + | static_cast(this->commandType) << 24 + ; + } + }; +} diff --git a/src/Targets/RiscV/DebugModule/Registers/AbstractControlStatusRegister.hpp b/src/Targets/RiscV/DebugModule/Registers/AbstractControlStatusRegister.hpp new file mode 100644 index 00000000..b352b0ea --- /dev/null +++ b/src/Targets/RiscV/DebugModule/Registers/AbstractControlStatusRegister.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include + +#include "src/Targets/RiscV/DebugModule/DebugModule.hpp" + +namespace Targets::RiscV::DebugModule::Registers +{ + struct AbstractControlStatusRegister + { + enum CommandError: std::uint8_t + { + NONE = 0x00, + BUSY = 0x01, + NOT_SUPPORTED = 0x02, + EXCEPTION = 0x03, + HALT_RESUME = 0x04, + BUS = 0x05, + OTHER = 0x07, + }; + + std::uint8_t dataCount:4 = 0; + CommandError commandError:3 = CommandError::NONE; + bool relaxedPrivilege:1 = false; + bool busy:1 = false; + std::uint8_t programBufferSize:5 = 0; + + AbstractControlStatusRegister() = default; + + constexpr explicit AbstractControlStatusRegister(RegisterValue registerValue) + : dataCount(static_cast(registerValue & 0x0F)) + , commandError(static_cast((registerValue >> 8) & 0x07)) + , relaxedPrivilege(static_cast(registerValue & (0x01 << 11))) + , busy(static_cast(registerValue & (0x01 << 12))) + , programBufferSize(static_cast((registerValue >> 24) & 0x1F)) + {} + + constexpr RegisterValue value() const { + return RegisterValue{0} + | static_cast(this->dataCount) + | static_cast(this->commandError) << 8 + | static_cast(this->relaxedPrivilege) << 11 + | static_cast(this->busy) << 12 + | static_cast(this->programBufferSize) << 24 + ; + } + + constexpr void clearCommandError() { + // Setting all of the bits will clear the field + this->commandError = CommandError::OTHER; + } + }; +} diff --git a/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp b/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp index a932c399..225cfcd8 100644 --- a/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp +++ b/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp @@ -6,7 +6,10 @@ namespace Targets::RiscV::DebugModule::Registers { enum RegisterAddresses: std::uint8_t { + ABSTRACT_DATA_0 = 0x04, CONTROL_REGISTER = 0x10, STATUS_REGISTER = 0x11, + ABSTRACT_CONTROL_STATUS_REGISTER = 0x16, + ABSTRACT_COMMAND_REGISTER = 0x17, }; } diff --git a/src/Targets/RiscV/RiscV.cpp b/src/Targets/RiscV/RiscV.cpp index 7ed66d9d..57ed30c8 100644 --- a/src/Targets/RiscV/RiscV.cpp +++ b/src/Targets/RiscV/RiscV.cpp @@ -15,6 +15,8 @@ namespace Targets::RiscV using DebugModule::Registers::RegisterAddresses; using DebugModule::Registers::ControlRegister; using DebugModule::Registers::StatusRegister; + using DebugModule::Registers::AbstractControlStatusRegister; + using DebugModule::Registers::AbstractCommandRegister; RiscV::RiscV(const TargetConfig& targetConfig) : name("CH32X035C8T6") // TODO: TDF @@ -278,10 +280,43 @@ namespace Targets::RiscV return StatusRegister(this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::STATUS_REGISTER)); } + AbstractControlStatusRegister RiscV::readDebugModuleAbstractControlStatusRegister() { + return AbstractControlStatusRegister( + this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::ABSTRACT_CONTROL_STATUS_REGISTER) + ); + } + void RiscV::writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister) { this->riscVDebugInterface->writeDebugModuleRegister( RegisterAddresses::CONTROL_REGISTER, controlRegister.value() ); } + + void RiscV::executeAbstractCommand( + const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister + ) { + this->riscVDebugInterface->writeDebugModuleRegister( + RegisterAddresses::ABSTRACT_COMMAND_REGISTER, + abstractCommandRegister.value() + ); + + auto abstractStatusRegister = this->readDebugModuleAbstractControlStatusRegister(); + if (abstractStatusRegister.commandError != AbstractControlStatusRegister::CommandError::NONE) { + throw Exceptions::Exception( + "Failed to execute abstract command - error: " + + Services::StringService::toHex(abstractStatusRegister.commandError) + ); + } + + constexpr auto maxAttempts = 10; + for (auto attempts = 1; abstractStatusRegister.busy && attempts <= maxAttempts; ++attempts) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + abstractStatusRegister = this->readDebugModuleAbstractControlStatusRegister(); + } + + if (abstractStatusRegister.busy) { + throw Exceptions::Exception("Abstract command took too long to execute"); + } + } } diff --git a/src/Targets/RiscV/RiscV.hpp b/src/Targets/RiscV/RiscV.hpp index 15f2428b..146b66a1 100644 --- a/src/Targets/RiscV/RiscV.hpp +++ b/src/Targets/RiscV/RiscV.hpp @@ -11,6 +11,8 @@ #include "src/Targets/RiscV/DebugModule/DebugModule.hpp" #include "src/Targets/RiscV/DebugModule/Registers/ControlRegister.hpp" #include "src/Targets/RiscV/DebugModule/Registers/StatusRegister.hpp" +#include "src/Targets/RiscV/DebugModule/Registers/AbstractControlStatusRegister.hpp" +#include "src/Targets/RiscV/DebugModule/Registers/AbstractCommandRegister.hpp" namespace Targets::RiscV { @@ -99,7 +101,10 @@ namespace Targets::RiscV DebugModule::Registers::ControlRegister readDebugModuleControlRegister(); DebugModule::Registers::StatusRegister readDebugModuleStatusRegister(); + DebugModule::Registers::AbstractControlStatusRegister readDebugModuleAbstractControlStatusRegister(); + void writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister); + void executeAbstractCommand(const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister); }; }