From 00919e40577b5f5e20fa016a7ffda4b9968390be Mon Sep 17 00:00:00 2001 From: Nav Date: Fri, 13 Dec 2024 22:48:20 +0000 Subject: [PATCH] WCH-Link erase command doesn't erase the whole chip, as initially thought. It only erases the program memory segment. The boot segment appears to be left untouched. --- .../RiscVGdb/CommandPackets/FlashErase.cpp | 21 +++++++++++++++---- .../{EraseChip.hpp => EraseProgramMemory.hpp} | 4 ++-- .../Protocols/WchLink/WchLinkInterface.cpp | 6 +++--- .../Protocols/WchLink/WchLinkInterface.hpp | 2 +- .../WCH/WchLinkDebugInterface.cpp | 15 ++++++------- .../WCH/WchLinkDebugInterface.hpp | 3 ++- 6 files changed, 33 insertions(+), 18 deletions(-) rename src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/{EraseChip.hpp => EraseProgramMemory.hpp} (75%) diff --git a/src/DebugServer/Gdb/RiscVGdb/CommandPackets/FlashErase.cpp b/src/DebugServer/Gdb/RiscVGdb/CommandPackets/FlashErase.cpp index 686cae15..07e99dd1 100644 --- a/src/DebugServer/Gdb/RiscVGdb/CommandPackets/FlashErase.cpp +++ b/src/DebugServer/Gdb/RiscVGdb/CommandPackets/FlashErase.cpp @@ -45,14 +45,27 @@ namespace DebugServer::Gdb::RiscVGdb::CommandPackets Logger::info("Handling FlashErase packet"); try { + const auto segmentDescriptorOpt = gdbTargetDescriptor.systemAddressSpaceDescriptor.getContainingMemorySegmentDescriptor( + this->startAddress + ); + + if (!segmentDescriptorOpt.has_value()) { + throw Exception{"Invalid command - no containing memory segment found for the given start address"}; + } + + const auto& segmentDescriptor = segmentDescriptorOpt->get(); + if (!segmentDescriptor.programmingModeAccess.writeable) { + throw Exception{"Memory segment (\"" + segmentDescriptor.name + "\") not writable in programming mode"}; + } + + Logger::warning("Erasing \"" + segmentDescriptor.name + "\" segment, in preparation for programming"); + targetControllerService.enableProgrammingMode(); - Logger::warning("Erasing program memory, in preparation for programming"); - - // We don't erase a specific address range - we just erase the entire program memory. + // We don't erase a specific address range - we just erase the entire segment targetControllerService.eraseMemory( gdbTargetDescriptor.systemAddressSpaceDescriptor, - gdbTargetDescriptor.programMemorySegmentDescriptor + segmentDescriptor ); debugSession.connection.writePacket(OkResponsePacket{}); diff --git a/src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/EraseChip.hpp b/src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/EraseProgramMemory.hpp similarity index 75% rename from src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/EraseChip.hpp rename to src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/EraseProgramMemory.hpp index 5a9f2102..a9d67faa 100644 --- a/src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/EraseChip.hpp +++ b/src/DebugToolDrivers/WCH/Protocols/WchLink/Commands/EraseProgramMemory.hpp @@ -6,10 +6,10 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink::Commands { - class EraseChip: public Command> + class EraseProgramMemory: public Command> { public: - EraseChip() + EraseProgramMemory() : Command(0x02) { this->payload = { diff --git a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp index 6525c920..de5cac75 100644 --- a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp +++ b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.cpp @@ -16,7 +16,7 @@ #include "Commands/StartRamCodeWrite.hpp" #include "Commands/EndRamCodeWrite.hpp" #include "Commands/WriteFlash.hpp" -#include "Commands/EraseChip.hpp" +#include "Commands/EraseProgramMemory.hpp" #include "src/Helpers/BiMap.hpp" #include "src/Services/StringService.hpp" @@ -243,7 +243,7 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink this->sendCommandAndWaitForResponse(Commands::EndProgrammingSession{}); } - void WchLinkInterface::eraseChip() { - this->sendCommandAndWaitForResponse(Commands::EraseChip{}); + void WchLinkInterface::eraseProgramMemory() { + this->sendCommandAndWaitForResponse(Commands::EraseProgramMemory{}); } } diff --git a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp index ed1e6901..a72b5f8d 100644 --- a/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp +++ b/src/DebugToolDrivers/WCH/Protocols/WchLink/WchLinkInterface.hpp @@ -52,7 +52,7 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink Targets::TargetMemorySize blockSize, std::span flashProgramOpcodes ); - void eraseChip(); + void eraseProgramMemory(); template auto sendCommandAndWaitForResponse(const CommandType& command) { diff --git a/src/DebugToolDrivers/WCH/WchLinkDebugInterface.cpp b/src/DebugToolDrivers/WCH/WchLinkDebugInterface.cpp index 6571f4cb..ca9658df 100644 --- a/src/DebugToolDrivers/WCH/WchLinkDebugInterface.cpp +++ b/src/DebugToolDrivers/WCH/WchLinkDebugInterface.cpp @@ -57,6 +57,11 @@ namespace DebugToolDrivers::Wch this->targetConfig } ) + , programSegmentDescriptor( + this->targetDescriptionFile.getSystemAddressSpaceDescriptor().getMemorySegmentDescriptor( + "internal_program_memory" + ) + ) , flashProgramOpcodes( WchLinkDebugInterface::getFlashProgramOpcodes( this->targetDescriptionFile.getProperty("wch_link_interface", "programming_opcode_key").value @@ -352,11 +357,11 @@ namespace DebugToolDrivers::Wch const TargetAddressSpaceDescriptor& addressSpaceDescriptor, const TargetMemorySegmentDescriptor& memorySegmentDescriptor ) { - if (memorySegmentDescriptor.type == TargetMemorySegmentType::FLASH) { - return this->eraseFlashMemory(); + if (memorySegmentDescriptor == this->programSegmentDescriptor) { + return this->wchLinkInterface.eraseProgramMemory(); } - throw Exception{"Erasing non-flash memory not supported in WchLinkDebugInterface"}; + // Ignore other (non-program memory) erase requests, for now. } void WchLinkDebugInterface::enableProgrammingMode() { @@ -471,10 +476,6 @@ namespace DebugToolDrivers::Wch this->softwareBreakpointRegistry.remove(softwareBreakpoint); } - void WchLinkDebugInterface::eraseFlashMemory() { - this->wchLinkInterface.eraseChip(); - } - std::span WchLinkDebugInterface::getFlashProgramOpcodes(const std::string& key) { if (key == "op1") { return FlashProgramOpcodes::FLASH_OP1; diff --git a/src/DebugToolDrivers/WCH/WchLinkDebugInterface.hpp b/src/DebugToolDrivers/WCH/WchLinkDebugInterface.hpp index b7d0f385..a3c0228c 100644 --- a/src/DebugToolDrivers/WCH/WchLinkDebugInterface.hpp +++ b/src/DebugToolDrivers/WCH/WchLinkDebugInterface.hpp @@ -89,6 +89,8 @@ namespace DebugToolDrivers::Wch Protocols::WchLink::WchLinkInterface& wchLinkInterface; DebugToolDrivers::Protocols::RiscVDebugSpec::DebugTranslator riscVTranslator; + const Targets::TargetMemorySegmentDescriptor& programSegmentDescriptor; + /** * The 'target activation' command returns a payload of 5 bytes. * @@ -107,7 +109,6 @@ namespace DebugToolDrivers::Wch void setSoftwareBreakpoint(const Targets::TargetProgramBreakpoint& breakpoint); void clearSoftwareBreakpoint(const Targets::TargetProgramBreakpoint& breakpoint); - void eraseFlashMemory(); static std::span getFlashProgramOpcodes(const std::string& key); }; }