Adding boot/user mode switching functionality for WCH RISC-V targets
This commit is contained in:
@@ -69,14 +69,6 @@ namespace Targets
|
|||||||
return this->bitField(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey));
|
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 {
|
TargetMemoryBuffer DynamicRegisterValue::data() const {
|
||||||
auto output = TargetMemoryBuffer(this->registerDescriptor.size, 0x00);
|
auto output = TargetMemoryBuffer(this->registerDescriptor.size, 0x00);
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,11 @@ namespace Targets
|
|||||||
|
|
||||||
[[nodiscard]] std::uint64_t bitField(const TargetBitFieldDescriptor& bitFieldDescriptor) const;
|
[[nodiscard]] std::uint64_t bitField(const TargetBitFieldDescriptor& bitFieldDescriptor) const;
|
||||||
[[nodiscard]] std::uint64_t bitField(const std::string& bitFieldKey) 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;
|
[[nodiscard]] TargetMemoryBuffer data() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
#include "src/Targets/DynamicRegisterValue.hpp"
|
||||||
|
|
||||||
#include "src/Exceptions/InvalidConfig.hpp"
|
#include "src/Exceptions/InvalidConfig.hpp"
|
||||||
#include "src/Exceptions/Exception.hpp"
|
#include "src/Exceptions/Exception.hpp"
|
||||||
|
|
||||||
@@ -28,6 +31,12 @@ namespace Targets::RiscV::Wch
|
|||||||
? this->bootProgramSegmentDescriptor
|
? this->bootProgramSegmentDescriptor
|
||||||
: this->mainProgramSegmentDescriptor
|
: 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(
|
Logger::info(
|
||||||
"Selected program memory segment: \"" + this->selectedProgramSegmentDescriptor.name + "\" (\""
|
"Selected program memory segment: \"" + this->selectedProgramSegmentDescriptor.name + "\" (\""
|
||||||
@@ -390,4 +399,48 @@ namespace Targets::RiscV::Wch
|
|||||||
|
|
||||||
return transformedAddress;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,10 +73,23 @@ namespace Targets::RiscV::Wch
|
|||||||
*/
|
*/
|
||||||
const TargetMemorySegmentDescriptor& selectedProgramSegmentDescriptor;
|
const TargetMemorySegmentDescriptor& selectedProgramSegmentDescriptor;
|
||||||
|
|
||||||
|
const TargetPeripheralDescriptor flashPeripheralDescriptor;
|
||||||
|
const TargetRegisterDescriptor& flashKeyRegisterDescriptor;
|
||||||
|
const TargetRegisterDescriptor& flashBootKeyRegisterDescriptor;
|
||||||
|
const TargetRegisterDescriptor& flashStatusRegisterDescriptor;
|
||||||
|
|
||||||
|
const TargetBitFieldDescriptor& flashStatusBootLockFieldDescriptor;
|
||||||
|
const TargetBitFieldDescriptor& flashStatusBootModeFieldDescriptor;
|
||||||
|
|
||||||
const TargetMemorySegmentDescriptor& resolveAliasedMemorySegment();
|
const TargetMemorySegmentDescriptor& resolveAliasedMemorySegment();
|
||||||
TargetMemoryAddress transformMappedAddress(
|
TargetMemoryAddress transformMappedAddress(
|
||||||
TargetMemoryAddress address,
|
TargetMemoryAddress address,
|
||||||
const TargetMemorySegmentDescriptor& segmentDescriptor
|
const TargetMemorySegmentDescriptor& segmentDescriptor
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void unlockFlash();
|
||||||
|
void unlockBootModeBitField();
|
||||||
|
void enableBootMode();
|
||||||
|
void enableUserMode();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user