Made a start with RISC-V target implementation
This commit is contained in:
@@ -9,4 +9,5 @@ target_sources(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/PhysicalInterface.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/OpcodeDecoder/Decoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/RiscV/RiscV.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Targets::RiscV::DebugModule::Registers
|
||||
{
|
||||
enum RegisterAddresses: std::uint8_t
|
||||
{
|
||||
CONTROL_REGISTER = 0x10,
|
||||
STATUS_REGISTER = 0x11,
|
||||
};
|
||||
}
|
||||
223
src/Targets/RiscV/RiscV.cpp
Normal file
223
src/Targets/RiscV/RiscV.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
#include "RiscV.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "DebugModule/Registers/RegisterAddresses.hpp"
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
namespace Targets::RiscV
|
||||
{
|
||||
using DebugModule::Registers::RegisterAddresses;
|
||||
using DebugModule::Registers::ControlRegister;
|
||||
using DebugModule::Registers::StatusRegister;
|
||||
|
||||
RiscV::RiscV(const TargetConfig& targetConfig)
|
||||
: name("CH32X035C8T6") // TODO: TDF
|
||||
{}
|
||||
|
||||
bool RiscV::supportsDebugTool(DebugTool* debugTool) {
|
||||
return debugTool->getRiscVDebugInterface() != nullptr;
|
||||
}
|
||||
|
||||
void RiscV::setDebugTool(DebugTool* debugTool) {
|
||||
this->riscVDebugInterface = debugTool->getRiscVDebugInterface();
|
||||
}
|
||||
|
||||
void RiscV::activate() {
|
||||
this->riscVDebugInterface->activate({});
|
||||
|
||||
// TODO: Select a hart here.
|
||||
|
||||
this->stop();
|
||||
}
|
||||
|
||||
void RiscV::deactivate() {
|
||||
this->riscVDebugInterface->deactivate();
|
||||
}
|
||||
|
||||
TargetDescriptor RiscV::getDescriptor() {
|
||||
return TargetDescriptor(
|
||||
"TDF ID",
|
||||
TargetFamily::RISC_V,
|
||||
this->name,
|
||||
"TDF VENDOR NAME",
|
||||
{
|
||||
{
|
||||
Targets::TargetMemoryType::FLASH,
|
||||
TargetMemoryDescriptor(
|
||||
Targets::TargetMemoryType::FLASH,
|
||||
Targets::TargetMemoryAddressRange(0x00, 0x1000),
|
||||
Targets::TargetMemoryAccess(true, true, false)
|
||||
)
|
||||
}
|
||||
},
|
||||
{},
|
||||
BreakpointResources(0, 0, 0),
|
||||
{},
|
||||
TargetMemoryType::FLASH
|
||||
);
|
||||
}
|
||||
|
||||
void RiscV::run(std::optional<TargetMemoryAddress> toAddress) {
|
||||
auto controlRegister = ControlRegister();
|
||||
controlRegister.debugModuleActive = true;
|
||||
controlRegister.resumeRequest = true;
|
||||
|
||||
this->writeControlRegister(controlRegister);
|
||||
|
||||
constexpr auto maxAttempts = 10;
|
||||
auto statusRegister = this->readStatusRegister();
|
||||
|
||||
for (auto attempts = 1; !statusRegister.allResumeAcknowledge && attempts <= maxAttempts; ++attempts) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
statusRegister = this->readStatusRegister();
|
||||
}
|
||||
|
||||
controlRegister.resumeRequest = false;
|
||||
this->writeControlRegister(controlRegister);
|
||||
|
||||
if (!statusRegister.allResumeAcknowledge) {
|
||||
throw Exceptions::Exception("Target took too long to acknowledge resume request");
|
||||
}
|
||||
}
|
||||
|
||||
void RiscV::stop() {
|
||||
auto controlRegister = ControlRegister();
|
||||
controlRegister.debugModuleActive = true;
|
||||
controlRegister.haltRequest = true;
|
||||
|
||||
this->writeControlRegister(controlRegister);
|
||||
|
||||
constexpr auto maxAttempts = 10;
|
||||
auto statusRegister = this->readStatusRegister();
|
||||
|
||||
for (auto attempts = 1; !statusRegister.allHalted && attempts <= maxAttempts; ++attempts) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
statusRegister = this->readStatusRegister();
|
||||
}
|
||||
|
||||
controlRegister.haltRequest = false;
|
||||
this->writeControlRegister(controlRegister);
|
||||
|
||||
if (!statusRegister.allHalted) {
|
||||
throw Exceptions::Exception("Target took too long to halt selected harts");
|
||||
}
|
||||
}
|
||||
|
||||
void RiscV::step() {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::reset() {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::setSoftwareBreakpoint(TargetMemoryAddress address) {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::removeSoftwareBreakpoint(TargetMemoryAddress address) {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::setHardwareBreakpoint(TargetMemoryAddress address) {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::removeHardwareBreakpoint(TargetMemoryAddress address) {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::clearAllBreakpoints() {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::writeRegisters(TargetRegisters registers) {
|
||||
|
||||
}
|
||||
|
||||
TargetRegisters RiscV::readRegisters(const Targets::TargetRegisterDescriptorIds& descriptorIds) {
|
||||
return {};
|
||||
}
|
||||
|
||||
TargetMemoryBuffer RiscV::readMemory(
|
||||
TargetMemoryType memoryType,
|
||||
TargetMemoryAddress startAddress,
|
||||
TargetMemorySize bytes,
|
||||
const std::set<Targets::TargetMemoryAddressRange>& excludedAddressRanges
|
||||
) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void RiscV::writeMemory(
|
||||
TargetMemoryType memoryType,
|
||||
TargetMemoryAddress startAddress,
|
||||
const TargetMemoryBuffer& buffer
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::eraseMemory(TargetMemoryType memoryType) {
|
||||
|
||||
}
|
||||
|
||||
TargetState RiscV::getState() {
|
||||
return TargetState::STOPPED;
|
||||
}
|
||||
|
||||
TargetMemoryAddress RiscV::getProgramCounter() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RiscV::setProgramCounter(TargetMemoryAddress programCounter) {
|
||||
|
||||
}
|
||||
|
||||
TargetStackPointer RiscV::getStackPointer() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<int, TargetPinState> RiscV::getPinStates(int variantId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void RiscV::setPinState(
|
||||
const TargetPinDescriptor& pinDescriptor,
|
||||
const TargetPinState& state
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::enableProgrammingMode() {
|
||||
|
||||
}
|
||||
|
||||
void RiscV::disableProgrammingMode() {
|
||||
|
||||
}
|
||||
|
||||
bool RiscV::programmingModeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
ControlRegister RiscV::readControlRegister() {
|
||||
return ControlRegister(
|
||||
this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::CONTROL_REGISTER)
|
||||
);
|
||||
}
|
||||
|
||||
StatusRegister RiscV::readStatusRegister() {
|
||||
return StatusRegister(this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::STATUS_REGISTER));
|
||||
}
|
||||
|
||||
void RiscV::writeControlRegister(const ControlRegister& controlRegister) {
|
||||
this->riscVDebugInterface->writeDebugModuleRegister(
|
||||
RegisterAddresses::CONTROL_REGISTER,
|
||||
controlRegister.value()
|
||||
);
|
||||
}
|
||||
}
|
||||
99
src/Targets/RiscV/RiscV.hpp
Normal file
99
src/Targets/RiscV/RiscV.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/Targets/Target.hpp"
|
||||
#include "src/DebugToolDrivers/DebugTool.hpp"
|
||||
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
|
||||
|
||||
#include "src/Targets/RiscV/DebugModule/DebugModule.hpp"
|
||||
#include "src/Targets/RiscV/DebugModule/Registers/ControlRegister.hpp"
|
||||
#include "src/Targets/RiscV/DebugModule/Registers/StatusRegister.hpp"
|
||||
|
||||
namespace Targets::RiscV
|
||||
{
|
||||
class RiscV: public Target
|
||||
{
|
||||
public:
|
||||
explicit RiscV(const TargetConfig& targetConfig);
|
||||
|
||||
/*
|
||||
* The functions below implement the Target interface for RISC-V targets.
|
||||
*
|
||||
* See the Targets::Target abstract class for documentation on the expected behaviour of
|
||||
* each function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* All RISC-V compatible debug tools must provide a valid RiscVDebugInterface.
|
||||
*
|
||||
* @param debugTool
|
||||
* @return
|
||||
*/
|
||||
bool supportsDebugTool(DebugTool* debugTool) override;
|
||||
|
||||
void setDebugTool(DebugTool* debugTool) override;
|
||||
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
TargetDescriptor getDescriptor() override;
|
||||
|
||||
void run(std::optional<TargetMemoryAddress> toAddress = std::nullopt) override;
|
||||
void stop() override;
|
||||
void step() override;
|
||||
void reset() override;
|
||||
|
||||
void setSoftwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void removeSoftwareBreakpoint(TargetMemoryAddress address) override;
|
||||
|
||||
void setHardwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void removeHardwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void clearAllBreakpoints() override;
|
||||
|
||||
void writeRegisters(TargetRegisters registers) override;
|
||||
TargetRegisters readRegisters(const Targets::TargetRegisterDescriptorIds& descriptorIds) override;
|
||||
|
||||
TargetMemoryBuffer readMemory(
|
||||
TargetMemoryType memoryType,
|
||||
TargetMemoryAddress startAddress,
|
||||
TargetMemorySize bytes,
|
||||
const std::set<Targets::TargetMemoryAddressRange>& excludedAddressRanges = {}
|
||||
) override;
|
||||
void writeMemory(
|
||||
TargetMemoryType memoryType,
|
||||
TargetMemoryAddress startAddress,
|
||||
const TargetMemoryBuffer& buffer
|
||||
) override;
|
||||
void eraseMemory(TargetMemoryType memoryType) override;
|
||||
|
||||
TargetState getState() override;
|
||||
|
||||
TargetMemoryAddress getProgramCounter() override;
|
||||
void setProgramCounter(TargetMemoryAddress programCounter) override;
|
||||
|
||||
TargetStackPointer getStackPointer() override;
|
||||
|
||||
std::map<int, TargetPinState> getPinStates(int variantId) override;
|
||||
void setPinState(
|
||||
const TargetPinDescriptor& pinDescriptor,
|
||||
const TargetPinState& state
|
||||
) override;
|
||||
|
||||
void enableProgrammingMode() override;
|
||||
|
||||
void disableProgrammingMode() override;
|
||||
|
||||
bool programmingModeEnabled() override;
|
||||
|
||||
protected:
|
||||
DebugToolDrivers::TargetInterfaces::RiscV::RiscVDebugInterface* riscVDebugInterface = nullptr;
|
||||
std::string name;
|
||||
|
||||
DebugModule::Registers::ControlRegister readControlRegister();
|
||||
DebugModule::Registers::StatusRegister readStatusRegister();
|
||||
|
||||
void writeControlRegister(const DebugModule::Registers::ControlRegister& controlRegister);
|
||||
};
|
||||
}
|
||||
@@ -2,3 +2,4 @@
|
||||
|
||||
#include "src/Targets/Target.hpp"
|
||||
#include "src/Targets/Microchip/AVR/AVR8/Avr8.hpp"
|
||||
#include "src/Targets/RiscV/RiscV.hpp"
|
||||
|
||||
Reference in New Issue
Block a user