Adding boot/user mode switching functionality for WCH RISC-V targets

This commit is contained in:
Nav
2024-12-15 00:41:49 +00:00
parent 4ff7c76621
commit 1392cda74f
4 changed files with 71 additions and 10 deletions

View File

@@ -69,14 +69,6 @@ namespace Targets
return this->bitField(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey));
}
bool DynamicRegisterValue::bitFieldFlag(const TargetBitFieldDescriptor& bitFieldDescriptor) const {
return static_cast<bool>(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);

View File

@@ -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 <typename ReturnType>
[[nodiscard]] ReturnType bitFieldAs(const TargetBitFieldDescriptor& bitFieldDescriptor) const {
return static_cast<ReturnType>(this->bitField(bitFieldDescriptor));
}
[[nodiscard]] TargetMemoryBuffer data() const;
};

View File

@@ -3,6 +3,9 @@
#include <utility>
#include <cassert>
#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<bool>(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<bool>(this->flashStatusBootLockFieldDescriptor)) {
throw Exceptions::Exception{"Failed to unlock boot mode field"};
}
statusRegister.setBitField(this->flashStatusBootModeFieldDescriptor, false);
this->writeRegister(this->flashStatusRegisterDescriptor, statusRegister.data());
this->reset();
}
}

View File

@@ -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();
};
}