Tidied structure of all classes within the entire code base

Also some other small bits of tidying
This commit is contained in:
Nav
2021-10-06 21:12:31 +01:00
parent 1aef5bba79
commit 6edfb7376a
179 changed files with 3446 additions and 3493 deletions

View File

@@ -8,7 +8,6 @@
#include <limits>
#include "PadDescriptor.hpp"
#include "PhysicalInterface.hpp"
#include "src/Logger/Logger.hpp"
#include "src/Exceptions/InvalidConfig.hpp"
#include "src/Targets/TargetRegister.hpp"
@@ -25,110 +24,6 @@ using namespace Bloom::Targets::Microchip::Avr;
using namespace Bloom::Targets::Microchip::Avr::Avr8Bit;
using namespace Exceptions;
void Avr8::loadTargetDescriptionFile() {
this->targetDescriptionFile = TargetDescription::TargetDescriptionFile(
this->getId(),
(!this->name.empty()) ? std::optional(this->name) : std::nullopt
);
}
void Avr8::initFromTargetDescriptionFile() {
assert(this->targetDescriptionFile.has_value());
this->name = this->targetDescriptionFile->getTargetName();
this->family = this->targetDescriptionFile->getFamily();
this->targetParameters = this->targetDescriptionFile->getTargetParameters();
this->padDescriptorsByName = this->targetDescriptionFile->getPadDescriptorsMappedByName();
this->targetVariantsById = this->targetDescriptionFile->getVariantsMappedById();
if (!this->targetParameters->stackPointerRegisterLowAddress.has_value()) {
throw Exception("Failed to load sufficient AVR8 target paramters - missting stack pointer start address");
}
if (!this->targetParameters->statusRegisterStartAddress.has_value()) {
throw Exception("Failed to load sufficient AVR8 target parameters - missting status register start address");
}
this->loadTargetRegisterDescriptors();
}
void Avr8::loadTargetRegisterDescriptors() {
this->targetRegisterDescriptorsByType = this->targetDescriptionFile->getRegisterDescriptorsMappedByType();
/*
* All AVR8 targets possess 32 general purpose CPU registers. These are not described in the TDF, so we
* construct the descriptors for them here.
*/
auto gpRegisterStartAddress = this->targetParameters->gpRegisterStartAddress.value_or(0);
for (std::uint8_t i = 0; i <= 31; i++) {
auto generalPurposeRegisterDescriptor = TargetRegisterDescriptor();
generalPurposeRegisterDescriptor.startAddress = gpRegisterStartAddress + i;
generalPurposeRegisterDescriptor.size = 1;
generalPurposeRegisterDescriptor.type = TargetRegisterType::GENERAL_PURPOSE_REGISTER;
generalPurposeRegisterDescriptor.name = "r" + std::to_string(i);
generalPurposeRegisterDescriptor.groupName = "general purpose cpu";
generalPurposeRegisterDescriptor.readable = true;
generalPurposeRegisterDescriptor.writable = true;
this->targetRegisterDescriptorsByType[generalPurposeRegisterDescriptor.type].insert(
generalPurposeRegisterDescriptor
);
}
/*
* The SP and SREG registers are described in the TDF, so we could just use the descriptors extracted from the
* TDF. The problem with that is, sometimes the SP register consists of two bytes; an SPL and an SPH. These need
* to be combined into one register descriptor. This is why we just use what we already have in
* this->targetParameters.
*/
auto stackPointerRegisterDescriptor = TargetRegisterDescriptor();
stackPointerRegisterDescriptor.type = TargetRegisterType::STACK_POINTER;
stackPointerRegisterDescriptor.startAddress = this->targetParameters->stackPointerRegisterLowAddress.value();
stackPointerRegisterDescriptor.size = this->targetParameters->stackPointerRegisterSize.value();
stackPointerRegisterDescriptor.name = "SP";
stackPointerRegisterDescriptor.groupName = "CPU";
stackPointerRegisterDescriptor.description = "Stack Pointer Register";
stackPointerRegisterDescriptor.readable = true;
stackPointerRegisterDescriptor.writable = true;
auto statusRegisterDescriptor = TargetRegisterDescriptor();
statusRegisterDescriptor.type = TargetRegisterType::STATUS_REGISTER;
statusRegisterDescriptor.startAddress = this->targetParameters->statusRegisterStartAddress.value();
statusRegisterDescriptor.size = this->targetParameters->statusRegisterSize.value();
statusRegisterDescriptor.name = "SREG";
statusRegisterDescriptor.groupName = "CPU";
statusRegisterDescriptor.description = "Status Register";
statusRegisterDescriptor.readable = true;
statusRegisterDescriptor.writable = true;
auto programCounterRegisterDescriptor = TargetRegisterDescriptor();
programCounterRegisterDescriptor.type = TargetRegisterType::PROGRAM_COUNTER;
programCounterRegisterDescriptor.size = 4;
programCounterRegisterDescriptor.name = "PC";
programCounterRegisterDescriptor.groupName = "CPU";
programCounterRegisterDescriptor.description = "Program Counter";
programCounterRegisterDescriptor.readable = true;
programCounterRegisterDescriptor.writable = true;
this->targetRegisterDescriptorsByType[stackPointerRegisterDescriptor.type].insert(
stackPointerRegisterDescriptor
);
this->targetRegisterDescriptorsByType[statusRegisterDescriptor.type].insert(
statusRegisterDescriptor
);
this->targetRegisterDescriptorsByType[programCounterRegisterDescriptor.type].insert(
programCounterRegisterDescriptor
);
}
TargetSignature Avr8::getId() {
if (!this->id.has_value()) {
this->id = this->avr8Interface->getDeviceId();
}
return this->id.value();
}
void Avr8::preActivationConfigure(const TargetConfig& targetConfig) {
Target::preActivationConfigure(targetConfig);
@@ -188,6 +83,16 @@ void Avr8::activate() {
this->activated = true;
}
void Avr8::deactivate() {
try {
this->avr8Interface->deactivate();
this->activated = false;
} catch (const Exception& exception) {
Logger::error("Failed to deactivate AVR8 target - " + exception.getMessage());
}
}
std::unique_ptr<Targets::Target> Avr8::promote() {
std::unique_ptr<Targets::Target> promoted = nullptr;
@@ -218,16 +123,6 @@ std::unique_ptr<Targets::Target> Avr8::promote() {
return promoted;
}
void Avr8::deactivate() {
try {
this->avr8Interface->deactivate();
this->activated = false;
} catch (const Exception& exception) {
Logger::error("Failed to deactivate AVR8 target - " + exception.getMessage());
}
}
TargetDescriptor Avr8Bit::Avr8::getDescriptor() {
auto descriptor = TargetDescriptor();
descriptor.id = this->getHumanReadableId();
@@ -560,3 +455,107 @@ void Avr8::setPinState(const TargetPinDescriptor& pinDescriptor, const TargetPin
}
}
}
void Avr8::loadTargetDescriptionFile() {
this->targetDescriptionFile = TargetDescription::TargetDescriptionFile(
this->getId(),
(!this->name.empty()) ? std::optional(this->name) : std::nullopt
);
}
void Avr8::initFromTargetDescriptionFile() {
assert(this->targetDescriptionFile.has_value());
this->name = this->targetDescriptionFile->getTargetName();
this->family = this->targetDescriptionFile->getFamily();
this->targetParameters = this->targetDescriptionFile->getTargetParameters();
this->padDescriptorsByName = this->targetDescriptionFile->getPadDescriptorsMappedByName();
this->targetVariantsById = this->targetDescriptionFile->getVariantsMappedById();
if (!this->targetParameters->stackPointerRegisterLowAddress.has_value()) {
throw Exception("Failed to load sufficient AVR8 target paramters - missting stack pointer start address");
}
if (!this->targetParameters->statusRegisterStartAddress.has_value()) {
throw Exception("Failed to load sufficient AVR8 target parameters - missting status register start address");
}
this->loadTargetRegisterDescriptors();
}
void Avr8::loadTargetRegisterDescriptors() {
this->targetRegisterDescriptorsByType = this->targetDescriptionFile->getRegisterDescriptorsMappedByType();
/*
* All AVR8 targets possess 32 general purpose CPU registers. These are not described in the TDF, so we
* construct the descriptors for them here.
*/
auto gpRegisterStartAddress = this->targetParameters->gpRegisterStartAddress.value_or(0);
for (std::uint8_t i = 0; i <= 31; i++) {
auto generalPurposeRegisterDescriptor = TargetRegisterDescriptor();
generalPurposeRegisterDescriptor.startAddress = gpRegisterStartAddress + i;
generalPurposeRegisterDescriptor.size = 1;
generalPurposeRegisterDescriptor.type = TargetRegisterType::GENERAL_PURPOSE_REGISTER;
generalPurposeRegisterDescriptor.name = "r" + std::to_string(i);
generalPurposeRegisterDescriptor.groupName = "general purpose cpu";
generalPurposeRegisterDescriptor.readable = true;
generalPurposeRegisterDescriptor.writable = true;
this->targetRegisterDescriptorsByType[generalPurposeRegisterDescriptor.type].insert(
generalPurposeRegisterDescriptor
);
}
/*
* The SP and SREG registers are described in the TDF, so we could just use the descriptors extracted from the
* TDF. The problem with that is, sometimes the SP register consists of two bytes; an SPL and an SPH. These need
* to be combined into one register descriptor. This is why we just use what we already have in
* this->targetParameters.
*/
auto stackPointerRegisterDescriptor = TargetRegisterDescriptor();
stackPointerRegisterDescriptor.type = TargetRegisterType::STACK_POINTER;
stackPointerRegisterDescriptor.startAddress = this->targetParameters->stackPointerRegisterLowAddress.value();
stackPointerRegisterDescriptor.size = this->targetParameters->stackPointerRegisterSize.value();
stackPointerRegisterDescriptor.name = "SP";
stackPointerRegisterDescriptor.groupName = "CPU";
stackPointerRegisterDescriptor.description = "Stack Pointer Register";
stackPointerRegisterDescriptor.readable = true;
stackPointerRegisterDescriptor.writable = true;
auto statusRegisterDescriptor = TargetRegisterDescriptor();
statusRegisterDescriptor.type = TargetRegisterType::STATUS_REGISTER;
statusRegisterDescriptor.startAddress = this->targetParameters->statusRegisterStartAddress.value();
statusRegisterDescriptor.size = this->targetParameters->statusRegisterSize.value();
statusRegisterDescriptor.name = "SREG";
statusRegisterDescriptor.groupName = "CPU";
statusRegisterDescriptor.description = "Status Register";
statusRegisterDescriptor.readable = true;
statusRegisterDescriptor.writable = true;
auto programCounterRegisterDescriptor = TargetRegisterDescriptor();
programCounterRegisterDescriptor.type = TargetRegisterType::PROGRAM_COUNTER;
programCounterRegisterDescriptor.size = 4;
programCounterRegisterDescriptor.name = "PC";
programCounterRegisterDescriptor.groupName = "CPU";
programCounterRegisterDescriptor.description = "Program Counter";
programCounterRegisterDescriptor.readable = true;
programCounterRegisterDescriptor.writable = true;
this->targetRegisterDescriptorsByType[stackPointerRegisterDescriptor.type].insert(
stackPointerRegisterDescriptor
);
this->targetRegisterDescriptorsByType[statusRegisterDescriptor.type].insert(
statusRegisterDescriptor
);
this->targetRegisterDescriptorsByType[programCounterRegisterDescriptor.type].insert(
programCounterRegisterDescriptor
);
}
TargetSignature Avr8::getId() {
if (!this->id.has_value()) {
this->id = this->avr8Interface->getDeviceId();
}
return this->id.value();
}

View File

@@ -21,41 +21,6 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
{
class Avr8: public Target
{
protected:
DebugToolDrivers::TargetInterfaces::Microchip::Avr::Avr8::Avr8Interface* avr8Interface = nullptr;
std::string name;
std::optional<Family> family;
std::optional<TargetDescription::TargetDescriptionFile> targetDescriptionFile;
std::optional<TargetParameters> targetParameters;
std::map<std::string, PadDescriptor> padDescriptorsByName;
std::map<int, TargetVariant> targetVariantsById;
std::map<TargetRegisterType, TargetRegisterDescriptors> targetRegisterDescriptorsByType;
/**
* Resolves the appropriate TDF for the AVR8 target and populates this->targetDescriptionFile.
*/
void loadTargetDescriptionFile();
/**
* Initiates the AVR8 instance from data extracted from the TDF.
*/
void initFromTargetDescriptionFile();
/**
* Populates this->targetRegisterDescriptorsByType with registers extracted from the TDF, as well as general
* purpose and other CPU registers.
*/
void loadTargetRegisterDescriptors();
/**
* Extracts the ID from the target's memory.
*
* This function will cache the ID value and use the cached version for any subsequent calls.
*
* @return
*/
TargetSignature getId() override;
public:
explicit Avr8() = default;
Avr8(std::string name, const TargetSignature& signature): name(std::move(name)) {
@@ -149,5 +114,40 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
const TargetPinDescriptor& pinDescriptor,
const TargetPinState& state
) override;
protected:
DebugToolDrivers::TargetInterfaces::Microchip::Avr::Avr8::Avr8Interface* avr8Interface = nullptr;
std::string name;
std::optional<Family> family;
std::optional<TargetDescription::TargetDescriptionFile> targetDescriptionFile;
std::optional<TargetParameters> targetParameters;
std::map<std::string, PadDescriptor> padDescriptorsByName;
std::map<int, TargetVariant> targetVariantsById;
std::map<TargetRegisterType, TargetRegisterDescriptors> targetRegisterDescriptorsByType;
/**
* Resolves the appropriate TDF for the AVR8 target and populates this->targetDescriptionFile.
*/
void loadTargetDescriptionFile();
/**
* Initiates the AVR8 instance from data extracted from the TDF.
*/
void initFromTargetDescriptionFile();
/**
* Populates this->targetRegisterDescriptorsByType with registers extracted from the TDF, as well as general
* purpose and other CPU registers.
*/
void loadTargetRegisterDescriptors();
/**
* Extracts the ID from the target's memory.
*
* This function will cache the ID value and use the cached version for any subsequent calls.
*
* @return
*/
TargetSignature getId() override;
};
}

View File

@@ -6,8 +6,6 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
{
class Mega: public Avr8
{
protected:
public:
explicit Mega(const Avr8& avr8): Avr8(avr8) {};

View File

@@ -4,9 +4,10 @@
#include <QJsonArray>
#include "src/Helpers/Paths.hpp"
#include "src/Logger/Logger.hpp"
#include "src/Exceptions/Exception.hpp"
#include "src/Targets/TargetDescription/Exceptions/TargetDescriptionParsingFailureException.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription;
using namespace Bloom::Targets::Microchip::Avr::Avr8Bit;
@@ -1127,36 +1128,3 @@ void TargetDescriptionFile::loadUpdiTargetParameters(TargetParameters& targetPar
targetParameters.lockbitsSegmentStartAddress = lockbitsMemorySegment->startAddress;
}
}
std::uint32_t TargetDescriptionFile::getRegisterAddressOffsetByModuleName(const std::string& moduleName) const {
if (this->peripheralModulesMappedByName.contains(moduleName)) {
auto& peripheralModule = this->peripheralModulesMappedByName.at(moduleName);
if (peripheralModule.instancesMappedByName.contains(moduleName)) {
auto& moduleInstance = peripheralModule.instancesMappedByName.at(moduleName);
if (moduleInstance.registerGroupsMappedByName.contains(moduleName)) {
auto& registerGroup = moduleInstance.registerGroupsMappedByName.at(moduleName);
if (!registerGroup.moduleName.has_value() || registerGroup.moduleName.value() == moduleName) {
return registerGroup.offset.value_or(0);
}
}
/*
* If we get here, that means we couldn't find the right register group by module name. This will happen
* if the register group name doesn't match the module name attribute ("name-in-module") against the
* register group node, in the TDF.
*
* As a final attempt, we'll brute force search all register groups in the module instance.
*/
for (const auto& [registerGroupName, registerGroup] : moduleInstance.registerGroupsMappedByName) {
if (registerGroup.moduleName.has_value() && registerGroup.moduleName.value() == moduleName) {
return registerGroup.offset.value_or(0);
}
}
}
}
return 0;
}

View File

@@ -27,6 +27,87 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
*/
class TargetDescriptionFile: public Targets::TargetDescription::TargetDescriptionFile
{
public:
/**
* Will resolve the target description file using the target description JSON mapping and a given target signature.
*
* @param targetSignatureHex
* @param targetName
*/
TargetDescriptionFile(const TargetSignature& targetSignature, std::optional<std::string> targetName);
/**
* Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among
* other things.
*
* @param xml
*/
void init(const QDomDocument& xml) override;
/**
* Loads the AVR8 target description JSON mapping file.
*
* @return
*/
static QJsonObject getTargetDescriptionMapping();
/**
* Extracts the AVR8 target signature from the TDF.
*
* @return
*/
[[nodiscard]] TargetSignature getTargetSignature() const;
/**
* Extracts the AVR8 target family from the TDF.
*
* @return
*/
[[nodiscard]] Family getFamily() const;
/**
* Constructs an instance of TargetParameters, for the AVR8 target, with data from the TDF.
*
* @return
*/
[[nodiscard]] TargetParameters getTargetParameters() const;
/**
* Returns a set of all supported physical interfaces for debugging.
*
* @return
*/
[[nodiscard]] const auto& getSupportedDebugPhysicalInterfaces() const {
return this->supportedDebugPhysicalInterfaces;
}
/**
* Returns a mapping of all pad descriptors extracted from TDF, mapped by name.
*
* @return
*/
[[nodiscard]] const auto& getPadDescriptorsMappedByName() const {
return this->padDescriptorsByName;
}
/**
* Returns a mapping of all target variants extracted from the TDF, mapped by ID.
*
* @return
*/
[[nodiscard]] const auto& getVariantsMappedById() const {
return this->targetVariantsById;
}
/**
* Returns a mapping of all target register descriptors extracted from the TDF, by type.
*
* @return
*/
[[nodiscard]] const auto& getRegisterDescriptorsMappedByType() const {
return this->targetRegisterDescriptorsByType;
}
private:
/**`
* AVR8 target description files include the target family name. This method returns a mapping of part
@@ -124,94 +205,5 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
* @param targetParameters
*/
virtual void loadUpdiTargetParameters(TargetParameters& targetParameters) const;
/**
* Extracts the register address offset, for registers from a particular module.
*
* @param moduleName
* @return
*/
[[nodiscard]] virtual std::uint32_t getRegisterAddressOffsetByModuleName(const std::string& moduleName) const;
public:
/**
* Will resolve the target description file using the target description JSON mapping and a given target signature.
*
* @param targetSignatureHex
* @param targetName
*/
TargetDescriptionFile(const TargetSignature& targetSignature, std::optional<std::string> targetName);
/**
* Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among
* other things.
*
* @param xml
*/
void init(const QDomDocument& xml) override;
/**
* Loads the AVR8 target description JSON mapping file.
*
* @return
*/
static QJsonObject getTargetDescriptionMapping();
/**
* Extracts the AVR8 target signature from the TDF.
*
* @return
*/
[[nodiscard]] TargetSignature getTargetSignature() const;
/**
* Extracts the AVR8 target family from the TDF.
*
* @return
*/
[[nodiscard]] Family getFamily() const;
/**
* Constructs an instance of TargetParameters, for the AVR8 target, with data from the TDF.
*
* @return
*/
[[nodiscard]] TargetParameters getTargetParameters() const;
/**
* Returns a set of all supported physical interfaces for debugging.
*
* @return
*/
[[nodiscard]] const auto& getSupportedDebugPhysicalInterfaces() const {
return this->supportedDebugPhysicalInterfaces;
}
/**
* Returns a mapping of all pad descriptors extracted from TDF, mapped by name.
*
* @return
*/
[[nodiscard]] const auto& getPadDescriptorsMappedByName() const {
return this->padDescriptorsByName;
}
/**
* Returns a mapping of all target variants extracted from the TDF, mapped by ID.
*
* @return
*/
[[nodiscard]] const auto& getVariantsMappedById() const {
return this->targetVariantsById;
}
/**
* Returns a mapping of all target register descriptors extracted from the TDF, by type.
*
* @return
*/
[[nodiscard]] const auto& getRegisterDescriptorsMappedByType() const {
return this->targetRegisterDescriptorsByType;
}
};
}