Handle mapped program memory segment aliasing properly, on WCH RISC-V targets

- Added `program_segment_key` target config param, to allow the user to specify the desired program memory segment
- Added the ability to resolve the currently aliased segment, by means of probing the mapped segment
- Added program counter transformation, when the mapped segment is aliasing a foreign segment
- Other bites of tidying
This commit is contained in:
Nav
2024-12-14 02:09:25 +00:00
parent b5ffca6753
commit 2580cecb26
11 changed files with 384 additions and 87 deletions

View File

@@ -6,6 +6,7 @@
#include "src/Targets/RiscV/RiscV.hpp"
#include "WchRiscVTargetConfig.hpp"
#include "TargetDescriptionFile.hpp"
namespace Targets::RiscV::Wch
@@ -22,22 +23,60 @@ namespace Targets::RiscV::Wch
void setProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) override;
void removeProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) override;
TargetMemoryBuffer readMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
TargetMemoryAddress startAddress,
TargetMemorySize bytes,
const std::set<TargetMemoryAddressRange>& excludedAddressRanges
) override;
void writeMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
TargetMemoryAddress startAddress,
TargetMemoryBufferSpan buffer
) override;
void eraseMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor
) override;
TargetMemoryAddress getProgramCounter() override;
protected:
WchRiscVTargetConfig targetConfig;
TargetDescriptionFile targetDescriptionFile;
std::optional<std::reference_wrapper<const TargetDescription::Variant>> variant = std::nullopt;
const TargetMemorySegmentDescriptor& programMemorySegmentDescriptor;
const TargetMemorySegmentDescriptor& bootProgramMemorySegmentDescriptor;
const TargetMemorySegmentDescriptor& mappedProgramMemorySegmentDescriptor;
const TargetMemorySegmentDescriptor& mappedSegmentDescriptor;
const TargetMemorySegmentDescriptor& mainProgramSegmentDescriptor;
const TargetMemorySegmentDescriptor& bootProgramSegmentDescriptor;
const TargetMemorySegmentDescriptor& peripheralSegmentDescriptor;
const TargetMemorySegmentDescriptor& getDestinationProgramMemorySegmentDescriptor();
TargetMemoryAddress transformAliasedProgramMemoryAddress(TargetMemoryAddress address) const;
/*
* The selected program segment is the program memory segment the user has selected to be the subject of all
* memory accesses that are forwarded from the mapped program memory segment.
*
* In other words, whenever we service a memory access via the mapped program memory segment, we perform the
* operation on the selected program segment, instead. This prevents memory access requests from being
* misinterpreted in cases where the WCH target has switched to/from boot mode.
*
* The user can use the "program_segment_key" config param to specify the selected segment. If not provided,
* the selected segment defaults to the main program memory segment. This means, by default, we assume the user
* intends to debug the main user program, residing on the main program segment, as opposed to the boot program
* residing on the boot segment. If the user intends to debug their boot program, they must select the boot
* segment as the program segment, via the "program_segment_key" config param.
*
* I will explain this more clearly in the user documentation, on the Bloom website.
*
* For more, see the implementation of the memory access member functions.
*/
const TargetMemorySegmentDescriptor& selectedProgramSegmentDescriptor;
const TargetMemorySegmentDescriptor& resolveAliasedMemorySegment();
TargetMemoryAddress transformMappedAddress(
TargetMemoryAddress address,
const TargetMemorySegmentDescriptor& segmentDescriptor
);
};
}