From 1392cda74f4d580aab7d94d3df12b2c7bd9356e5 Mon Sep 17 00:00:00 2001 From: Nav Date: Sun, 15 Dec 2024 00:41:49 +0000 Subject: [PATCH] Adding boot/user mode switching functionality for WCH RISC-V targets --- src/Targets/DynamicRegisterValue.cpp | 8 ----- src/Targets/DynamicRegisterValue.hpp | 7 ++-- src/Targets/RiscV/Wch/WchRiscV.cpp | 53 ++++++++++++++++++++++++++++ src/Targets/RiscV/Wch/WchRiscV.hpp | 13 +++++++ 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/Targets/DynamicRegisterValue.cpp b/src/Targets/DynamicRegisterValue.cpp index 34b4c626..1ccc90ab 100644 --- a/src/Targets/DynamicRegisterValue.cpp +++ b/src/Targets/DynamicRegisterValue.cpp @@ -69,14 +69,6 @@ namespace Targets return this->bitField(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey)); } - bool DynamicRegisterValue::bitFieldFlag(const TargetBitFieldDescriptor& bitFieldDescriptor) const { - return static_cast(this->bitField(bitFieldDescriptor)); - } - - bool DynamicRegisterValue::bitFieldFlag(const std::string& bitFieldKey) const { - return this->bitFieldFlag(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey)); - } - TargetMemoryBuffer DynamicRegisterValue::data() const { auto output = TargetMemoryBuffer(this->registerDescriptor.size, 0x00); diff --git a/src/Targets/DynamicRegisterValue.hpp b/src/Targets/DynamicRegisterValue.hpp index fb7e6057..7dfc6e65 100644 --- a/src/Targets/DynamicRegisterValue.hpp +++ b/src/Targets/DynamicRegisterValue.hpp @@ -24,8 +24,11 @@ namespace Targets [[nodiscard]] std::uint64_t bitField(const TargetBitFieldDescriptor& bitFieldDescriptor) const; [[nodiscard]] std::uint64_t bitField(const std::string& bitFieldKey) const; - [[nodiscard]] bool bitFieldFlag(const TargetBitFieldDescriptor& bitFieldDescriptor) const; - [[nodiscard]] bool bitFieldFlag(const std::string& bitFieldKey) const; + + template + [[nodiscard]] ReturnType bitFieldAs(const TargetBitFieldDescriptor& bitFieldDescriptor) const { + return static_cast(this->bitField(bitFieldDescriptor)); + } [[nodiscard]] TargetMemoryBuffer data() const; }; diff --git a/src/Targets/RiscV/Wch/WchRiscV.cpp b/src/Targets/RiscV/Wch/WchRiscV.cpp index 57f77143..cb2ee4a5 100644 --- a/src/Targets/RiscV/Wch/WchRiscV.cpp +++ b/src/Targets/RiscV/Wch/WchRiscV.cpp @@ -3,6 +3,9 @@ #include #include + +#include "src/Targets/DynamicRegisterValue.hpp" + #include "src/Exceptions/InvalidConfig.hpp" #include "src/Exceptions/Exception.hpp" @@ -28,6 +31,12 @@ namespace Targets::RiscV::Wch ? this->bootProgramSegmentDescriptor : this->mainProgramSegmentDescriptor ) + , flashPeripheralDescriptor(this->targetDescriptionFile.getTargetPeripheralDescriptor("flash")) + , flashKeyRegisterDescriptor(this->flashPeripheralDescriptor.getRegisterDescriptor("flash", "keyr")) + , flashBootKeyRegisterDescriptor(this->flashPeripheralDescriptor.getRegisterDescriptor("flash", "boot_modekeyr")) + , flashStatusRegisterDescriptor(this->flashPeripheralDescriptor.getRegisterDescriptor("flash", "statr")) + , flashStatusBootLockFieldDescriptor(this->flashStatusRegisterDescriptor.getBitFieldDescriptor("boot_lock")) + , flashStatusBootModeFieldDescriptor(this->flashStatusRegisterDescriptor.getBitFieldDescriptor("boot_mode")) { Logger::info( "Selected program memory segment: \"" + this->selectedProgramSegmentDescriptor.name + "\" (\"" @@ -390,4 +399,48 @@ namespace Targets::RiscV::Wch return transformedAddress; } + + void WchRiscV::unlockFlash() { + // TODO: Move these key values to a TDF property. After v2.0.0 + this->writeRegister(this->flashKeyRegisterDescriptor, 0x45670123); + this->writeRegister(this->flashKeyRegisterDescriptor, 0xCDEF89AB); + } + + void WchRiscV::unlockBootModeBitField() { + // TODO: Move these key values to a TDF property. After v2.0.0 + this->writeRegister(this->flashBootKeyRegisterDescriptor, 0x45670123); + this->writeRegister(this->flashBootKeyRegisterDescriptor, 0xCDEF89AB); + } + + void WchRiscV::enableBootMode() { + this->unlockFlash(); + this->unlockBootModeBitField(); + + auto statusRegister = this->readRegisterDynamicValue(this->flashStatusRegisterDescriptor); + + if (statusRegister.bitFieldAs(this->flashStatusBootLockFieldDescriptor)) { + throw Exceptions::Exception{"Failed to unlock boot mode field"}; + } + + statusRegister.setBitField(this->flashStatusBootModeFieldDescriptor, true); + this->writeRegister(this->flashStatusRegisterDescriptor, statusRegister.data()); + + this->reset(); + } + + void WchRiscV::enableUserMode() { + this->unlockFlash(); + this->unlockBootModeBitField(); + + auto statusRegister = this->readRegisterDynamicValue(this->flashStatusRegisterDescriptor); + + if (statusRegister.bitFieldAs(this->flashStatusBootLockFieldDescriptor)) { + throw Exceptions::Exception{"Failed to unlock boot mode field"}; + } + + statusRegister.setBitField(this->flashStatusBootModeFieldDescriptor, false); + this->writeRegister(this->flashStatusRegisterDescriptor, statusRegister.data()); + + this->reset(); + } } diff --git a/src/Targets/RiscV/Wch/WchRiscV.hpp b/src/Targets/RiscV/Wch/WchRiscV.hpp index ede117ce..86dfa06c 100644 --- a/src/Targets/RiscV/Wch/WchRiscV.hpp +++ b/src/Targets/RiscV/Wch/WchRiscV.hpp @@ -73,10 +73,23 @@ namespace Targets::RiscV::Wch */ const TargetMemorySegmentDescriptor& selectedProgramSegmentDescriptor; + const TargetPeripheralDescriptor flashPeripheralDescriptor; + const TargetRegisterDescriptor& flashKeyRegisterDescriptor; + const TargetRegisterDescriptor& flashBootKeyRegisterDescriptor; + const TargetRegisterDescriptor& flashStatusRegisterDescriptor; + + const TargetBitFieldDescriptor& flashStatusBootLockFieldDescriptor; + const TargetBitFieldDescriptor& flashStatusBootModeFieldDescriptor; + const TargetMemorySegmentDescriptor& resolveAliasedMemorySegment(); TargetMemoryAddress transformMappedAddress( TargetMemoryAddress address, const TargetMemorySegmentDescriptor& segmentDescriptor ); + + void unlockFlash(); + void unlockBootModeBitField(); + void enableBootMode(); + void enableUserMode(); }; }