RISC-V abstract commands
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#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<std::uint32_t>(registerValue & 0x00FFFFFF))
|
||||||
|
, commandType(static_cast<CommandType>((registerValue >> 24) & 0xFF))
|
||||||
|
{}
|
||||||
|
|
||||||
|
constexpr RegisterValue value() const {
|
||||||
|
assert(this->control <= 0x00FFFFFF);
|
||||||
|
|
||||||
|
return RegisterValue{0}
|
||||||
|
| static_cast<RegisterValue>(this->control & 0x00FFFFFF)
|
||||||
|
| static_cast<RegisterValue>(this->commandType) << 24
|
||||||
|
;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#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<std::uint8_t>(registerValue & 0x0F))
|
||||||
|
, commandError(static_cast<CommandError>((registerValue >> 8) & 0x07))
|
||||||
|
, relaxedPrivilege(static_cast<bool>(registerValue & (0x01 << 11)))
|
||||||
|
, busy(static_cast<bool>(registerValue & (0x01 << 12)))
|
||||||
|
, programBufferSize(static_cast<std::uint8_t>((registerValue >> 24) & 0x1F))
|
||||||
|
{}
|
||||||
|
|
||||||
|
constexpr RegisterValue value() const {
|
||||||
|
return RegisterValue{0}
|
||||||
|
| static_cast<RegisterValue>(this->dataCount)
|
||||||
|
| static_cast<RegisterValue>(this->commandError) << 8
|
||||||
|
| static_cast<RegisterValue>(this->relaxedPrivilege) << 11
|
||||||
|
| static_cast<RegisterValue>(this->busy) << 12
|
||||||
|
| static_cast<RegisterValue>(this->programBufferSize) << 24
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void clearCommandError() {
|
||||||
|
// Setting all of the bits will clear the field
|
||||||
|
this->commandError = CommandError::OTHER;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -6,7 +6,10 @@ namespace Targets::RiscV::DebugModule::Registers
|
|||||||
{
|
{
|
||||||
enum RegisterAddresses: std::uint8_t
|
enum RegisterAddresses: std::uint8_t
|
||||||
{
|
{
|
||||||
|
ABSTRACT_DATA_0 = 0x04,
|
||||||
CONTROL_REGISTER = 0x10,
|
CONTROL_REGISTER = 0x10,
|
||||||
STATUS_REGISTER = 0x11,
|
STATUS_REGISTER = 0x11,
|
||||||
|
ABSTRACT_CONTROL_STATUS_REGISTER = 0x16,
|
||||||
|
ABSTRACT_COMMAND_REGISTER = 0x17,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ namespace Targets::RiscV
|
|||||||
using DebugModule::Registers::RegisterAddresses;
|
using DebugModule::Registers::RegisterAddresses;
|
||||||
using DebugModule::Registers::ControlRegister;
|
using DebugModule::Registers::ControlRegister;
|
||||||
using DebugModule::Registers::StatusRegister;
|
using DebugModule::Registers::StatusRegister;
|
||||||
|
using DebugModule::Registers::AbstractControlStatusRegister;
|
||||||
|
using DebugModule::Registers::AbstractCommandRegister;
|
||||||
|
|
||||||
RiscV::RiscV(const TargetConfig& targetConfig)
|
RiscV::RiscV(const TargetConfig& targetConfig)
|
||||||
: name("CH32X035C8T6") // TODO: TDF
|
: name("CH32X035C8T6") // TODO: TDF
|
||||||
@@ -278,10 +280,43 @@ namespace Targets::RiscV
|
|||||||
return StatusRegister(this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::STATUS_REGISTER));
|
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) {
|
void RiscV::writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister) {
|
||||||
this->riscVDebugInterface->writeDebugModuleRegister(
|
this->riscVDebugInterface->writeDebugModuleRegister(
|
||||||
RegisterAddresses::CONTROL_REGISTER,
|
RegisterAddresses::CONTROL_REGISTER,
|
||||||
controlRegister.value()
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "src/Targets/RiscV/DebugModule/DebugModule.hpp"
|
#include "src/Targets/RiscV/DebugModule/DebugModule.hpp"
|
||||||
#include "src/Targets/RiscV/DebugModule/Registers/ControlRegister.hpp"
|
#include "src/Targets/RiscV/DebugModule/Registers/ControlRegister.hpp"
|
||||||
#include "src/Targets/RiscV/DebugModule/Registers/StatusRegister.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
|
namespace Targets::RiscV
|
||||||
{
|
{
|
||||||
@@ -99,7 +101,10 @@ namespace Targets::RiscV
|
|||||||
|
|
||||||
DebugModule::Registers::ControlRegister readDebugModuleControlRegister();
|
DebugModule::Registers::ControlRegister readDebugModuleControlRegister();
|
||||||
DebugModule::Registers::StatusRegister readDebugModuleStatusRegister();
|
DebugModule::Registers::StatusRegister readDebugModuleStatusRegister();
|
||||||
|
DebugModule::Registers::AbstractControlStatusRegister readDebugModuleAbstractControlStatusRegister();
|
||||||
|
|
||||||
|
|
||||||
void writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister);
|
void writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister);
|
||||||
|
void executeAbstractCommand(const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user