diff --git a/src/Targets/RiscV/DebugModule/Registers/RegisterAccessControlField.hpp b/src/Targets/RiscV/DebugModule/Registers/RegisterAccessControlField.hpp new file mode 100644 index 00000000..4d8bdddb --- /dev/null +++ b/src/Targets/RiscV/DebugModule/Registers/RegisterAccessControlField.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include "src/Targets/RiscV/RiscVGeneric.hpp" + +namespace Targets::RiscV::DebugModule::Registers +{ + struct RegisterAccessControlField + { + enum class RegisterSize: std::uint8_t + { + SIZE_32 = 0x02, + SIZE_64 = 0x03, + SIZE_128 = 0x04, + }; + + ::Targets::RiscV::Registers::RegisterNumber registerNumber; + bool write:1 = false; + bool transfer:1 = false; + bool postExecute:1 = false; + bool postIncrement:1 = false; + RegisterSize size:3 = RegisterSize::SIZE_32; + + RegisterAccessControlField() = default; + + RegisterAccessControlField( + ::Targets::RiscV::Registers::RegisterNumber registerNumber, + bool write, + bool transfer, + bool postExecute, + bool postIncrement, + RegisterSize size + ) + : registerNumber(registerNumber) + , write(write) + , transfer(transfer) + , postExecute(postExecute) + , postIncrement(postIncrement) + , size(size) + {} + + constexpr explicit RegisterAccessControlField(std::uint32_t controlValue) + : registerNumber(static_cast<::Targets::RiscV::Registers::RegisterNumber>(controlValue & 0xFFFF)) + , write(static_cast(controlValue & (0x01 << 16))) + , transfer(static_cast(controlValue & (0x01 << 17))) + , postExecute(static_cast(controlValue & (0x01 << 18))) + , postIncrement(static_cast(controlValue & (0x01 << 19))) + , size(static_cast((controlValue >> 20) & 0x07)) + {} + + constexpr std::uint32_t value() const { + return std::uint32_t{0} + | static_cast(this->registerNumber) + | static_cast(this->write) << 16 + | static_cast(this->transfer) << 17 + | static_cast(this->postExecute) << 18 + | static_cast(this->postIncrement) << 19 + | static_cast(this->size) << 20 + ; + } + }; +} diff --git a/src/Targets/RiscV/Registers/RegisterNumbers.hpp b/src/Targets/RiscV/Registers/RegisterNumbers.hpp new file mode 100644 index 00000000..6f2b9761 --- /dev/null +++ b/src/Targets/RiscV/Registers/RegisterNumbers.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "src/Targets/RiscV/RiscVGeneric.hpp" + +namespace Targets::RiscV::Registers +{ + enum class RegisterNumber: std::uint16_t + { + DEBUG_CONTROL_STATUS_REGISTER = 0x07b0, + }; +} diff --git a/src/Targets/RiscV/RiscV.cpp b/src/Targets/RiscV/RiscV.cpp index 57ed30c8..40eb2e73 100644 --- a/src/Targets/RiscV/RiscV.cpp +++ b/src/Targets/RiscV/RiscV.cpp @@ -4,6 +4,7 @@ #include #include "DebugModule/Registers/RegisterAddresses.hpp" +#include "DebugModule/Registers/RegisterAccessControlField.hpp" #include "src/Exceptions/Exception.hpp" #include "src/TargetController/Exceptions/TargetOperationFailure.hpp" @@ -12,6 +13,7 @@ namespace Targets::RiscV { + using Registers::RegisterNumber; using DebugModule::Registers::RegisterAddresses; using DebugModule::Registers::ControlRegister; using DebugModule::Registers::StatusRegister; @@ -55,6 +57,13 @@ namespace Targets::RiscV Logger::info("Selected RISC-V hart index: " + std::to_string(this->selectedHartIndex)); this->stop(); + + auto debugControlStatusRegister = this->readDebugControlStatusRegister(); + debugControlStatusRegister.breakUMode = true; + debugControlStatusRegister.breakSMode = true; + debugControlStatusRegister.breakMMode = true; + + this->writeDebugControlStatusRegister(debugControlStatusRegister); } void RiscV::deactivate() { @@ -286,6 +295,43 @@ namespace Targets::RiscV ); } + RegisterValue RiscV::readRegister(RegisterNumber number) { + using DebugModule::Registers::RegisterAccessControlField; + + auto command = AbstractCommandRegister(); + command.commandType = AbstractCommandRegister::CommandType::REGISTER_ACCESS; + command.control = RegisterAccessControlField( + number, + false, + true, + false, + false, + RegisterAccessControlField::RegisterSize::SIZE_32 + ).value(); + + this->executeAbstractCommand(command); + + return this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::ABSTRACT_DATA_0); + } + + void RiscV::writeRegister(Registers::RegisterNumber number, RegisterValue value) { + using DebugModule::Registers::RegisterAccessControlField; + + auto command = AbstractCommandRegister(); + command.commandType = AbstractCommandRegister::CommandType::REGISTER_ACCESS; + command.control = RegisterAccessControlField( + number, + true, + true, + false, + false, + RegisterAccessControlField::RegisterSize::SIZE_32 + ).value(); + + this->riscVDebugInterface->writeDebugModuleRegister(RegisterAddresses::ABSTRACT_DATA_0, value); + this->executeAbstractCommand(command); + } + void RiscV::writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister) { this->riscVDebugInterface->writeDebugModuleRegister( RegisterAddresses::CONTROL_REGISTER, diff --git a/src/Targets/RiscV/RiscV.hpp b/src/Targets/RiscV/RiscV.hpp index 146b66a1..0affbdbd 100644 --- a/src/Targets/RiscV/RiscV.hpp +++ b/src/Targets/RiscV/RiscV.hpp @@ -8,6 +8,7 @@ #include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp" +#include "src/Targets/RiscV/RiscVGeneric.hpp" #include "src/Targets/RiscV/DebugModule/DebugModule.hpp" #include "src/Targets/RiscV/DebugModule/Registers/ControlRegister.hpp" #include "src/Targets/RiscV/DebugModule/Registers/StatusRegister.hpp" @@ -104,6 +105,10 @@ namespace Targets::RiscV DebugModule::Registers::AbstractControlStatusRegister readDebugModuleAbstractControlStatusRegister(); + RegisterValue readRegister(Registers::RegisterNumber number); + void writeRegister(Registers::RegisterNumber number, RegisterValue value); + + void writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister); void executeAbstractCommand(const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister); }; diff --git a/src/Targets/RiscV/RiscVGeneric.hpp b/src/Targets/RiscV/RiscVGeneric.hpp new file mode 100644 index 00000000..65369726 --- /dev/null +++ b/src/Targets/RiscV/RiscVGeneric.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "Registers/RegisterNumbers.hpp" + +namespace Targets::RiscV +{ + using RegisterValue = std::uint32_t; + + enum class PrivilegeMode: std::uint8_t + { + U_MODE = 0x00, + S_MODE = 0x01, + M_MODE = 0x03, + }; +}