WCH RISC-V software breakpoints, and a few other bits of refactoring/tidying
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
namespace Targets::RiscV::Opcodes
|
||||
{
|
||||
using Opcode = std::uint32_t;
|
||||
using OpcodeCompressed = std::uint16_t;
|
||||
|
||||
enum class GprNumber: std::uint8_t
|
||||
{
|
||||
@@ -14,4 +15,8 @@ namespace Targets::RiscV::Opcodes
|
||||
};
|
||||
|
||||
static constexpr auto Ebreak = Opcode{0x00100073};
|
||||
static constexpr auto EbreakCompressed = OpcodeCompressed{0x9002};
|
||||
|
||||
static constexpr auto Fence = Opcode{0x0000000f};
|
||||
static constexpr auto FenceI = Opcode{0x0000100f};
|
||||
}
|
||||
|
||||
23
src/Targets/RiscV/ProgramBreakpoint.hpp
Normal file
23
src/Targets/RiscV/ProgramBreakpoint.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
#include "Opcodes/Opcode.hpp"
|
||||
|
||||
namespace Targets::RiscV
|
||||
{
|
||||
struct ProgramBreakpoint: TargetProgramBreakpoint
|
||||
{
|
||||
std::optional<Opcodes::Opcode> originalInstruction = std::nullopt;
|
||||
|
||||
explicit ProgramBreakpoint(const TargetProgramBreakpoint& breakpoint)
|
||||
: TargetProgramBreakpoint(breakpoint)
|
||||
{}
|
||||
|
||||
explicit ProgramBreakpoint(const TargetProgramBreakpoint& breakpoint, Opcodes::Opcode originalInstruction)
|
||||
: TargetProgramBreakpoint(breakpoint)
|
||||
, originalInstruction(originalInstruction)
|
||||
{}
|
||||
};
|
||||
}
|
||||
@@ -59,8 +59,6 @@ namespace Targets::RiscV
|
||||
this->stop();
|
||||
}
|
||||
|
||||
this->clearAllBreakpoints();
|
||||
this->run();
|
||||
this->riscVDebugInterface->deactivate();
|
||||
}
|
||||
|
||||
@@ -80,26 +78,6 @@ namespace Targets::RiscV
|
||||
this->riscVDebugInterface->reset();
|
||||
}
|
||||
|
||||
void RiscV::setSoftwareBreakpoint(TargetMemoryAddress address) {
|
||||
throw Exceptions::Exception{"TARGET - SW breakpoints not supported"};
|
||||
}
|
||||
|
||||
void RiscV::removeSoftwareBreakpoint(TargetMemoryAddress address) {
|
||||
throw Exceptions::Exception{"TARGET - SW breakpoints not supported"};
|
||||
}
|
||||
|
||||
void RiscV::setHardwareBreakpoint(TargetMemoryAddress address) {
|
||||
this->riscVDebugInterface->setHardwareBreakpoint(address);
|
||||
}
|
||||
|
||||
void RiscV::removeHardwareBreakpoint(TargetMemoryAddress address) {
|
||||
this->riscVDebugInterface->clearHardwareBreakpoint(address);
|
||||
}
|
||||
|
||||
void RiscV::clearAllBreakpoints() {
|
||||
this->riscVDebugInterface->clearAllHardwareBreakpoints();
|
||||
}
|
||||
|
||||
TargetRegisterDescriptorAndValuePairs RiscV::readRegisters(const TargetRegisterDescriptors& descriptors) {
|
||||
auto output = TargetRegisterDescriptorAndValuePairs{};
|
||||
|
||||
@@ -316,10 +294,12 @@ namespace Targets::RiscV
|
||||
}
|
||||
|
||||
void RiscV::enableProgrammingMode() {
|
||||
this->riscVDebugInterface->enableProgrammingMode();
|
||||
this->programmingMode = true;
|
||||
}
|
||||
|
||||
void RiscV::disableProgrammingMode() {
|
||||
this->riscVDebugInterface->disableProgrammingMode();
|
||||
this->programmingMode = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,13 +38,6 @@ namespace Targets::RiscV
|
||||
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;
|
||||
|
||||
TargetRegisterDescriptorAndValuePairs readRegisters(const TargetRegisterDescriptors& descriptors) override;
|
||||
void writeRegisters(const TargetRegisterDescriptorAndValuePairs& registers) override;
|
||||
|
||||
@@ -84,9 +77,7 @@ namespace Targets::RiscV
|
||||
void setGpioPadState(const TargetPadDescriptor& padDescriptor, const TargetGpioPadState& state) override;
|
||||
|
||||
void enableProgrammingMode() override;
|
||||
|
||||
void disableProgrammingMode() override;
|
||||
|
||||
bool programmingModeEnabled() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -47,8 +47,6 @@ namespace Targets::RiscV::Wch
|
||||
}
|
||||
|
||||
TargetDescriptor WchRiscV::targetDescriptor() {
|
||||
const auto hardwareBreakpointCount = this->riscVDebugInterface->getHardwareBreakpointCount();
|
||||
|
||||
auto descriptor = TargetDescriptor{
|
||||
this->targetDescriptionFile.getName(),
|
||||
this->targetDescriptionFile.getFamily(),
|
||||
@@ -59,15 +57,16 @@ namespace Targets::RiscV::Wch
|
||||
this->targetDescriptionFile.targetPadDescriptorsByKey(),
|
||||
this->targetDescriptionFile.targetPinoutDescriptorsByKey(),
|
||||
this->targetDescriptionFile.targetVariantDescriptorsByKey(),
|
||||
BreakpointResources{
|
||||
hardwareBreakpointCount,
|
||||
std::nullopt,
|
||||
static_cast<std::uint16_t>(
|
||||
this->targetConfig.reserveSteppingBreakpoint.value_or(false) && hardwareBreakpointCount > 0 ? 1 : 0
|
||||
)
|
||||
}
|
||||
this->riscVDebugInterface->getBreakpointResources()
|
||||
};
|
||||
|
||||
if (
|
||||
this->targetConfig.reserveSteppingBreakpoint.value_or(false)
|
||||
&& descriptor.breakpointResources.hardwareBreakpoints > 0
|
||||
) {
|
||||
descriptor.breakpointResources.reservedHardwareBreakpoints = 1;
|
||||
}
|
||||
|
||||
// Copy the RISC-V CPU register address space and peripheral descriptor
|
||||
descriptor.addressSpaceDescriptorsByKey.emplace(
|
||||
this->cpuRegisterAddressSpaceDescriptor.key,
|
||||
@@ -100,6 +99,44 @@ namespace Targets::RiscV::Wch
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
void WchRiscV::setProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) {
|
||||
if (
|
||||
breakpoint.type == TargetProgramBreakpoint::Type::SOFTWARE
|
||||
&& breakpoint.memorySegmentDescriptor == this->mappedProgramMemorySegmentDescriptor
|
||||
) {
|
||||
this->riscVDebugInterface->setProgramBreakpoint(TargetProgramBreakpoint{
|
||||
.addressSpaceDescriptor = this->sysAddressSpaceDescriptor,
|
||||
.memorySegmentDescriptor = this->getDestinationProgramMemorySegmentDescriptor(),
|
||||
.address = this->transformAliasedProgramMemoryAddress(breakpoint.address),
|
||||
.size = breakpoint.size,
|
||||
.type = breakpoint.type
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this->riscVDebugInterface->setProgramBreakpoint(breakpoint);
|
||||
}
|
||||
|
||||
void WchRiscV::removeProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) {
|
||||
if (
|
||||
breakpoint.type == TargetProgramBreakpoint::Type::SOFTWARE
|
||||
&& breakpoint.memorySegmentDescriptor == this->mappedProgramMemorySegmentDescriptor
|
||||
) {
|
||||
this->riscVDebugInterface->removeProgramBreakpoint(TargetProgramBreakpoint{
|
||||
.addressSpaceDescriptor = this->sysAddressSpaceDescriptor,
|
||||
.memorySegmentDescriptor = this->getDestinationProgramMemorySegmentDescriptor(),
|
||||
.address = this->transformAliasedProgramMemoryAddress(breakpoint.address),
|
||||
.size = breakpoint.size,
|
||||
.type = breakpoint.type
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this->riscVDebugInterface->removeProgramBreakpoint(breakpoint);
|
||||
}
|
||||
|
||||
void WchRiscV::writeMemory(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
@@ -119,13 +156,35 @@ namespace Targets::RiscV::Wch
|
||||
* before v2.0.0.
|
||||
*/
|
||||
if (memorySegmentDescriptor == this->mappedProgramMemorySegmentDescriptor) {
|
||||
const auto newAddress = startAddress - this->mappedProgramMemorySegmentDescriptor.addressRange.startAddress
|
||||
+ this->programMemorySegmentDescriptor.addressRange.startAddress;
|
||||
assert(this->programMemorySegmentDescriptor.addressRange.contains(newAddress));
|
||||
const auto transformedAddress = this->transformAliasedProgramMemoryAddress(startAddress);
|
||||
assert(this->programMemorySegmentDescriptor.addressRange.contains(transformedAddress));
|
||||
|
||||
return RiscV::writeMemory(addressSpaceDescriptor, this->programMemorySegmentDescriptor, newAddress, buffer);
|
||||
return RiscV::writeMemory(
|
||||
addressSpaceDescriptor,
|
||||
this->programMemorySegmentDescriptor,
|
||||
transformedAddress,
|
||||
buffer
|
||||
);
|
||||
}
|
||||
|
||||
return RiscV::writeMemory(addressSpaceDescriptor, memorySegmentDescriptor, startAddress, buffer);
|
||||
}
|
||||
|
||||
const TargetMemorySegmentDescriptor& WchRiscV::getDestinationProgramMemorySegmentDescriptor() {
|
||||
return this->programMemorySegmentDescriptor;
|
||||
}
|
||||
|
||||
TargetMemoryAddress WchRiscV::transformAliasedProgramMemoryAddress(TargetMemoryAddress address) const {
|
||||
using Services::StringService;
|
||||
|
||||
const auto transformedAddress = address - this->mappedProgramMemorySegmentDescriptor.addressRange.startAddress
|
||||
+ this->programMemorySegmentDescriptor.addressRange.startAddress;
|
||||
|
||||
Logger::debug(
|
||||
"Transformed mapped program memory address 0x" + StringService::toHex(address) + " to 0x"
|
||||
+ StringService::toHex(transformedAddress)
|
||||
);
|
||||
|
||||
return transformedAddress;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ namespace Targets::RiscV::Wch
|
||||
void postActivate() override;
|
||||
TargetDescriptor targetDescriptor() override;
|
||||
|
||||
void setProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) override;
|
||||
void removeProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) override;
|
||||
|
||||
void writeMemory(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
@@ -31,6 +34,10 @@ namespace Targets::RiscV::Wch
|
||||
std::optional<std::reference_wrapper<const TargetDescription::Variant>> variant = std::nullopt;
|
||||
|
||||
const TargetMemorySegmentDescriptor& programMemorySegmentDescriptor;
|
||||
const TargetMemorySegmentDescriptor& bootProgramMemorySegmentDescriptor;
|
||||
const TargetMemorySegmentDescriptor& mappedProgramMemorySegmentDescriptor;
|
||||
|
||||
const TargetMemorySegmentDescriptor& getDestinationProgramMemorySegmentDescriptor();
|
||||
TargetMemoryAddress transformAliasedProgramMemoryAddress(TargetMemoryAddress address) const;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user