Moved AVR8 specific TDF parsing to AVR8 derivation of TDF class.

Also some other small tweaks to TDF function qualifiers
Also improved some comments
This commit is contained in:
Nav
2021-06-06 19:14:36 +01:00
parent 1aab927ea2
commit 9b1f250625
4 changed files with 458 additions and 397 deletions

View File

@@ -12,6 +12,11 @@ using namespace Bloom::Targets::Microchip::Avr::Avr8Bit;
using namespace Bloom::Targets::Microchip::Avr; using namespace Bloom::Targets::Microchip::Avr;
using namespace Bloom::Exceptions; using namespace Bloom::Exceptions;
using Bloom::Targets::TargetDescription::RegisterGroup;
using Bloom::Targets::TargetDescription::MemorySegment;
using Bloom::Targets::TargetDescription::MemorySegmentType;
using Bloom::Targets::TargetDescription::Register;
TargetDescriptionFile::TargetDescriptionFile( TargetDescriptionFile::TargetDescriptionFile(
const TargetSignature& targetSignature, const TargetSignature& targetSignature,
std::optional<std::string> targetName std::optional<std::string> targetName
@@ -147,3 +152,357 @@ Family TargetDescriptionFile::getFamily() const {
return familyNameToEnums.at(familyName); return familyNameToEnums.at(familyName);
} }
std::optional<MemorySegment> TargetDescriptionFile::getFlashMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
auto programAddressSpaceIt = addressMapping.find("prog");
// Flash memory attributes are typically found in memory segments within the program address space.
if (programAddressSpaceIt != addressMapping.end()) {
auto& programAddressSpace = programAddressSpaceIt->second;
auto& programMemorySegments = programAddressSpace.memorySegmentsByTypeAndName;
if (programMemorySegments.find(MemorySegmentType::FLASH) != programMemorySegments.end()) {
auto& flashMemorySegments = programMemorySegments.find(MemorySegmentType::FLASH)->second;
/*
* In AVR8 TDFs, flash memory segments are typically named "APP_SECTION", "PROGMEM" or "FLASH".
*/
auto flashSegmentIt = flashMemorySegments.find("app_section") != flashMemorySegments.end() ?
flashMemorySegments.find("app_section")
: flashMemorySegments.find("progmem") != flashMemorySegments.end()
? flashMemorySegments.find("progmem") : flashMemorySegments.find("flash");
if (flashSegmentIt != flashMemorySegments.end()) {
return flashSegmentIt->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getRamMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
// Internal RAM &register attributes are usually found in the data address space
auto dataAddressSpaceIt = addressMapping.find("data");
if (dataAddressSpaceIt != addressMapping.end()) {
auto& dataAddressSpace = dataAddressSpaceIt->second;
auto& dataMemorySegments = dataAddressSpace.memorySegmentsByTypeAndName;
if (dataMemorySegments.find(MemorySegmentType::RAM) != dataMemorySegments.end()) {
auto& ramMemorySegments = dataMemorySegments.find(MemorySegmentType::RAM)->second;
auto ramMemorySegmentIt = ramMemorySegments.begin();
if (ramMemorySegmentIt != ramMemorySegments.end()) {
return ramMemorySegmentIt->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getRegisterMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
// Internal RAM &register attributes are usually found in the data address space
auto dataAddressSpaceIt = addressMapping.find("data");
if (dataAddressSpaceIt != addressMapping.end()) {
auto& dataAddressSpace = dataAddressSpaceIt->second;
auto& dataMemorySegments = dataAddressSpace.memorySegmentsByTypeAndName;
if (dataMemorySegments.find(MemorySegmentType::REGISTERS) != dataMemorySegments.end()) {
auto& registerMemorySegments = dataMemorySegments.find(MemorySegmentType::REGISTERS)->second;
auto registerMemorySegmentIt = registerMemorySegments.begin();
if (registerMemorySegmentIt != registerMemorySegments.end()) {
return registerMemorySegmentIt->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getEepromMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
if (addressMapping.contains("eeprom")) {
auto& eepromAddressSpace = addressMapping.at("eeprom");
auto& eepromAddressSpaceSegments = eepromAddressSpace.memorySegmentsByTypeAndName;
if (eepromAddressSpaceSegments.contains(MemorySegmentType::EEPROM)) {
return eepromAddressSpaceSegments.at(MemorySegmentType::EEPROM).begin()->second;
}
} else {
// The EEPROM memory segment may be part of the data address space
if (addressMapping.contains("data")) {
auto dataAddressSpace = addressMapping.at("data");
if (dataAddressSpace.memorySegmentsByTypeAndName.contains(MemorySegmentType::EEPROM)) {
return dataAddressSpace.memorySegmentsByTypeAndName.at(MemorySegmentType::EEPROM).begin()->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getFirstBootSectionMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
auto programAddressSpaceIt = addressMapping.find("prog");
if (programAddressSpaceIt != addressMapping.end()) {
auto& programAddressSpace = programAddressSpaceIt->second;
auto& programMemorySegments = programAddressSpace.memorySegmentsByTypeAndName;
if (programMemorySegments.find(MemorySegmentType::FLASH) != programMemorySegments.end()) {
auto& flashMemorySegments = programMemorySegments.find(MemorySegmentType::FLASH)->second;
if (flashMemorySegments.contains("boot_section_1")) {
return flashMemorySegments.at("boot_section_1");
} else if (flashMemorySegments.contains("boot_section")) {
return flashMemorySegments.at("boot_section");
}
}
}
return std::nullopt;
}
std::optional<RegisterGroup> TargetDescriptionFile::getCpuRegisterGroup() const {
auto& modulesByName = this->getModulesMappedByName();
if (modulesByName.find("cpu") != modulesByName.end()) {
auto cpuModule = modulesByName.find("cpu")->second;
auto cpuRegisterGroupIt = cpuModule.registerGroupsMappedByName.find("cpu");
if (cpuRegisterGroupIt != cpuModule.registerGroupsMappedByName.end()) {
return cpuRegisterGroupIt->second;
}
}
return std::nullopt;
}
std::optional<RegisterGroup> TargetDescriptionFile::getBootLoadRegisterGroup() const {
auto& modulesByName = this->getModulesMappedByName();
if (modulesByName.contains("boot_load")) {
auto& bootLoadModule = modulesByName.at("boot_load");
auto bootLoadRegisterGroupIt = bootLoadModule.registerGroupsMappedByName.find("boot_load");
if (bootLoadRegisterGroupIt != bootLoadModule.registerGroupsMappedByName.end()) {
return bootLoadRegisterGroupIt->second;
}
}
return std::nullopt;
}
std::optional<RegisterGroup> TargetDescriptionFile::getEepromRegisterGroup() const {
auto& modulesByName = this->getModulesMappedByName();
if (modulesByName.find("eeprom") != modulesByName.end()) {
auto eepromModule = modulesByName.find("eeprom")->second;
auto eepromRegisterGroupIt = eepromModule.registerGroupsMappedByName.find("eeprom");
if (eepromRegisterGroupIt != eepromModule.registerGroupsMappedByName.end()) {
return eepromRegisterGroupIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStatusRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto statusRegisterIt = cpuRegisterGroup->registersMappedByName.find("sreg");
if (statusRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return statusRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStackPointerRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto stackPointerRegisterIt = cpuRegisterGroup->registersMappedByName.find("sp");
if (stackPointerRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return stackPointerRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStackPointerHighRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto stackPointerHighRegisterIt = cpuRegisterGroup->registersMappedByName.find("sph");
if (stackPointerHighRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return stackPointerHighRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStackPointerLowRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto stackPointerLowRegisterIt = cpuRegisterGroup->registersMappedByName.find("spl");
if (stackPointerLowRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return stackPointerLowRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getOscillatorCalibrationRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto& cpuRegisters = cpuRegisterGroup->registersMappedByName;
if (cpuRegisters.contains("osccal")) {
return cpuRegisters.at("osccal");
} else if (cpuRegisters.contains("osccal0")) {
return cpuRegisters.at("osccal0");
} else if (cpuRegisters.contains("osccal1")) {
return cpuRegisters.at("osccal1");
} else if (cpuRegisters.contains("fosccal")) {
return cpuRegisters.at("fosccal");
} else if (cpuRegisters.contains("sosccala")) {
return cpuRegisters.at("sosccala");
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getSpmcsRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value() && cpuRegisterGroup->registersMappedByName.contains("spmcsr")) {
return cpuRegisterGroup->registersMappedByName.at("spmcsr");
} else {
auto bootLoadRegisterGroup = this->getBootLoadRegisterGroup();
if (bootLoadRegisterGroup.has_value() && bootLoadRegisterGroup->registersMappedByName.contains("spmcsr")) {
return bootLoadRegisterGroup->registersMappedByName.at("spmcsr");
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getSpmcRegister() const {
auto bootLoadRegisterGroup = this->getBootLoadRegisterGroup();
if (bootLoadRegisterGroup.has_value() && bootLoadRegisterGroup->registersMappedByName.contains("spmcr")) {
return bootLoadRegisterGroup->registersMappedByName.at("spmcr");
} else {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value() && cpuRegisterGroup->registersMappedByName.contains("spmcr")) {
return cpuRegisterGroup->registersMappedByName.at("spmcr");
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromAddressRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eear");
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromAddressRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromAddressLowRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eearl");
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromAddressRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromAddressHighRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eearh");
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromAddressRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromDataRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromDataRegisterIt = eepromRegisterGroup->registersMappedByName.find("eedr");
if (eepromDataRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromDataRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromControlRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromControlRegisterIt = eepromRegisterGroup->registersMappedByName.find("eecr");
if (eepromControlRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromControlRegisterIt->second;
}
}
return std::nullopt;
}

View File

@@ -71,5 +71,26 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
* @return * @return
*/ */
Family getFamily() const; Family getFamily() const;
std::optional<Targets::TargetDescription::MemorySegment> getFlashMemorySegment() const;
std::optional<Targets::TargetDescription::MemorySegment> getRamMemorySegment() const;
std::optional<Targets::TargetDescription::MemorySegment> getRegisterMemorySegment() const;
std::optional<Targets::TargetDescription::MemorySegment> getEepromMemorySegment() const;
std::optional<Targets::TargetDescription::MemorySegment> getFirstBootSectionMemorySegment() const;
std::optional<Targets::TargetDescription::RegisterGroup> getCpuRegisterGroup() const;
std::optional<Targets::TargetDescription::RegisterGroup> getBootLoadRegisterGroup() const;
std::optional<Targets::TargetDescription::RegisterGroup> getEepromRegisterGroup() const;
std::optional<Targets::TargetDescription::Register> getStatusRegister() const;
std::optional<Targets::TargetDescription::Register> getStackPointerRegister() const;
std::optional<Targets::TargetDescription::Register> getStackPointerHighRegister() const;
std::optional<Targets::TargetDescription::Register> getStackPointerLowRegister() const;
std::optional<Targets::TargetDescription::Register> getOscillatorCalibrationRegister() const;
std::optional<Targets::TargetDescription::Register> getSpmcsRegister() const;
std::optional<Targets::TargetDescription::Register> getSpmcRegister() const;
std::optional<Targets::TargetDescription::Register> getEepromAddressRegister() const;
std::optional<Targets::TargetDescription::Register> getEepromAddressLowRegister() const;
std::optional<Targets::TargetDescription::Register> getEepromAddressHighRegister() const;
std::optional<Targets::TargetDescription::Register> getEepromDataRegister() const;
std::optional<Targets::TargetDescription::Register> getEepromControlRegister() const;
}; };
} }

View File

@@ -37,7 +37,7 @@ std::string TargetDescriptionFile::getTargetName() const {
return this->deviceElement.attributes().namedItem("name").nodeValue().toStdString(); return this->deviceElement.attributes().namedItem("name").nodeValue().toStdString();
} }
AddressSpace TargetDescriptionFile::generateAddressSpaceFromXml(const QDomElement& xmlElement) const { AddressSpace TargetDescriptionFile::generateAddressSpaceFromXml(const QDomElement& xmlElement) {
if ( if (
!xmlElement.hasAttribute("id") !xmlElement.hasAttribute("id")
|| !xmlElement.hasAttribute("name") || !xmlElement.hasAttribute("name")
@@ -73,7 +73,9 @@ AddressSpace TargetDescriptionFile::generateAddressSpaceFromXml(const QDomElemen
auto& memorySegments = addressSpace.memorySegmentsByTypeAndName; auto& memorySegments = addressSpace.memorySegmentsByTypeAndName;
for (int segmentIndex = 0; segmentIndex < segmentNodes.count(); segmentIndex++) { for (int segmentIndex = 0; segmentIndex < segmentNodes.count(); segmentIndex++) {
try { try {
auto segment = this->generateMemorySegmentFromXml(segmentNodes.item(segmentIndex).toElement()); auto segment = TargetDescriptionFile::generateMemorySegmentFromXml(
segmentNodes.item(segmentIndex).toElement()
);
if (memorySegments.find(segment.type) == memorySegments.end()) { if (memorySegments.find(segment.type) == memorySegments.end()) {
memorySegments.insert( memorySegments.insert(
@@ -94,7 +96,7 @@ AddressSpace TargetDescriptionFile::generateAddressSpaceFromXml(const QDomElemen
return addressSpace; return addressSpace;
} }
MemorySegment TargetDescriptionFile::generateMemorySegmentFromXml(const QDomElement& xmlElement) const { MemorySegment TargetDescriptionFile::generateMemorySegmentFromXml(const QDomElement& xmlElement) {
if ( if (
!xmlElement.hasAttribute("type") !xmlElement.hasAttribute("type")
|| !xmlElement.hasAttribute("name") || !xmlElement.hasAttribute("name")
@@ -144,7 +146,7 @@ MemorySegment TargetDescriptionFile::generateMemorySegmentFromXml(const QDomElem
return segment; return segment;
} }
RegisterGroup TargetDescriptionFile::generateRegisterGroupFromXml(const QDomElement& xmlElement) const { RegisterGroup TargetDescriptionFile::generateRegisterGroupFromXml(const QDomElement& xmlElement) {
if (!xmlElement.hasAttribute("name")) { if (!xmlElement.hasAttribute("name")) {
throw Exception("Missing register group name attribute"); throw Exception("Missing register group name attribute");
} }
@@ -164,7 +166,9 @@ RegisterGroup TargetDescriptionFile::generateRegisterGroupFromXml(const QDomElem
auto registerNodes = xmlElement.elementsByTagName("register"); auto registerNodes = xmlElement.elementsByTagName("register");
for (int registerIndex = 0; registerIndex < registerNodes.count(); registerIndex++) { for (int registerIndex = 0; registerIndex < registerNodes.count(); registerIndex++) {
try { try {
auto reg = this->generateRegisterFromXml(registerNodes.item(registerIndex).toElement()); auto reg = TargetDescriptionFile::generateRegisterFromXml(
registerNodes.item(registerIndex).toElement()
);
registers.insert(std::pair(reg.name, reg)); registers.insert(std::pair(reg.name, reg));
} catch (const Exception& exception) { } catch (const Exception& exception) {
@@ -176,7 +180,7 @@ RegisterGroup TargetDescriptionFile::generateRegisterGroupFromXml(const QDomElem
return registerGroup; return registerGroup;
} }
Register TargetDescriptionFile::generateRegisterFromXml(const QDomElement& xmlElement) const { Register TargetDescriptionFile::generateRegisterFromXml(const QDomElement& xmlElement) {
if ( if (
!xmlElement.hasAttribute("name") !xmlElement.hasAttribute("name")
|| !xmlElement.hasAttribute("offset") || !xmlElement.hasAttribute("offset")
@@ -255,7 +259,9 @@ const std::map<std::string, Module>& TargetDescriptionFile::getModulesMappedByNa
auto registerGroupNodes = moduleElement.elementsByTagName("register-group"); auto registerGroupNodes = moduleElement.elementsByTagName("register-group");
for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) { for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) {
auto registerGroup = this->generateRegisterGroupFromXml(registerGroupNodes.item(registerGroupIndex).toElement()); auto registerGroup = TargetDescriptionFile::generateRegisterGroupFromXml(
registerGroupNodes.item(registerGroupIndex).toElement()
);
module.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup)); module.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup));
} }
@@ -283,7 +289,9 @@ const std::map<std::string, Module>& TargetDescriptionFile::getPeripheralModules
auto registerGroupNodes = moduleElement.elementsByTagName("register-group"); auto registerGroupNodes = moduleElement.elementsByTagName("register-group");
for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) { for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) {
auto registerGroup = this->generateRegisterGroupFromXml(registerGroupNodes.item(registerGroupIndex).toElement()); auto registerGroup = TargetDescriptionFile::generateRegisterGroupFromXml(
registerGroupNodes.item(registerGroupIndex).toElement()
);
module.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup)); module.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup));
} }
@@ -296,7 +304,9 @@ const std::map<std::string, Module>& TargetDescriptionFile::getPeripheralModules
auto registerGroupNodes = instanceXml.elementsByTagName("register-group"); auto registerGroupNodes = instanceXml.elementsByTagName("register-group");
for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) { for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) {
auto registerGroup = this->generateRegisterGroupFromXml(registerGroupNodes.item(registerGroupIndex).toElement()); auto registerGroup = TargetDescriptionFile::generateRegisterGroupFromXml(
registerGroupNodes.item(registerGroupIndex).toElement()
);
instance.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup)); instance.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup));
} }
@@ -345,7 +355,9 @@ std::map<std::string, AddressSpace> TargetDescriptionFile::getAddressSpacesMappe
for (int addressSpaceIndex = 0; addressSpaceIndex < addressSpaceNodes.count(); addressSpaceIndex++) { for (int addressSpaceIndex = 0; addressSpaceIndex < addressSpaceNodes.count(); addressSpaceIndex++) {
try { try {
auto addressSpace = this->generateAddressSpaceFromXml(addressSpaceNodes.item(addressSpaceIndex).toElement()); auto addressSpace = TargetDescriptionFile::generateAddressSpaceFromXml(
addressSpaceNodes.item(addressSpaceIndex).toElement()
);
output.insert(std::pair(addressSpace.id, addressSpace)); output.insert(std::pair(addressSpace.id, addressSpace));
} catch (const Exception& exception) { } catch (const Exception& exception) {
@@ -356,360 +368,6 @@ std::map<std::string, AddressSpace> TargetDescriptionFile::getAddressSpacesMappe
return output; return output;
} }
std::optional<MemorySegment> TargetDescriptionFile::getFlashMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
auto programAddressSpaceIt = addressMapping.find("prog");
// Flash memory attributes are typically found in memory segments within the program address space.
if (programAddressSpaceIt != addressMapping.end()) {
auto& programAddressSpace = programAddressSpaceIt->second;
auto& programMemorySegments = programAddressSpace.memorySegmentsByTypeAndName;
if (programMemorySegments.find(MemorySegmentType::FLASH) != programMemorySegments.end()) {
auto& flashMemorySegments = programMemorySegments.find(MemorySegmentType::FLASH)->second;
/*
* In AVR8 TDFs, flash memory segments are typically named "APP_SECTION", "PROGMEM" or "FLASH".
*/
auto flashSegmentIt = flashMemorySegments.find("app_section") != flashMemorySegments.end() ?
flashMemorySegments.find("app_section")
: flashMemorySegments.find("progmem") != flashMemorySegments.end()
? flashMemorySegments.find("progmem") : flashMemorySegments.find("flash");
if (flashSegmentIt != flashMemorySegments.end()) {
return flashSegmentIt->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getRamMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
// Internal RAM &register attributes are usually found in the data address space
auto dataAddressSpaceIt = addressMapping.find("data");
if (dataAddressSpaceIt != addressMapping.end()) {
auto& dataAddressSpace = dataAddressSpaceIt->second;
auto& dataMemorySegments = dataAddressSpace.memorySegmentsByTypeAndName;
if (dataMemorySegments.find(MemorySegmentType::RAM) != dataMemorySegments.end()) {
auto& ramMemorySegments = dataMemorySegments.find(MemorySegmentType::RAM)->second;
auto ramMemorySegmentIt = ramMemorySegments.begin();
if (ramMemorySegmentIt != ramMemorySegments.end()) {
return ramMemorySegmentIt->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getRegisterMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
// Internal RAM &register attributes are usually found in the data address space
auto dataAddressSpaceIt = addressMapping.find("data");
if (dataAddressSpaceIt != addressMapping.end()) {
auto& dataAddressSpace = dataAddressSpaceIt->second;
auto& dataMemorySegments = dataAddressSpace.memorySegmentsByTypeAndName;
if (dataMemorySegments.find(MemorySegmentType::REGISTERS) != dataMemorySegments.end()) {
auto& registerMemorySegments = dataMemorySegments.find(MemorySegmentType::REGISTERS)->second;
auto registerMemorySegmentIt = registerMemorySegments.begin();
if (registerMemorySegmentIt != registerMemorySegments.end()) {
return registerMemorySegmentIt->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getEepromMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
if (addressMapping.contains("eeprom")) {
auto& eepromAddressSpace = addressMapping.at("eeprom");
auto& eepromAddressSpaceSegments = eepromAddressSpace.memorySegmentsByTypeAndName;
if (eepromAddressSpaceSegments.contains(MemorySegmentType::EEPROM)) {
return eepromAddressSpaceSegments.at(MemorySegmentType::EEPROM).begin()->second;
}
} else {
// The EEPROM memory segment may be part of the data address space
if (addressMapping.contains("data")) {
auto dataAddressSpace = addressMapping.at("data");
if (dataAddressSpace.memorySegmentsByTypeAndName.contains(MemorySegmentType::EEPROM)) {
return dataAddressSpace.memorySegmentsByTypeAndName.at(MemorySegmentType::EEPROM).begin()->second;
}
}
}
return std::nullopt;
}
std::optional<MemorySegment> TargetDescriptionFile::getFirstBootSectionMemorySegment() const {
auto addressMapping = this->getAddressSpacesMappedById();
auto programAddressSpaceIt = addressMapping.find("prog");
if (programAddressSpaceIt != addressMapping.end()) {
auto& programAddressSpace = programAddressSpaceIt->second;
auto& programMemorySegments = programAddressSpace.memorySegmentsByTypeAndName;
if (programMemorySegments.find(MemorySegmentType::FLASH) != programMemorySegments.end()) {
auto& flashMemorySegments = programMemorySegments.find(MemorySegmentType::FLASH)->second;
if (flashMemorySegments.contains("boot_section_1")) {
return flashMemorySegments.at("boot_section_1");
} else if (flashMemorySegments.contains("boot_section")) {
return flashMemorySegments.at("boot_section");
}
}
}
return std::nullopt;
}
std::optional<RegisterGroup> TargetDescriptionFile::getCpuRegisterGroup() const {
auto& modulesByName = this->getModulesMappedByName();
if (modulesByName.find("cpu") != modulesByName.end()) {
auto cpuModule = modulesByName.find("cpu")->second;
auto cpuRegisterGroupIt = cpuModule.registerGroupsMappedByName.find("cpu");
if (cpuRegisterGroupIt != cpuModule.registerGroupsMappedByName.end()) {
return cpuRegisterGroupIt->second;
}
}
return std::nullopt;
}
std::optional<RegisterGroup> TargetDescriptionFile::getBootLoadRegisterGroup() const {
auto& modulesByName = this->getModulesMappedByName();
if (modulesByName.contains("boot_load")) {
auto& bootLoadModule = modulesByName.at("boot_load");
auto bootLoadRegisterGroupIt = bootLoadModule.registerGroupsMappedByName.find("boot_load");
if (bootLoadRegisterGroupIt != bootLoadModule.registerGroupsMappedByName.end()) {
return bootLoadRegisterGroupIt->second;
}
}
return std::nullopt;
}
std::optional<RegisterGroup> TargetDescriptionFile::getEepromRegisterGroup() const {
auto& modulesByName = this->getModulesMappedByName();
if (modulesByName.find("eeprom") != modulesByName.end()) {
auto eepromModule = modulesByName.find("eeprom")->second;
auto eepromRegisterGroupIt = eepromModule.registerGroupsMappedByName.find("eeprom");
if (eepromRegisterGroupIt != eepromModule.registerGroupsMappedByName.end()) {
return eepromRegisterGroupIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStatusRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto statusRegisterIt = cpuRegisterGroup->registersMappedByName.find("sreg");
if (statusRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return statusRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStackPointerRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto stackPointerRegisterIt = cpuRegisterGroup->registersMappedByName.find("sp");
if (stackPointerRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return stackPointerRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStackPointerHighRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto stackPointerHighRegisterIt = cpuRegisterGroup->registersMappedByName.find("sph");
if (stackPointerHighRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return stackPointerHighRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getStackPointerLowRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto stackPointerLowRegisterIt = cpuRegisterGroup->registersMappedByName.find("spl");
if (stackPointerLowRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
return stackPointerLowRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getOscillatorCalibrationRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value()) {
auto& cpuRegisters = cpuRegisterGroup->registersMappedByName;
if (cpuRegisters.contains("osccal")) {
return cpuRegisters.at("osccal");
} else if (cpuRegisters.contains("osccal0")) {
return cpuRegisters.at("osccal0");
} else if (cpuRegisters.contains("osccal1")) {
return cpuRegisters.at("osccal1");
} else if (cpuRegisters.contains("fosccal")) {
return cpuRegisters.at("fosccal");
} else if (cpuRegisters.contains("sosccala")) {
return cpuRegisters.at("sosccala");
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getSpmcsRegister() const {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value() && cpuRegisterGroup->registersMappedByName.contains("spmcsr")) {
return cpuRegisterGroup->registersMappedByName.at("spmcsr");
} else {
auto bootLoadRegisterGroup = this->getBootLoadRegisterGroup();
if (bootLoadRegisterGroup.has_value() && bootLoadRegisterGroup->registersMappedByName.contains("spmcsr")) {
return bootLoadRegisterGroup->registersMappedByName.at("spmcsr");
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getSpmcRegister() const {
auto bootLoadRegisterGroup = this->getBootLoadRegisterGroup();
if (bootLoadRegisterGroup.has_value() && bootLoadRegisterGroup->registersMappedByName.contains("spmcr")) {
return bootLoadRegisterGroup->registersMappedByName.at("spmcr");
} else {
auto cpuRegisterGroup = this->getCpuRegisterGroup();
if (cpuRegisterGroup.has_value() && cpuRegisterGroup->registersMappedByName.contains("spmcr")) {
return cpuRegisterGroup->registersMappedByName.at("spmcr");
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromAddressRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eear");
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromAddressRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromAddressLowRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eearl");
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromAddressRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromAddressHighRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eearh");
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromAddressRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromDataRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromDataRegisterIt = eepromRegisterGroup->registersMappedByName.find("eedr");
if (eepromDataRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromDataRegisterIt->second;
}
}
return std::nullopt;
}
std::optional<Register> TargetDescriptionFile::getEepromControlRegister() const {
auto eepromRegisterGroup = this->getEepromRegisterGroup();
if (eepromRegisterGroup.has_value()) {
auto eepromControlRegisterIt = eepromRegisterGroup->registersMappedByName.find("eecr");
if (eepromControlRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
return eepromControlRegisterIt->second;
}
}
return std::nullopt;
}
std::vector<Variant> TargetDescriptionFile::getVariants() const { std::vector<Variant> TargetDescriptionFile::getVariants() const {
std::vector<Variant> output; std::vector<Variant> output;

View File

@@ -10,8 +10,6 @@
#include "Module.hpp" #include "Module.hpp"
#include "Variant.hpp" #include "Variant.hpp"
#include "Pinout.hpp" #include "Pinout.hpp"
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
#include "src/Targets/Microchip/AVR/AVR8/Family.hpp"
namespace Bloom::Targets::TargetDescription namespace Bloom::Targets::TargetDescription
{ {
@@ -48,25 +46,36 @@ namespace Bloom::Targets::TargetDescription
mutable std::optional<std::map<std::string, Pinout>> cachedPinoutByNameMapping; mutable std::optional<std::map<std::string, Pinout>> cachedPinoutByNameMapping;
/** /**
* Constructs an AddressSpace object from an XML element (in the form of a QDomElement), taken from a target * Constructs an AddressSpace object from an XML element.
* description file.
* *
* @param xmlElement * @param xmlElement
* @return * @return
*/ */
AddressSpace generateAddressSpaceFromXml(const QDomElement& xmlElement) const; static AddressSpace generateAddressSpaceFromXml(const QDomElement& xmlElement);
/** /**
* Constructs a MemorySegment from an XML element (in the form of a QDomElement) taken from a target * Constructs a MemorySegment object from an XML element.
* description file.
* *
* @param xmlElement * @param xmlElement
* @return * @return
*/ */
MemorySegment generateMemorySegmentFromXml(const QDomElement& xmlElement) const; static MemorySegment generateMemorySegmentFromXml(const QDomElement& xmlElement);
RegisterGroup generateRegisterGroupFromXml(const QDomElement& xmlElement) const;
Register generateRegisterFromXml(const QDomElement& xmlElement) const; /**
* Constructs a RegisterGroup object from an XML element.
*
* @param xmlElement
* @return
*/
static RegisterGroup generateRegisterGroupFromXml(const QDomElement& xmlElement);
/**
* Constructs a Register object from an XML element.
*
* @param xmlElement
* @return
*/
static Register generateRegisterFromXml(const QDomElement& xmlElement);
public: public:
TargetDescriptionFile() = default; TargetDescriptionFile() = default;
@@ -77,7 +86,7 @@ namespace Bloom::Targets::TargetDescription
* *
* @param xmlFilePath * @param xmlFilePath
*/ */
TargetDescriptionFile(const QString& xmlFilePath) { explicit TargetDescriptionFile(const QString& xmlFilePath) {
this->init(xmlFilePath); this->init(xmlFilePath);
} }
@@ -86,14 +95,19 @@ namespace Bloom::Targets::TargetDescription
* *
* @param xml * @param xml
*/ */
TargetDescriptionFile(const QDomDocument& xml) { explicit TargetDescriptionFile(const QDomDocument& xml) {
this->init(xml); this->init(xml);
} }
/**
* Extracts target name.
*
* @return
*/
std::string getTargetName() const; std::string getTargetName() const;
/** /**
* Extracts all address spaces for the AVR8 target, from the target description XML. * Extracts all address spaces for the target.
* *
* Will return a mapping of the extracted address spaces, mapped by id. * Will return a mapping of the extracted address spaces, mapped by id.
* *
@@ -101,31 +115,40 @@ namespace Bloom::Targets::TargetDescription
*/ */
std::map<std::string, AddressSpace> getAddressSpacesMappedById() const; std::map<std::string, AddressSpace> getAddressSpacesMappedById() const;
/**
* Extracts all property groups and returns a mapping of them, with the property group name being the key.
*
* @return
*/
const std::map<std::string, PropertyGroup>& getPropertyGroupsMappedByName() const; const std::map<std::string, PropertyGroup>& getPropertyGroupsMappedByName() const;
/**
* Extracts all modules and returns a mapping of them, with the module name being the key.
*
* @return
*/
const std::map<std::string, Module>& getModulesMappedByName() const; const std::map<std::string, Module>& getModulesMappedByName() const;
/**
* Extracts all peripheral modules and returns a mapping of this, with the peripheral module name being
* the key.
*
* @return
*/
const std::map<std::string, Module>& getPeripheralModulesMappedByName() const; const std::map<std::string, Module>& getPeripheralModulesMappedByName() const;
std::optional<MemorySegment> getFlashMemorySegment() const; /**
std::optional<MemorySegment> getRamMemorySegment() const; * Extracts all variants.
std::optional<MemorySegment> getRegisterMemorySegment() const; *
std::optional<MemorySegment> getEepromMemorySegment() const; * @return
std::optional<MemorySegment> getFirstBootSectionMemorySegment() const; */
std::optional<RegisterGroup> getCpuRegisterGroup() const;
std::optional<RegisterGroup> getBootLoadRegisterGroup() const;
std::optional<RegisterGroup> getEepromRegisterGroup() const;
std::optional<Register> getStatusRegister() const;
std::optional<Register> getStackPointerRegister() const;
std::optional<Register> getStackPointerHighRegister() const;
std::optional<Register> getStackPointerLowRegister() const;
std::optional<Register> getOscillatorCalibrationRegister() const;
std::optional<Register> getSpmcsRegister() const;
std::optional<Register> getSpmcRegister() const;
std::optional<Register> getEepromAddressRegister() const;
std::optional<Register> getEepromAddressLowRegister() const;
std::optional<Register> getEepromAddressHighRegister() const;
std::optional<Register> getEepromDataRegister() const;
std::optional<Register> getEepromControlRegister() const;
std::vector<Variant> getVariants() const; std::vector<Variant> getVariants() const;
/**
* Extracts all pinouts and returns a mapping of them, with the pinout name being the key.
*
* @return
*/
const std::map<std::string, Pinout>& getPinoutsMappedByName() const; const std::map<std::string, Pinout>& getPinoutsMappedByName() const;
}; };
} }