2021-08-27 23:51:21 +01:00
|
|
|
#include "TargetDescriptionFile.hpp"
|
|
|
|
|
|
2021-05-31 01:01:14 +01:00
|
|
|
#include <QJsonDocument>
|
|
|
|
|
#include <QJsonArray>
|
2022-07-23 15:37:22 +01:00
|
|
|
#include <QJsonObject>
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-26 21:47:09 +00:00
|
|
|
#include "src/Services/PathService.hpp"
|
2021-10-06 21:12:31 +01:00
|
|
|
#include "src/Logger/Logger.hpp"
|
|
|
|
|
|
2021-05-31 01:01:14 +01:00
|
|
|
#include "src/Exceptions/Exception.hpp"
|
|
|
|
|
#include "src/Targets/TargetDescription/Exceptions/TargetDescriptionParsingFailureException.hpp"
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|
|
|
|
{
|
|
|
|
|
using namespace Bloom::Exceptions;
|
|
|
|
|
|
|
|
|
|
using Bloom::Targets::TargetDescription::RegisterGroup;
|
2022-06-03 11:53:03 +01:00
|
|
|
using Bloom::Targets::TargetDescription::AddressSpace;
|
2022-02-05 15:32:08 +00:00
|
|
|
using Bloom::Targets::TargetDescription::MemorySegment;
|
|
|
|
|
using Bloom::Targets::TargetDescription::MemorySegmentType;
|
|
|
|
|
using Bloom::Targets::TargetDescription::Register;
|
|
|
|
|
using Bloom::Targets::TargetVariant;
|
|
|
|
|
using Bloom::Targets::TargetRegisterDescriptor;
|
|
|
|
|
|
|
|
|
|
TargetDescriptionFile::TargetDescriptionFile(
|
|
|
|
|
const TargetSignature& targetSignature,
|
|
|
|
|
std::optional<std::string> targetName
|
|
|
|
|
) {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto targetSignatureHex = targetSignature.toHex();
|
|
|
|
|
const auto mapping = TargetDescriptionFile::getTargetDescriptionMapping();
|
|
|
|
|
const auto descriptionFiles = mapping.find(QString::fromStdString(targetSignatureHex).toLower())->toArray();
|
|
|
|
|
|
|
|
|
|
if (descriptionFiles.empty()) {
|
|
|
|
|
throw Exception(
|
|
|
|
|
"Failed to resolve target description file for target \"" + targetSignatureHex
|
|
|
|
|
+ "\" - unknown target signature."
|
2022-02-05 15:32:08 +00:00
|
|
|
);
|
2022-12-03 22:16:21 +00:00
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (descriptionFiles.size() > 1 && !targetName.has_value()) {
|
|
|
|
|
/*
|
|
|
|
|
* There are numerous target description files mapped to this target signature and we don't have a target
|
|
|
|
|
* name to filter by. There's really not much we can do at this point, so we'll just instruct the user to
|
|
|
|
|
* provide a specific target name.
|
|
|
|
|
*/
|
|
|
|
|
auto targetNames = QStringList();
|
|
|
|
|
std::transform(
|
|
|
|
|
descriptionFiles.begin(),
|
|
|
|
|
descriptionFiles.end(),
|
|
|
|
|
std::back_inserter(targetNames),
|
|
|
|
|
[] (const QJsonValue& descriptionFile) {
|
|
|
|
|
return QString(
|
|
|
|
|
"\"" + descriptionFile.toObject().find("targetName")->toString().toLower() + "\""
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
);
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
throw Exception(
|
|
|
|
|
"Failed to resolve target description file for target \"" + targetSignatureHex
|
|
|
|
|
+ "\" - ambiguous signature.\nThe signature is mapped to numerous targets: "
|
|
|
|
|
+ targetNames.join(", ").toStdString() + ".\n\nPlease update the target name in your Bloom "
|
|
|
|
|
+ "configuration file, to one of the above."
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
for (const auto& mappingJsonValue : descriptionFiles) {
|
|
|
|
|
const auto mappingObject = mappingJsonValue.toObject();
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (
|
|
|
|
|
targetName.has_value()
|
|
|
|
|
&& *targetName != mappingObject.find("targetName")->toString().toLower().toStdString()
|
|
|
|
|
) {
|
|
|
|
|
continue;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-26 21:47:09 +00:00
|
|
|
const auto descriptionFilePath = QString::fromStdString(Services::PathService::applicationDirPath()) + "/"
|
2022-12-03 22:16:21 +00:00
|
|
|
+ mappingObject.find("targetDescriptionFilePath")->toString();
|
|
|
|
|
|
|
|
|
|
Logger::debug("Loading AVR8 target description file: " + descriptionFilePath.toStdString());
|
|
|
|
|
Targets::TargetDescription::TargetDescriptionFile::init(descriptionFilePath);
|
|
|
|
|
return;
|
2021-05-31 01:01:14 +01:00
|
|
|
}
|
2022-12-03 22:16:21 +00:00
|
|
|
|
|
|
|
|
throw Exception(
|
|
|
|
|
"Failed to resolve target description file for target \"" + *targetName
|
|
|
|
|
+ "\" - target signature \"" + targetSignatureHex + "\" does not belong to target with name \""
|
|
|
|
|
+ *targetName + "\". Please review your bloom.yaml configuration."
|
|
|
|
|
);
|
2021-05-31 01:01:14 +01:00
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
void TargetDescriptionFile::init(const QDomDocument& xml) {
|
|
|
|
|
Targets::TargetDescription::TargetDescriptionFile::init(xml);
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-08-04 21:06:13 +01:00
|
|
|
this->loadSupportedPhysicalInterfaces();
|
2022-02-05 15:32:08 +00:00
|
|
|
this->loadPadDescriptors();
|
|
|
|
|
this->loadTargetVariants();
|
|
|
|
|
this->loadTargetRegisterDescriptors();
|
2021-05-31 01:01:14 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() {
|
|
|
|
|
auto mappingFile = QFile(
|
2022-12-26 21:47:09 +00:00
|
|
|
QString::fromStdString(Services::PathService::resourcesDirPath() + "/TargetDescriptionFiles/AVR/Mapping.json")
|
2022-02-05 15:32:08 +00:00
|
|
|
);
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (!mappingFile.exists()) {
|
|
|
|
|
throw Exception("Failed to load AVR target description mapping - mapping file not found");
|
|
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
mappingFile.open(QIODevice::ReadOnly);
|
|
|
|
|
return QJsonDocument::fromJson(mappingFile.readAll()).object();
|
2021-05-31 01:01:14 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
TargetSignature TargetDescriptionFile::getTargetSignature() const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& propertyGroups = this->propertyGroupsMappedByName;
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto signaturePropertyGroupIt = propertyGroups.find("signatures");
|
2022-02-05 15:32:08 +00:00
|
|
|
if (signaturePropertyGroupIt == propertyGroups.end()) {
|
|
|
|
|
throw TargetDescriptionParsingFailureException("Signature property group not found");
|
|
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto& signatureProperties = signaturePropertyGroupIt->second.propertiesMappedByName;
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<unsigned char> signatureByteZero;
|
|
|
|
|
std::optional<unsigned char> signatureByteOne;
|
|
|
|
|
std::optional<unsigned char> signatureByteTwo;
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto signatureZeroIt = signatureProperties.find("signature0");
|
|
|
|
|
if (signatureZeroIt != signatureProperties.end()) {
|
|
|
|
|
signatureByteZero = static_cast<unsigned char>(signatureZeroIt->second.value.toShort(nullptr, 16));
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto signatureOneIt = signatureProperties.find("signature1");
|
|
|
|
|
if (signatureOneIt != signatureProperties.end()) {
|
|
|
|
|
signatureByteOne = static_cast<unsigned char>(signatureOneIt->second.value.toShort(nullptr, 16));
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto signatureTwoIt = signatureProperties.find("signature2");
|
|
|
|
|
if (signatureTwoIt != signatureProperties.end()) {
|
|
|
|
|
signatureByteTwo = static_cast<unsigned char>(signatureTwoIt->second.value.toShort(nullptr, 16));
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (signatureByteZero.has_value() && signatureByteOne.has_value() && signatureByteTwo.has_value()) {
|
|
|
|
|
return TargetSignature(signatureByteZero.value(), signatureByteOne.value(), signatureByteTwo.value());
|
|
|
|
|
}
|
2021-05-31 01:01:14 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
throw TargetDescriptionParsingFailureException(
|
|
|
|
|
"Failed to extract target signature from AVR8 target description."
|
|
|
|
|
);
|
2021-05-31 01:01:14 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
Family TargetDescriptionFile::getFamily() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
static const auto targetFamiliesByName = TargetDescriptionFile::getFamilyNameToEnumMapping();
|
|
|
|
|
|
|
|
|
|
const auto familyName = this->deviceElement.attributes().namedItem(
|
2022-02-05 15:32:08 +00:00
|
|
|
"family"
|
|
|
|
|
).nodeValue().toLower().toStdString();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (familyName.empty()) {
|
|
|
|
|
throw Exception("Could not find target family name in target description file.");
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto familyIt = targetFamiliesByName.find(familyName);
|
|
|
|
|
|
|
|
|
|
if (familyIt == targetFamiliesByName.end()) {
|
2022-02-05 15:32:08 +00:00
|
|
|
throw Exception("Unknown family name in target description file.");
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
return familyIt->second;
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
TargetParameters TargetDescriptionFile::getTargetParameters() const {
|
|
|
|
|
TargetParameters targetParameters;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
|
|
|
|
const auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-06-03 11:53:03 +01:00
|
|
|
const auto programMemoryAddressSpace = this->getProgramMemoryAddressSpace();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-06-03 11:53:03 +01:00
|
|
|
if (programMemoryAddressSpace.has_value()) {
|
|
|
|
|
targetParameters.flashSize = programMemoryAddressSpace->size;
|
|
|
|
|
targetParameters.flashStartAddress = programMemoryAddressSpace->startAddress;
|
|
|
|
|
|
|
|
|
|
const auto appMemorySegment = this->getFlashApplicationMemorySegment(programMemoryAddressSpace.value());
|
|
|
|
|
|
2022-12-12 00:51:45 +00:00
|
|
|
if (appMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.appSectionStartAddress = appMemorySegment->startAddress;
|
|
|
|
|
targetParameters.appSectionSize = appMemorySegment->size;
|
|
|
|
|
targetParameters.flashPageSize = appMemorySegment->pageSize;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto ramMemorySegment = this->getRamMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (ramMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.ramSize = ramMemorySegment->size;
|
|
|
|
|
targetParameters.ramStartAddress = ramMemorySegment->startAddress;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto ioMemorySegment = this->getIoMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (ioMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.mappedIoSegmentSize = ioMemorySegment->size;
|
|
|
|
|
targetParameters.mappedIoSegmentStartAddress = ioMemorySegment->startAddress;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto registerMemorySegment = this->getRegisterMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (registerMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.gpRegisterSize = registerMemorySegment->size;
|
|
|
|
|
targetParameters.gpRegisterStartAddress = registerMemorySegment->startAddress;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto eepromMemorySegment = this->getEepromMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.eepromSize = eepromMemorySegment->size;
|
|
|
|
|
targetParameters.eepromStartAddress = eepromMemorySegment->startAddress;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromMemorySegment->pageSize.has_value()) {
|
|
|
|
|
targetParameters.eepromPageSize = eepromMemorySegment->pageSize.value();
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto firstBootSectionMemorySegment = this->getFirstBootSectionMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (firstBootSectionMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.bootSectionStartAddress = firstBootSectionMemorySegment->startAddress / 2;
|
|
|
|
|
targetParameters.bootSectionSize = firstBootSectionMemorySegment->size;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::uint32_t cpuRegistersOffset = 0;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto cpuPeripheralModuleIt = peripheralModules.find("cpu");
|
|
|
|
|
if (cpuPeripheralModuleIt != peripheralModules.end()) {
|
|
|
|
|
const auto& cpuPeripheralModule = cpuPeripheralModuleIt->second;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto cpuInstanceIt = cpuPeripheralModule.instancesMappedByName.find("cpu");
|
|
|
|
|
if (cpuInstanceIt != cpuPeripheralModule.instancesMappedByName.end()) {
|
|
|
|
|
const auto& cpuInstance = cpuInstanceIt->second;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto cpuRegisterGroupIt = cpuInstance.registerGroupsMappedByName.find("cpu");
|
|
|
|
|
if (cpuRegisterGroupIt != cpuInstance.registerGroupsMappedByName.end()) {
|
|
|
|
|
cpuRegistersOffset = cpuRegisterGroupIt->second.offset.value_or(0);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto statusRegister = this->getStatusRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (statusRegister.has_value()) {
|
|
|
|
|
targetParameters.statusRegisterStartAddress = cpuRegistersOffset + statusRegister->offset;
|
|
|
|
|
targetParameters.statusRegisterSize = statusRegister->size;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto stackPointerRegister = this->getStackPointerRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (stackPointerRegister.has_value()) {
|
|
|
|
|
targetParameters.stackPointerRegisterLowAddress = cpuRegistersOffset + stackPointerRegister->offset;
|
|
|
|
|
targetParameters.stackPointerRegisterSize = stackPointerRegister->size;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else {
|
|
|
|
|
// Sometimes the SP register is split into two register nodes, one for low, the other for high
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto stackPointerLowRegister = this->getStackPointerLowRegister();
|
|
|
|
|
const auto stackPointerHighRegister = this->getStackPointerHighRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
|
|
|
|
|
if (stackPointerLowRegister.has_value()) {
|
|
|
|
|
targetParameters.stackPointerRegisterLowAddress = cpuRegistersOffset
|
|
|
|
|
+ stackPointerLowRegister->offset;
|
|
|
|
|
targetParameters.stackPointerRegisterSize = stackPointerLowRegister->size;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (stackPointerHighRegister.has_value()) {
|
|
|
|
|
targetParameters.stackPointerRegisterSize =
|
|
|
|
|
targetParameters.stackPointerRegisterSize.has_value() ?
|
|
|
|
|
targetParameters.stackPointerRegisterSize.value() + stackPointerHighRegister->size :
|
|
|
|
|
stackPointerHighRegister->size;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-08-04 21:06:13 +01:00
|
|
|
const auto& supportedPhysicalInterfaces = this->getSupportedPhysicalInterfaces();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (
|
|
|
|
|
supportedPhysicalInterfaces.contains(PhysicalInterface::DEBUG_WIRE)
|
2022-02-05 15:32:08 +00:00
|
|
|
|| supportedPhysicalInterfaces.contains(PhysicalInterface::JTAG)
|
|
|
|
|
) {
|
|
|
|
|
this->loadDebugWireAndJtagTargetParameters(targetParameters);
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (supportedPhysicalInterfaces.contains(PhysicalInterface::PDI)) {
|
|
|
|
|
this->loadPdiTargetParameters(targetParameters);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (supportedPhysicalInterfaces.contains(PhysicalInterface::UPDI)) {
|
|
|
|
|
this->loadUpdiTargetParameters(targetParameters);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return targetParameters;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-03-02 22:42:28 +00:00
|
|
|
IspParameters TargetDescriptionFile::getIspParameters() const {
|
|
|
|
|
if (!this->propertyGroupsMappedByName.contains("isp_interface")) {
|
|
|
|
|
throw Exception("TDF missing ISP parameters");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& ispParameterPropertiesByName = this->propertyGroupsMappedByName.at(
|
|
|
|
|
"isp_interface"
|
|
|
|
|
).propertiesMappedByName;
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispenterprogmode_timeout")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode timeout property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispenterprogmode_stabdelay")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode stabilization delay property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispenterprogmode_cmdexedelay")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode command execution delay property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispenterprogmode_synchloops")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode sync loops property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispenterprogmode_bytedelay")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode byte delay property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispenterprogmode_pollindex")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode poll index property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispenterprogmode_pollvalue")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode poll value property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispleaveprogmode_predelay")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode pre-delay property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispleaveprogmode_postdelay")) {
|
|
|
|
|
throw Exception("TDF missing ISP programming mode post-delay property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispreadsign_pollindex")) {
|
|
|
|
|
throw Exception("TDF missing ISP read signature poll index property");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ispParameterPropertiesByName.contains("ispreadfuse_pollindex")) {
|
|
|
|
|
throw Exception("TDF missing ISP read fuse poll index property");
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-05 14:09:36 +00:00
|
|
|
if (!ispParameterPropertiesByName.contains("ispreadlock_pollindex")) {
|
|
|
|
|
throw Exception("TDF missing ISP read lock poll index property");
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-02 22:42:28 +00:00
|
|
|
auto output = IspParameters();
|
|
|
|
|
|
|
|
|
|
output.programModeTimeout = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispenterprogmode_timeout").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.programModeStabilizationDelay = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispenterprogmode_stabdelay").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.programModeCommandExecutionDelay = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispenterprogmode_cmdexedelay").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.programModeSyncLoops = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispenterprogmode_synchloops").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.programModeByteDelay = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispenterprogmode_bytedelay").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.programModePollValue = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispenterprogmode_pollvalue").value.toUShort(nullptr, 16)
|
|
|
|
|
);
|
|
|
|
|
output.programModePollIndex = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispenterprogmode_pollindex").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.programModePreDelay = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispleaveprogmode_predelay").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.programModePostDelay = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispleaveprogmode_postdelay").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.readSignaturePollIndex = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispreadsign_pollindex").value.toUShort()
|
|
|
|
|
);
|
|
|
|
|
output.readFusePollIndex = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispreadfuse_pollindex").value.toUShort()
|
|
|
|
|
);
|
2022-03-05 14:09:36 +00:00
|
|
|
output.readLockPollIndex = static_cast<std::uint8_t>(
|
|
|
|
|
ispParameterPropertiesByName.at("ispreadlock_pollindex").value.toUShort()
|
|
|
|
|
);
|
2022-03-02 22:42:28 +00:00
|
|
|
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-05 14:08:27 +00:00
|
|
|
std::optional<FuseBitsDescriptor> TargetDescriptionFile::getDwenFuseBitsDescriptor() const {
|
|
|
|
|
return this->getFuseBitsDescriptorByName("dwen");
|
2022-03-04 23:43:26 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-05 14:08:27 +00:00
|
|
|
std::optional<FuseBitsDescriptor> TargetDescriptionFile::getSpienFuseBitsDescriptor() const {
|
|
|
|
|
return this->getFuseBitsDescriptorByName("spien");
|
2022-03-04 23:43:26 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-04 21:06:13 +01:00
|
|
|
void TargetDescriptionFile::loadSupportedPhysicalInterfaces() {
|
2022-02-05 15:32:08 +00:00
|
|
|
auto interfaceNamesToInterfaces = std::map<std::string, PhysicalInterface>({
|
|
|
|
|
{"updi", PhysicalInterface::UPDI},
|
|
|
|
|
{"debugwire", PhysicalInterface::DEBUG_WIRE},
|
2022-09-18 15:01:39 +01:00
|
|
|
{"jtag", PhysicalInterface::JTAG},
|
2022-02-05 15:32:08 +00:00
|
|
|
{"pdi", PhysicalInterface::PDI},
|
2022-08-04 21:06:13 +01:00
|
|
|
{"isp", PhysicalInterface::ISP},
|
2022-02-05 15:32:08 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (const auto& [interfaceName, interface]: this->interfacesByName) {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto interfaceIt = interfaceNamesToInterfaces.find(interfaceName);
|
|
|
|
|
if (interfaceIt != interfaceNamesToInterfaces.end()) {
|
|
|
|
|
this->supportedPhysicalInterfaces.insert(interfaceIt->second);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
void TargetDescriptionFile::loadPadDescriptors() {
|
|
|
|
|
const auto& modules = this->getModulesMappedByName();
|
2022-12-03 22:16:21 +00:00
|
|
|
|
|
|
|
|
const auto portModuleIt = modules.find("port");
|
|
|
|
|
const auto portModule = (portModuleIt != modules.end()) ? std::optional(portModuleIt->second) : std::nullopt;
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
const auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto portPeripheralModuleIt = peripheralModules.find("port");
|
|
|
|
|
if (portPeripheralModuleIt == peripheralModules.end()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto& portPeripheralModule = portPeripheralModuleIt->second;
|
|
|
|
|
|
|
|
|
|
for (const auto& [instanceName, instance] : portPeripheralModule.instancesMappedByName) {
|
|
|
|
|
if (instanceName.find("port") != 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto portPeripheralRegisterGroupIt = portPeripheralModule.registerGroupsMappedByName.find(
|
|
|
|
|
instanceName
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const auto portPeripheralRegisterGroup =
|
|
|
|
|
portPeripheralRegisterGroupIt != portPeripheralModule.registerGroupsMappedByName.end()
|
|
|
|
|
? std::optional(portPeripheralRegisterGroupIt->second)
|
|
|
|
|
: std::nullopt;
|
|
|
|
|
|
|
|
|
|
for (const auto& signal : instance.instanceSignals) {
|
|
|
|
|
if (!signal.index.has_value()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& padDescriptor = this->padDescriptorsByName.insert(
|
|
|
|
|
std::pair(signal.padName, PadDescriptor())
|
|
|
|
|
).first->second;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
padDescriptor.name = signal.padName;
|
|
|
|
|
padDescriptor.gpioPinNumber = signal.index.value();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (!portModule.has_value()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto instanceRegisterGroupIt = portModule->registerGroupsMappedByName.find(instanceName);
|
|
|
|
|
if (instanceRegisterGroupIt != portModule->registerGroupsMappedByName.end()) {
|
|
|
|
|
// We have register information for this port
|
|
|
|
|
const auto& registerGroup = instanceRegisterGroupIt->second;
|
|
|
|
|
|
|
|
|
|
for (const auto& [registerName, portRegister] : registerGroup.registersMappedByName) {
|
|
|
|
|
if (registerName.find("port") == 0) {
|
|
|
|
|
// This is the data register for the port
|
|
|
|
|
padDescriptor.gpioPortAddress = portRegister.offset;
|
2022-02-05 15:32:08 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (registerName.find("pin") == 0) {
|
|
|
|
|
// This is the input data register for the port
|
|
|
|
|
padDescriptor.gpioPortInputAddress = portRegister.offset;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (registerName.find("ddr") == 0) {
|
|
|
|
|
// This is the data direction register for the port
|
|
|
|
|
padDescriptor.gpioDdrAddress = portRegister.offset;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto portRegisterGroupIt = portModule->registerGroupsMappedByName.find("port");
|
|
|
|
|
if (portRegisterGroupIt != portModule->registerGroupsMappedByName.end()) {
|
|
|
|
|
// We have generic register information for all ports on the target
|
|
|
|
|
const auto& registerGroup = portRegisterGroupIt->second;
|
|
|
|
|
|
|
|
|
|
for (const auto& [registerName, portRegister] : registerGroup.registersMappedByName) {
|
|
|
|
|
if (registerName == "out") {
|
|
|
|
|
// Include the port register offset
|
|
|
|
|
padDescriptor.gpioPortAddress = (
|
|
|
|
|
portPeripheralRegisterGroup.has_value()
|
|
|
|
|
&& portPeripheralRegisterGroup->offset.has_value()
|
|
|
|
|
)
|
|
|
|
|
? portPeripheralRegisterGroup->offset.value_or(0) + portRegister.offset
|
|
|
|
|
: 0 + portRegister.offset;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (registerName == "dir") {
|
|
|
|
|
padDescriptor.gpioDdrAddress = (
|
|
|
|
|
portPeripheralRegisterGroup.has_value()
|
|
|
|
|
&& portPeripheralRegisterGroup->offset.has_value()
|
|
|
|
|
)
|
|
|
|
|
? portPeripheralRegisterGroup->offset.value_or(0) + portRegister.offset
|
|
|
|
|
: 0 + portRegister.offset;
|
|
|
|
|
continue;
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (registerName == "in") {
|
|
|
|
|
padDescriptor.gpioPortInputAddress = (
|
|
|
|
|
portPeripheralRegisterGroup.has_value()
|
|
|
|
|
&& portPeripheralRegisterGroup->offset.has_value()
|
|
|
|
|
)
|
|
|
|
|
? portPeripheralRegisterGroup->offset.value_or(0) + portRegister.offset
|
|
|
|
|
: 0 + portRegister.offset;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2022-12-03 22:16:21 +00:00
|
|
|
|
|
|
|
|
continue;
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
void TargetDescriptionFile::loadTargetVariants() {
|
|
|
|
|
auto tdVariants = this->getVariants();
|
|
|
|
|
auto tdPinoutsByName = this->getPinoutsMappedByName();
|
|
|
|
|
const auto& modules = this->getModulesMappedByName();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
for (const auto& tdVariant : tdVariants) {
|
|
|
|
|
if (tdVariant.disabled) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
auto targetVariant = TargetVariant();
|
|
|
|
|
targetVariant.id = static_cast<int>(this->targetVariantsById.size());
|
|
|
|
|
targetVariant.name = tdVariant.name;
|
|
|
|
|
targetVariant.packageName = tdVariant.package;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (tdVariant.package.find("QFP") == 0 || tdVariant.package.find("TQFP") == 0) {
|
|
|
|
|
targetVariant.package = TargetPackage::QFP;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else if (tdVariant.package.find("PDIP") == 0 || tdVariant.package.find("DIP") == 0) {
|
|
|
|
|
targetVariant.package = TargetPackage::DIP;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else if (tdVariant.package.find("QFN") == 0 || tdVariant.package.find("VQFN") == 0) {
|
|
|
|
|
targetVariant.package = TargetPackage::QFN;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else if (tdVariant.package.find("SOIC") == 0) {
|
|
|
|
|
targetVariant.package = TargetPackage::SOIC;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else if (tdVariant.package.find("SSOP") == 0) {
|
|
|
|
|
targetVariant.package = TargetPackage::SSOP;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto tdPinoutIt = tdPinoutsByName.find(tdVariant.pinoutName);
|
|
|
|
|
if (tdPinoutIt == tdPinoutsByName.end()) {
|
2022-02-05 15:32:08 +00:00
|
|
|
// Missing pinouts in the target description file
|
|
|
|
|
continue;
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto& tdPinout = tdPinoutIt->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
for (const auto& tdPin : tdPinout.pins) {
|
|
|
|
|
auto targetPin = TargetPinDescriptor();
|
|
|
|
|
targetPin.name = tdPin.pad;
|
|
|
|
|
targetPin.padName = tdPin.pad;
|
|
|
|
|
targetPin.number = tdPin.position;
|
|
|
|
|
targetPin.variantId = targetVariant.id;
|
|
|
|
|
|
|
|
|
|
// TODO: REMOVE THIS:
|
2022-06-22 22:24:27 +01:00
|
|
|
if (
|
|
|
|
|
tdPin.pad.find("vcc") == 0
|
2022-02-05 15:32:08 +00:00
|
|
|
|| tdPin.pad.find("avcc") == 0
|
|
|
|
|
|| tdPin.pad.find("aref") == 0
|
|
|
|
|
|| tdPin.pad.find("avdd") == 0
|
|
|
|
|
|| tdPin.pad.find("vdd") == 0
|
2022-06-22 22:24:27 +01:00
|
|
|
) {
|
2022-02-05 15:32:08 +00:00
|
|
|
targetPin.type = TargetPinType::VCC;
|
|
|
|
|
|
|
|
|
|
} else if (tdPin.pad.find("gnd") == 0) {
|
|
|
|
|
targetPin.type = TargetPinType::GND;
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto padIt = this->padDescriptorsByName.find(targetPin.padName);
|
|
|
|
|
if (padIt != this->padDescriptorsByName.end()) {
|
|
|
|
|
const auto& pad = padIt->second;
|
2022-06-22 22:23:00 +01:00
|
|
|
if (pad.gpioPortAddress.has_value() && pad.gpioDdrAddress.has_value()) {
|
2022-02-05 15:32:08 +00:00
|
|
|
targetPin.type = TargetPinType::GPIO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
targetVariant.pinDescriptorsByNumber.insert(std::pair(targetPin.number, targetPin));
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
this->targetVariantsById.insert(std::pair(targetVariant.id, targetVariant));
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
void TargetDescriptionFile::loadTargetRegisterDescriptors() {
|
2022-03-04 23:45:14 +00:00
|
|
|
const auto& modulesByName = this->modulesMappedByName;
|
|
|
|
|
const auto& peripheralModulesByName = this->peripheralModulesMappedByName;
|
2022-02-05 15:32:08 +00:00
|
|
|
|
|
|
|
|
for (const auto& [moduleName, module] : modulesByName) {
|
|
|
|
|
for (const auto& [registerGroupName, registerGroup] : module.registerGroupsMappedByName) {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto peripheralRegisterGroupsIt = this->peripheralRegisterGroupsMappedByModuleRegisterGroupName.find(
|
|
|
|
|
registerGroupName
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (peripheralRegisterGroupsIt != this->peripheralRegisterGroupsMappedByModuleRegisterGroupName.end()) {
|
|
|
|
|
const auto& peripheralRegisterGroups = peripheralRegisterGroupsIt->second;
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
for (const auto& peripheralRegisterGroup : peripheralRegisterGroups) {
|
|
|
|
|
if (peripheralRegisterGroup.addressSpaceId.value_or("") != "data") {
|
|
|
|
|
// Currently, we only deal with registers in the data address space.
|
2021-08-27 23:51:21 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
2021-08-07 17:15:48 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
for (const auto& [moduleRegisterName, moduleRegister] : registerGroup.registersMappedByName) {
|
|
|
|
|
if (moduleRegister.size < 1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-08-07 17:15:48 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
auto registerDescriptor = TargetRegisterDescriptor();
|
|
|
|
|
registerDescriptor.type = moduleName == "port"
|
|
|
|
|
? TargetRegisterType::PORT_REGISTER : TargetRegisterType::OTHER;
|
|
|
|
|
registerDescriptor.memoryType = TargetMemoryType::RAM;
|
|
|
|
|
registerDescriptor.name = moduleRegisterName;
|
|
|
|
|
registerDescriptor.groupName = peripheralRegisterGroup.name;
|
|
|
|
|
registerDescriptor.size = moduleRegister.size;
|
|
|
|
|
registerDescriptor.startAddress = moduleRegister.offset
|
|
|
|
|
+ peripheralRegisterGroup.offset.value_or(0);
|
|
|
|
|
|
|
|
|
|
if (moduleRegister.caption.has_value() && !moduleRegister.caption->empty()) {
|
|
|
|
|
registerDescriptor.description = moduleRegister.caption;
|
|
|
|
|
}
|
2021-08-30 22:32:40 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (moduleRegister.readWriteAccess.has_value()) {
|
2022-03-04 23:45:14 +00:00
|
|
|
const auto& readWriteAccess = moduleRegister.readWriteAccess.value();
|
2022-02-05 15:32:08 +00:00
|
|
|
registerDescriptor.readable = readWriteAccess.find('r') != std::string::npos;
|
|
|
|
|
registerDescriptor.writable = readWriteAccess.find('w') != std::string::npos;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
/*
|
|
|
|
|
* If the TDF doesn't specify the OCD read/write access for a register, we assume both
|
|
|
|
|
* are permitted.
|
|
|
|
|
*/
|
|
|
|
|
registerDescriptor.readable = true;
|
|
|
|
|
registerDescriptor.writable = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->targetRegisterDescriptorsByType[registerDescriptor.type].insert(registerDescriptor);
|
|
|
|
|
}
|
2021-08-27 23:51:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-08-07 17:15:48 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-03-05 14:08:27 +00:00
|
|
|
std::optional<FuseBitsDescriptor> TargetDescriptionFile::getFuseBitsDescriptorByName(
|
2022-03-04 23:43:26 +00:00
|
|
|
const std::string& fuseBitName
|
|
|
|
|
) const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto fuseModuleIt = this->modulesMappedByName.find("fuse");
|
|
|
|
|
|
|
|
|
|
if (fuseModuleIt == this->modulesMappedByName.end()) {
|
2022-03-04 23:43:26 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto& fuseModule = fuseModuleIt->second;
|
2022-03-04 23:43:26 +00:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto fuseRegisterGroupIt = fuseModule.registerGroupsMappedByName.find("fuse");
|
|
|
|
|
|
|
|
|
|
if (fuseRegisterGroupIt == fuseModule.registerGroupsMappedByName.end()) {
|
2022-03-04 23:43:26 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto& fuseRegisterGroup = fuseRegisterGroupIt->second;
|
2022-03-04 23:43:26 +00:00
|
|
|
|
2022-03-04 23:45:14 +00:00
|
|
|
static const auto fuseTypesByName = std::map<std::string, FuseType>({
|
|
|
|
|
{"low", FuseType::LOW},
|
|
|
|
|
{"high", FuseType::HIGH},
|
|
|
|
|
{"extended", FuseType::EXTENDED},
|
|
|
|
|
});
|
2022-03-04 23:43:26 +00:00
|
|
|
|
|
|
|
|
for (const auto&[fuseTypeName, fuse] : fuseRegisterGroup.registersMappedByName) {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto fuseTypeIt = fuseTypesByName.find(fuseTypeName);
|
|
|
|
|
if (fuseTypeIt == fuseTypesByName.end()) {
|
2022-03-04 23:43:26 +00:00
|
|
|
// Unknown fuse type name
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto fuseBitFieldIt = fuse.bitFieldsMappedByName.find(fuseBitName);
|
|
|
|
|
|
|
|
|
|
if (fuseBitFieldIt != fuse.bitFieldsMappedByName.end()) {
|
2022-03-05 14:08:27 +00:00
|
|
|
return FuseBitsDescriptor(
|
2022-12-03 22:16:21 +00:00
|
|
|
fuseTypeIt->second,
|
|
|
|
|
fuseBitFieldIt->second.mask
|
2022-03-04 23:43:26 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2022-03-04 23:45:14 +00:00
|
|
|
|
2022-06-03 11:53:03 +01:00
|
|
|
std::optional<AddressSpace> TargetDescriptionFile::getProgramMemoryAddressSpace() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto programAddressSpaceIt = this->addressSpacesMappedById.find("prog");
|
|
|
|
|
|
|
|
|
|
if (programAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
return programAddressSpaceIt->second;
|
2022-06-03 11:53:03 +01:00
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-06-03 11:53:03 +01:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-06-03 11:53:03 +01:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getFlashApplicationMemorySegment(
|
|
|
|
|
const AddressSpace& programAddressSpace
|
|
|
|
|
) const {
|
|
|
|
|
const auto& programMemorySegments = programAddressSpace.memorySegmentsByTypeAndName;
|
|
|
|
|
|
2022-12-12 01:15:06 +00:00
|
|
|
const auto flashMemorySegmentsIt = programMemorySegments.find(MemorySegmentType::FLASH);
|
|
|
|
|
if (flashMemorySegmentsIt != programMemorySegments.end()) {
|
|
|
|
|
const auto& flashMemorySegments = flashMemorySegmentsIt->second;
|
2022-06-03 11:53:03 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* In AVR8 TDFs, flash application memory segments are typically named "APP_SECTION", "PROGMEM" or
|
|
|
|
|
* "FLASH".
|
|
|
|
|
*/
|
2022-12-12 01:15:06 +00:00
|
|
|
const auto appSectionSegmentIt = flashMemorySegments.find("app_section");
|
|
|
|
|
if (appSectionSegmentIt != flashMemorySegments.end()) {
|
|
|
|
|
return appSectionSegmentIt->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto programMemSegmentIt = flashMemorySegments.find("progmem");
|
|
|
|
|
if (programMemSegmentIt != flashMemorySegments.end()) {
|
|
|
|
|
return programMemSegmentIt->second;
|
|
|
|
|
}
|
2022-06-03 11:53:03 +01:00
|
|
|
|
2022-12-12 01:15:06 +00:00
|
|
|
const auto flashSegmentIt = flashMemorySegments.find("flash");
|
2022-06-03 11:53:03 +01:00
|
|
|
if (flashSegmentIt != flashMemorySegments.end()) {
|
|
|
|
|
return flashSegmentIt->second;
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getRamMemorySegment() const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& addressMapping = this->addressSpacesMappedById;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
// Internal RAM ®ister attributes are usually found in the data address space
|
|
|
|
|
auto dataAddressSpaceIt = addressMapping.find("data");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (dataAddressSpaceIt != addressMapping.end()) {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& dataAddressSpace = dataAddressSpaceIt->second;
|
|
|
|
|
const auto& dataMemorySegments = dataAddressSpace.memorySegmentsByTypeAndName;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (dataMemorySegments.find(MemorySegmentType::RAM) != dataMemorySegments.end()) {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& ramMemorySegments = dataMemorySegments.find(MemorySegmentType::RAM)->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
auto ramMemorySegmentIt = ramMemorySegments.begin();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (ramMemorySegmentIt != ramMemorySegments.end()) {
|
|
|
|
|
return ramMemorySegmentIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getIoMemorySegment() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto dataAddressMappingIt = this->addressSpacesMappedById.find("data");
|
2021-07-04 00:29:43 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (dataAddressMappingIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
const auto& dataAddressSpace = dataAddressMappingIt->second;
|
|
|
|
|
const auto ioMemorySegmentsIt = dataAddressSpace.memorySegmentsByTypeAndName.find(MemorySegmentType::IO);
|
2021-07-04 00:29:43 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (ioMemorySegmentsIt != dataAddressSpace.memorySegmentsByTypeAndName.end()) {
|
|
|
|
|
const auto& ramMemorySegments = ioMemorySegmentsIt->second;
|
|
|
|
|
const auto ramMemorySegmentIt = ramMemorySegments.begin();
|
2021-07-04 00:29:43 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (ramMemorySegmentIt != ramMemorySegments.end()) {
|
|
|
|
|
return ramMemorySegmentIt->second;
|
|
|
|
|
}
|
2021-07-04 00:29:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-07-04 00:29:43 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getRegisterMemorySegment() const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& addressMapping = this->addressSpacesMappedById;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
// Internal RAM ®ister attributes are usually found in the data address space
|
|
|
|
|
auto dataAddressSpaceIt = addressMapping.find("data");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (dataAddressSpaceIt != addressMapping.end()) {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& dataAddressSpace = dataAddressSpaceIt->second;
|
|
|
|
|
const auto& dataMemorySegments = dataAddressSpace.memorySegmentsByTypeAndName;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (dataMemorySegments.find(MemorySegmentType::REGISTERS) != dataMemorySegments.end()) {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& registerMemorySegments = dataMemorySegments.find(MemorySegmentType::REGISTERS)->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
auto registerMemorySegmentIt = registerMemorySegments.begin();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (registerMemorySegmentIt != registerMemorySegments.end()) {
|
|
|
|
|
return registerMemorySegmentIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getEepromMemorySegment() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto eepromAddressSpaceIt = this->addressSpacesMappedById.find("eeprom");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (eepromAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
const auto& eepromAddressSpace = eepromAddressSpaceIt->second;
|
|
|
|
|
const auto eepromSegmentsIt = eepromAddressSpace.memorySegmentsByTypeAndName.find(
|
|
|
|
|
MemorySegmentType::EEPROM
|
|
|
|
|
);
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (
|
|
|
|
|
eepromSegmentsIt != eepromAddressSpace.memorySegmentsByTypeAndName.end()
|
|
|
|
|
&& !eepromSegmentsIt->second.empty()
|
|
|
|
|
) {
|
|
|
|
|
return eepromSegmentsIt->second.begin()->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else {
|
|
|
|
|
// The EEPROM memory segment may be part of the data address space
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto dataAddressSpaceIt = this->addressSpacesMappedById.find("data");
|
|
|
|
|
|
|
|
|
|
if (dataAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
const auto& dataAddressSpace = dataAddressSpaceIt->second;
|
|
|
|
|
const auto eepromSegmentsIt = dataAddressSpace.memorySegmentsByTypeAndName.find(
|
|
|
|
|
MemorySegmentType::EEPROM
|
|
|
|
|
);
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (
|
|
|
|
|
eepromSegmentsIt != dataAddressSpace.memorySegmentsByTypeAndName.end()
|
|
|
|
|
&& !eepromSegmentsIt->second.empty()
|
|
|
|
|
) {
|
|
|
|
|
return eepromSegmentsIt->second.begin()->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getFirstBootSectionMemorySegment() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto programAddressSpaceIt = this->addressSpacesMappedById.find("prog");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (programAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& programAddressSpace = programAddressSpaceIt->second;
|
|
|
|
|
const auto& programMemorySegments = programAddressSpace.memorySegmentsByTypeAndName;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto flashMemorySegmentsit = programMemorySegments.find(MemorySegmentType::FLASH);
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (flashMemorySegmentsit != programMemorySegments.end()) {
|
|
|
|
|
const auto& flashMemorySegments = flashMemorySegmentsit->second;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
auto bootSectionSegmentIt = flashMemorySegments.find("boot_section_1");
|
|
|
|
|
if (bootSectionSegmentIt != flashMemorySegments.end()) {
|
|
|
|
|
return bootSectionSegmentIt->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bootSectionSegmentIt = flashMemorySegments.find("boot_section");
|
|
|
|
|
if (bootSectionSegmentIt != flashMemorySegments.end()) {
|
|
|
|
|
return bootSectionSegmentIt->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getSignatureMemorySegment() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto signatureAddressSpaceIt = this->addressSpacesMappedById.find("signatures");
|
|
|
|
|
if (signatureAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
const auto& signaturesAddressSpace = signatureAddressSpaceIt->second;
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& signaturesAddressSpaceSegments = signaturesAddressSpace.memorySegmentsByTypeAndName;
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto signatureMemorySegmentsIt = signaturesAddressSpaceSegments.find(MemorySegmentType::SIGNATURES);
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (
|
|
|
|
|
signatureMemorySegmentsIt != signaturesAddressSpaceSegments.end()
|
|
|
|
|
&& !signatureMemorySegmentsIt->second.empty()
|
|
|
|
|
) {
|
|
|
|
|
return signatureMemorySegmentsIt->second.begin()->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else {
|
|
|
|
|
// The signatures memory segment may be part of the data address space
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto dataAddressSpaceIt = this->addressSpacesMappedById.find("data");
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (dataAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
const auto& dataAddressSpace = dataAddressSpaceIt->second;
|
|
|
|
|
const auto signatureSegmentsIt = dataAddressSpace.memorySegmentsByTypeAndName.find(
|
|
|
|
|
MemorySegmentType::SIGNATURES
|
|
|
|
|
);
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (signatureSegmentsIt != dataAddressSpace.memorySegmentsByTypeAndName.end()) {
|
|
|
|
|
const auto& signatureSegmentsByName = signatureSegmentsIt->second;
|
|
|
|
|
const auto signatureSegmentIt = signatureSegmentsByName.find("signatures");
|
|
|
|
|
|
|
|
|
|
if (signatureSegmentIt != signatureSegmentsByName.end()) {
|
|
|
|
|
return signatureSegmentIt->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getFuseMemorySegment() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto dataAddressSpaceIt = this->addressSpacesMappedById.find("data");
|
|
|
|
|
|
|
|
|
|
if (dataAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
const auto& dataAddressSpace = dataAddressSpaceIt->second;
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto fuseMemorySegmentsIt = dataAddressSpace.memorySegmentsByTypeAndName.find(
|
|
|
|
|
MemorySegmentType::FUSES
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
fuseMemorySegmentsIt != dataAddressSpace.memorySegmentsByTypeAndName.end()
|
|
|
|
|
&& !fuseMemorySegmentsIt->second.empty()
|
|
|
|
|
) {
|
|
|
|
|
return fuseMemorySegmentsIt->second.begin()->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<MemorySegment> TargetDescriptionFile::getLockbitsMemorySegment() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto dataAddressSpaceIt = this->addressSpacesMappedById.find("data");
|
|
|
|
|
|
|
|
|
|
if (dataAddressSpaceIt != this->addressSpacesMappedById.end()) {
|
|
|
|
|
const auto& dataAddressSpace = dataAddressSpaceIt->second;
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto lockbitsMemorySegmentsIt = dataAddressSpace.memorySegmentsByTypeAndName.find(
|
|
|
|
|
MemorySegmentType::LOCKBITS
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
lockbitsMemorySegmentsIt != dataAddressSpace.memorySegmentsByTypeAndName.end()
|
|
|
|
|
&& !lockbitsMemorySegmentsIt->second.empty()
|
|
|
|
|
) {
|
|
|
|
|
return lockbitsMemorySegmentsIt->second.begin()->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-27 20:09:15 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<RegisterGroup> TargetDescriptionFile::getCpuRegisterGroup() const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& modulesByName = this->modulesMappedByName;
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto cpuModuleIt = modulesByName.find("cpu");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (cpuModuleIt != modulesByName.end()) {
|
|
|
|
|
const auto& cpuModule = cpuModuleIt->second;
|
|
|
|
|
const auto cpuRegisterGroupIt = cpuModule.registerGroupsMappedByName.find("cpu");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (cpuRegisterGroupIt != cpuModule.registerGroupsMappedByName.end()) {
|
|
|
|
|
return cpuRegisterGroupIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<RegisterGroup> TargetDescriptionFile::getBootLoadRegisterGroup() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto bootLoadModuleIt = this->modulesMappedByName.find("boot_load");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (bootLoadModuleIt != this->modulesMappedByName.end()) {
|
|
|
|
|
const auto& bootLoadModule = bootLoadModuleIt->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
auto bootLoadRegisterGroupIt = bootLoadModule.registerGroupsMappedByName.find("boot_load");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (bootLoadRegisterGroupIt != bootLoadModule.registerGroupsMappedByName.end()) {
|
|
|
|
|
return bootLoadRegisterGroupIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<RegisterGroup> TargetDescriptionFile::getEepromRegisterGroup() const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& modulesByName = this->modulesMappedByName;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (modulesByName.find("eeprom") != modulesByName.end()) {
|
|
|
|
|
auto eepromModule = modulesByName.find("eeprom")->second;
|
|
|
|
|
auto eepromRegisterGroupIt = eepromModule.registerGroupsMappedByName.find("eeprom");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromRegisterGroupIt != eepromModule.registerGroupsMappedByName.end()) {
|
|
|
|
|
return eepromRegisterGroupIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getStatusRegister() const {
|
|
|
|
|
auto cpuRegisterGroup = this->getCpuRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (cpuRegisterGroup.has_value()) {
|
|
|
|
|
auto statusRegisterIt = cpuRegisterGroup->registersMappedByName.find("sreg");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (statusRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return statusRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getStackPointerRegister() const {
|
|
|
|
|
auto cpuRegisterGroup = this->getCpuRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (cpuRegisterGroup.has_value()) {
|
|
|
|
|
auto stackPointerRegisterIt = cpuRegisterGroup->registersMappedByName.find("sp");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (stackPointerRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return stackPointerRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getStackPointerHighRegister() const {
|
|
|
|
|
auto cpuRegisterGroup = this->getCpuRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (cpuRegisterGroup.has_value()) {
|
|
|
|
|
auto stackPointerHighRegisterIt = cpuRegisterGroup->registersMappedByName.find("sph");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (stackPointerHighRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return stackPointerHighRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getStackPointerLowRegister() const {
|
|
|
|
|
auto cpuRegisterGroup = this->getCpuRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (cpuRegisterGroup.has_value()) {
|
|
|
|
|
auto stackPointerLowRegisterIt = cpuRegisterGroup->registersMappedByName.find("spl");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (stackPointerLowRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return stackPointerLowRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getOscillatorCalibrationRegister() const {
|
|
|
|
|
auto cpuRegisterGroup = this->getCpuRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (cpuRegisterGroup.has_value()) {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& cpuRegisters = cpuRegisterGroup->registersMappedByName;
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
auto osccalRegisterIt = cpuRegisters.find("osccal");
|
|
|
|
|
if (osccalRegisterIt != cpuRegisters.end()) {
|
|
|
|
|
return osccalRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
osccalRegisterIt = cpuRegisters.find("osccal0");
|
|
|
|
|
if (osccalRegisterIt != cpuRegisters.end()) {
|
|
|
|
|
return osccalRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
osccalRegisterIt = cpuRegisters.find("osccal1");
|
|
|
|
|
if (osccalRegisterIt != cpuRegisters.end()) {
|
|
|
|
|
return osccalRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
osccalRegisterIt = cpuRegisters.find("fosccal");
|
|
|
|
|
if (osccalRegisterIt != cpuRegisters.end()) {
|
|
|
|
|
return osccalRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
osccalRegisterIt = cpuRegisters.find("sosccala");
|
|
|
|
|
if (osccalRegisterIt != cpuRegisters.end()) {
|
|
|
|
|
return osccalRegisterIt->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getSpmcsRegister() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto cpuRegisterGroup = this->getCpuRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (cpuRegisterGroup.has_value()) {
|
|
|
|
|
const auto spmcsRegisterIt = cpuRegisterGroup->registersMappedByName.find("spmcsr");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (spmcsRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return spmcsRegisterIt->second;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto bootLoadRegisterGroup = this->getBootLoadRegisterGroup();
|
|
|
|
|
|
|
|
|
|
if (bootLoadRegisterGroup.has_value()) {
|
|
|
|
|
const auto spmcsRegisterIt = bootLoadRegisterGroup->registersMappedByName.find("spmcsr");
|
|
|
|
|
|
|
|
|
|
if (spmcsRegisterIt != bootLoadRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return spmcsRegisterIt->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getSpmcRegister() const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto cpuRegisterGroup = this->getCpuRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (cpuRegisterGroup.has_value()) {
|
|
|
|
|
const auto spmcRegisterIt = cpuRegisterGroup->registersMappedByName.find("spmcr");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (spmcRegisterIt != cpuRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return spmcRegisterIt->second;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto bootLoadRegisterGroup = this->getBootLoadRegisterGroup();
|
|
|
|
|
|
|
|
|
|
if (bootLoadRegisterGroup.has_value()) {
|
|
|
|
|
const auto spmcRegisterIt = bootLoadRegisterGroup->registersMappedByName.find("spmcr");
|
|
|
|
|
|
|
|
|
|
if (spmcRegisterIt != bootLoadRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return spmcRegisterIt->second;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getEepromAddressRegister() const {
|
|
|
|
|
auto eepromRegisterGroup = this->getEepromRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromRegisterGroup.has_value()) {
|
|
|
|
|
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eear");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return eepromAddressRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getEepromAddressLowRegister() const {
|
|
|
|
|
auto eepromRegisterGroup = this->getEepromRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromRegisterGroup.has_value()) {
|
|
|
|
|
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eearl");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return eepromAddressRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getEepromAddressHighRegister() const {
|
|
|
|
|
auto eepromRegisterGroup = this->getEepromRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromRegisterGroup.has_value()) {
|
|
|
|
|
auto eepromAddressRegisterIt = eepromRegisterGroup->registersMappedByName.find("eearh");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromAddressRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return eepromAddressRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getEepromDataRegister() const {
|
|
|
|
|
auto eepromRegisterGroup = this->getEepromRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromRegisterGroup.has_value()) {
|
|
|
|
|
auto eepromDataRegisterIt = eepromRegisterGroup->registersMappedByName.find("eedr");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromDataRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return eepromDataRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
std::optional<Register> TargetDescriptionFile::getEepromControlRegister() const {
|
|
|
|
|
auto eepromRegisterGroup = this->getEepromRegisterGroup();
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromRegisterGroup.has_value()) {
|
|
|
|
|
auto eepromControlRegisterIt = eepromRegisterGroup->registersMappedByName.find("eecr");
|
2021-06-06 19:14:36 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromControlRegisterIt != eepromRegisterGroup->registersMappedByName.end()) {
|
|
|
|
|
return eepromControlRegisterIt->second;
|
|
|
|
|
}
|
2021-06-06 19:14:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
void TargetDescriptionFile::loadDebugWireAndJtagTargetParameters(TargetParameters& targetParameters) const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
|
|
|
|
const auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
// OCD attributes can be found in property groups
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto ocdPropertyGroupIt = propertyGroups.find("ocd");
|
|
|
|
|
if (ocdPropertyGroupIt != propertyGroups.end()) {
|
|
|
|
|
const auto& ocdProperties = ocdPropertyGroupIt->second.propertiesMappedByName;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto ocdRevisionPropertyIt = ocdProperties.find("ocd_revision");
|
|
|
|
|
if (ocdRevisionPropertyIt != ocdProperties.end()) {
|
|
|
|
|
targetParameters.ocdRevision = ocdRevisionPropertyIt->second.value.toUShort(nullptr, 10);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto ocdDataRegPropertyIt = ocdProperties.find("ocd_datareg");
|
|
|
|
|
if (ocdDataRegPropertyIt != ocdProperties.end()) {
|
|
|
|
|
targetParameters.ocdDataRegister = ocdDataRegPropertyIt->second.value.toUShort(nullptr, 16);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto spmcsRegister = this->getSpmcsRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (spmcsRegister.has_value()) {
|
|
|
|
|
targetParameters.spmcRegisterStartAddress = spmcsRegister->offset;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto spmcRegister = this->getSpmcRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (spmcRegister.has_value()) {
|
|
|
|
|
targetParameters.spmcRegisterStartAddress = spmcRegister->offset;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto osccalRegister = this->getOscillatorCalibrationRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (osccalRegister.has_value()) {
|
|
|
|
|
targetParameters.osccalAddress = osccalRegister->offset;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto eepromAddressRegister = this->getEepromAddressRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromAddressRegister.has_value()) {
|
|
|
|
|
targetParameters.eepromAddressRegisterLow = eepromAddressRegister->offset;
|
|
|
|
|
targetParameters.eepromAddressRegisterHigh = (eepromAddressRegister->size == 2)
|
|
|
|
|
? eepromAddressRegister->offset + 1 : eepromAddressRegister->offset;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto eepromAddressLowRegister = this->getEepromAddressLowRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromAddressLowRegister.has_value()) {
|
|
|
|
|
targetParameters.eepromAddressRegisterLow = eepromAddressLowRegister->offset;
|
|
|
|
|
auto eepromAddressHighRegister = this->getEepromAddressHighRegister();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromAddressHighRegister.has_value()) {
|
|
|
|
|
targetParameters.eepromAddressRegisterHigh = eepromAddressHighRegister->offset;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} else {
|
|
|
|
|
targetParameters.eepromAddressRegisterHigh = eepromAddressLowRegister->offset;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto eepromDataRegister = this->getEepromDataRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromDataRegister.has_value()) {
|
|
|
|
|
targetParameters.eepromDataRegisterAddress = eepromDataRegister->offset;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto eepromControlRegister = this->getEepromControlRegister();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (eepromControlRegister.has_value()) {
|
|
|
|
|
targetParameters.eepromControlRegisterAddress = eepromControlRegister->offset;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
void TargetDescriptionFile::loadPdiTargetParameters(TargetParameters& targetParameters) const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
|
|
|
|
const auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto pdiPropertyGroupIt = propertyGroups.find("pdi_interface");
|
|
|
|
|
if (pdiPropertyGroupIt == propertyGroups.end()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto& pdiInterfaceProperties = pdiPropertyGroupIt->second.propertiesMappedByName;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto appOffsetPropertyIt = pdiInterfaceProperties.find("app_section_offset");
|
|
|
|
|
if (appOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.appSectionPdiOffset = appOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto bootOffsetPropertyIt = pdiInterfaceProperties.find("boot_section_offset");
|
|
|
|
|
if (bootOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.bootSectionPdiOffset = bootOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto dataOffsetPropertyIt = pdiInterfaceProperties.find("datamem_offset");
|
|
|
|
|
if (dataOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.ramPdiOffset = dataOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto eepromOffsetPropertyIt = pdiInterfaceProperties.find("eeprom_offset");
|
|
|
|
|
if (eepromOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.eepromPdiOffset = eepromOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto userSigOffsetPropertyIt = pdiInterfaceProperties.find("user_signatures_offset");
|
|
|
|
|
if (userSigOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.userSignaturesPdiOffset = userSigOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto prodSigOffsetPropertyIt = pdiInterfaceProperties.find("prod_signatures_offset");
|
|
|
|
|
if (prodSigOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.productSignaturesPdiOffset = prodSigOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto fuseRegOffsetPropertyIt = pdiInterfaceProperties.find("fuse_registers_offset");
|
|
|
|
|
if (fuseRegOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.fuseRegistersPdiOffset = fuseRegOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto lockRegOffsetPropertyIt = pdiInterfaceProperties.find("lock_registers_offset");
|
|
|
|
|
if (lockRegOffsetPropertyIt != pdiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.lockRegistersPdiOffset = lockRegOffsetPropertyIt->second.value.toUInt(nullptr, 16);
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto nvmPeripheralModuleIt = peripheralModules.find("nvm");
|
|
|
|
|
if (nvmPeripheralModuleIt != peripheralModules.end()) {
|
|
|
|
|
const auto& nvmModule = nvmPeripheralModuleIt->second;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto nvmInstanceIt = nvmModule.instancesMappedByName.find("nvm");
|
|
|
|
|
if (nvmInstanceIt != nvmModule.instancesMappedByName.end()) {
|
|
|
|
|
const auto& nvmInstance = nvmInstanceIt->second;
|
|
|
|
|
|
|
|
|
|
const auto nvmRegisterGroupIt = nvmInstance.registerGroupsMappedByName.find("nvm");
|
|
|
|
|
if (nvmRegisterGroupIt != nvmInstance.registerGroupsMappedByName.end()) {
|
|
|
|
|
targetParameters.nvmModuleBaseAddress = nvmRegisterGroupIt->second.offset;
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-03 22:16:21 +00:00
|
|
|
}
|
2022-06-02 23:05:38 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto mcuPeripheralModuleIt = peripheralModules.find("mcu");
|
|
|
|
|
if (mcuPeripheralModuleIt != peripheralModules.end()) {
|
|
|
|
|
const auto& mcuModule = mcuPeripheralModuleIt->second;
|
2022-06-02 23:05:38 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto mcuInstanceIt = mcuModule.instancesMappedByName.find("mcu");
|
|
|
|
|
if (mcuInstanceIt != mcuModule.instancesMappedByName.end()) {
|
|
|
|
|
const auto& mcuInstance = mcuInstanceIt->second;
|
2022-06-02 23:05:38 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto mcuRegisterGroupIt = mcuInstance.registerGroupsMappedByName.find("mcu");
|
|
|
|
|
if (mcuRegisterGroupIt != mcuInstance.registerGroupsMappedByName.end()) {
|
|
|
|
|
targetParameters.mcuModuleBaseAddress = mcuRegisterGroupIt->second.offset;
|
2022-06-02 23:05:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
void TargetDescriptionFile::loadUpdiTargetParameters(TargetParameters& targetParameters) const {
|
2022-03-02 22:42:55 +00:00
|
|
|
const auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
|
|
|
|
const auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto& modulesByName = this->getModulesMappedByName();
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto nvmCtrlPeripheralModuleIt = peripheralModules.find("nvmctrl");
|
|
|
|
|
if (nvmCtrlPeripheralModuleIt != peripheralModules.end()) {
|
|
|
|
|
const auto& nvmCtrlModule = nvmCtrlPeripheralModuleIt->second;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto nvmCtrlInstanceIt = nvmCtrlModule.instancesMappedByName.find("nvmctrl");
|
|
|
|
|
if (nvmCtrlInstanceIt != nvmCtrlModule.instancesMappedByName.end()) {
|
|
|
|
|
const auto& nvmCtrlInstance = nvmCtrlInstanceIt->second;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto nvmCtrlRegisterGroupIt = nvmCtrlInstance.registerGroupsMappedByName.find("nvmctrl");
|
|
|
|
|
if (nvmCtrlRegisterGroupIt != nvmCtrlInstance.registerGroupsMappedByName.end()) {
|
|
|
|
|
targetParameters.nvmModuleBaseAddress = nvmCtrlRegisterGroupIt->second.offset;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto updiPropertyGroupIt = propertyGroups.find("updi_interface");
|
|
|
|
|
if (updiPropertyGroupIt != propertyGroups.end()) {
|
|
|
|
|
const auto& updiInterfaceProperties = updiPropertyGroupIt->second.propertiesMappedByName;
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto ocdBaseAddressPropertyIt = updiInterfaceProperties.find("ocd_base_addr");
|
|
|
|
|
if (ocdBaseAddressPropertyIt != updiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.ocdModuleAddress = ocdBaseAddressPropertyIt->second.value.toUShort(nullptr, 16);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto progMemOffsetPropertyIt = updiInterfaceProperties.find("progmem_offset");
|
|
|
|
|
if (progMemOffsetPropertyIt != updiInterfaceProperties.end()) {
|
|
|
|
|
targetParameters.programMemoryUpdiStartAddress = progMemOffsetPropertyIt->second.value.toUInt(
|
|
|
|
|
nullptr,
|
|
|
|
|
16
|
|
|
|
|
);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto signatureMemorySegment = this->getSignatureMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (signatureMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.signatureSegmentStartAddress = signatureMemorySegment->startAddress;
|
|
|
|
|
targetParameters.signatureSegmentSize = signatureMemorySegment->size;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto fuseMemorySegment = this->getFuseMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (fuseMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.fuseSegmentStartAddress = fuseMemorySegment->startAddress;
|
|
|
|
|
targetParameters.fuseSegmentSize = fuseMemorySegment->size;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto lockbitsMemorySegment = this->getLockbitsMemorySegment();
|
2022-02-05 15:32:08 +00:00
|
|
|
if (lockbitsMemorySegment.has_value()) {
|
|
|
|
|
targetParameters.lockbitsSegmentStartAddress = lockbitsMemorySegment->startAddress;
|
|
|
|
|
}
|
2021-07-06 20:07:41 +01:00
|
|
|
}
|
|
|
|
|
}
|