Moved AVR8 TDF data extraction into AVR8 TDF class.
This commit is contained in:
@@ -138,7 +138,7 @@ void EdbgAvr8Interface::setDebugWireAndJtagParameters() {
|
|||||||
*
|
*
|
||||||
* It *doesn't* seem to apply to the SPMCR address.
|
* It *doesn't* seem to apply to the SPMCR address.
|
||||||
*/
|
*/
|
||||||
auto mappedIoStartAddress = this->targetParameters.mappedIoStartAddress.value_or(0);
|
auto mappedIoStartAddress = this->targetParameters.mappedIoSegmentStartAddress.value_or(0);
|
||||||
|
|
||||||
if (this->targetParameters.ocdDataRegister.has_value()) {
|
if (this->targetParameters.ocdDataRegister.has_value()) {
|
||||||
Logger::debug("Setting DEVICE_OCD_DATA_REGISTER AVR8 parameter");
|
Logger::debug("Setting DEVICE_OCD_DATA_REGISTER AVR8 parameter");
|
||||||
|
|||||||
@@ -32,497 +32,13 @@ void Avr8::loadTargetDescriptionFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Avr8::initFromTargetDescriptionFile() {
|
void Avr8::initFromTargetDescriptionFile() {
|
||||||
|
assert(this->targetDescriptionFile.has_value());
|
||||||
this->name = this->targetDescriptionFile->getTargetName();
|
this->name = this->targetDescriptionFile->getTargetName();
|
||||||
this->family = this->targetDescriptionFile->getFamily();
|
this->family = this->targetDescriptionFile->getFamily();
|
||||||
|
|
||||||
this->loadTargetParameters();
|
this->targetParameters = this->targetDescriptionFile->getTargetParameters();
|
||||||
this->loadPadDescriptors();
|
this->padDescriptorsByName = this->targetDescriptionFile->getPadDescriptorsMappedByName();
|
||||||
this->loadTargetVariants();
|
this->targetVariantsById = this->targetDescriptionFile->getVariantsMappedById();
|
||||||
}
|
|
||||||
|
|
||||||
void Avr8::loadTargetParameters() {
|
|
||||||
assert(this->targetDescriptionFile.has_value());
|
|
||||||
auto& peripheralModules = this->targetDescriptionFile->getPeripheralModulesMappedByName();
|
|
||||||
this->targetParameters = TargetParameters();
|
|
||||||
auto& propertyGroups = this->targetDescriptionFile->getPropertyGroupsMappedByName();
|
|
||||||
|
|
||||||
auto flashMemorySegment = this->targetDescriptionFile->getFlashMemorySegment();
|
|
||||||
if (flashMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->flashSize = flashMemorySegment->size;
|
|
||||||
this->targetParameters->flashStartAddress = flashMemorySegment->startAddress;
|
|
||||||
|
|
||||||
if (flashMemorySegment->pageSize.has_value()) {
|
|
||||||
this->targetParameters->flashPageSize = flashMemorySegment->pageSize.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ramMemorySegment = this->targetDescriptionFile->getRamMemorySegment();
|
|
||||||
if (ramMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->ramSize = ramMemorySegment->size;
|
|
||||||
this->targetParameters->ramStartAddress = ramMemorySegment->startAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ioMemorySegment = this->targetDescriptionFile->getIoMemorySegment();
|
|
||||||
if (ioMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->mappedIoStartAddress = ioMemorySegment->startAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto registerMemorySegment = this->targetDescriptionFile->getRegisterMemorySegment();
|
|
||||||
if (registerMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->gpRegisterSize = registerMemorySegment->size;
|
|
||||||
this->targetParameters->gpRegisterStartAddress = registerMemorySegment->startAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto eepromMemorySegment = this->targetDescriptionFile->getEepromMemorySegment();
|
|
||||||
if (eepromMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->eepromSize = eepromMemorySegment->size;
|
|
||||||
this->targetParameters->eepromStartAddress = eepromMemorySegment->startAddress;
|
|
||||||
|
|
||||||
if (eepromMemorySegment->pageSize.has_value()) {
|
|
||||||
this->targetParameters->eepromPageSize = eepromMemorySegment->pageSize.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto firstBootSectionMemorySegment = this->targetDescriptionFile->getFirstBootSectionMemorySegment();
|
|
||||||
if (firstBootSectionMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->bootSectionStartAddress = firstBootSectionMemorySegment->startAddress / 2;
|
|
||||||
this->targetParameters->bootSectionSize = firstBootSectionMemorySegment->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint32_t cpuRegistersOffset = 0;
|
|
||||||
|
|
||||||
if (peripheralModules.contains("cpu")) {
|
|
||||||
auto cpuPeripheralModule = peripheralModules.at("cpu");
|
|
||||||
|
|
||||||
if (cpuPeripheralModule.instancesMappedByName.contains("cpu")) {
|
|
||||||
auto cpuInstance = cpuPeripheralModule.instancesMappedByName.at("cpu");
|
|
||||||
|
|
||||||
if (cpuInstance.registerGroupsMappedByName.contains("cpu")) {
|
|
||||||
cpuRegistersOffset = cpuInstance.registerGroupsMappedByName.at("cpu").offset.value_or(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto statusRegister = this->targetDescriptionFile->getStatusRegister();
|
|
||||||
if (statusRegister.has_value()) {
|
|
||||||
this->targetParameters->statusRegisterStartAddress = cpuRegistersOffset + statusRegister->offset;
|
|
||||||
this->targetParameters->statusRegisterSize = statusRegister->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto stackPointerRegister = this->targetDescriptionFile->getStackPointerRegister();
|
|
||||||
if (stackPointerRegister.has_value()) {
|
|
||||||
this->targetParameters->stackPointerRegisterLowAddress = cpuRegistersOffset + stackPointerRegister->offset;
|
|
||||||
this->targetParameters->stackPointerRegisterSize = stackPointerRegister->size;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Sometimes the SP register is split into two register nodes, one for low, the other for high
|
|
||||||
auto stackPointerLowRegister = this->targetDescriptionFile->getStackPointerLowRegister();
|
|
||||||
auto stackPointerHighRegister = this->targetDescriptionFile->getStackPointerHighRegister();
|
|
||||||
|
|
||||||
if (stackPointerLowRegister.has_value()) {
|
|
||||||
this->targetParameters->stackPointerRegisterLowAddress = cpuRegistersOffset
|
|
||||||
+ stackPointerLowRegister->offset;
|
|
||||||
this->targetParameters->stackPointerRegisterSize = stackPointerLowRegister->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stackPointerHighRegister.has_value()) {
|
|
||||||
this->targetParameters->stackPointerRegisterSize =
|
|
||||||
this->targetParameters->stackPointerRegisterSize.has_value() ?
|
|
||||||
this->targetParameters->stackPointerRegisterSize.value() + stackPointerHighRegister->size :
|
|
||||||
stackPointerHighRegister->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto supportedPhysicalInterfaces = this->targetDescriptionFile->getSupportedDebugPhysicalInterfaces();
|
|
||||||
|
|
||||||
if (supportedPhysicalInterfaces.contains(PhysicalInterface::DEBUG_WIRE)
|
|
||||||
|| supportedPhysicalInterfaces.contains(PhysicalInterface::JTAG)) {
|
|
||||||
this->loadDebugWireAndJtagTargetParameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportedPhysicalInterfaces.contains(PhysicalInterface::PDI)) {
|
|
||||||
this->loadPdiTargetParameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportedPhysicalInterfaces.contains(PhysicalInterface::UPDI)) {
|
|
||||||
this->loadUpdiTargetParameters();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avr8::loadDebugWireAndJtagTargetParameters() {
|
|
||||||
auto& peripheralModules = this->targetDescriptionFile->getPeripheralModulesMappedByName();
|
|
||||||
auto& propertyGroups = this->targetDescriptionFile->getPropertyGroupsMappedByName();
|
|
||||||
|
|
||||||
// OCD attributes can be found in property groups
|
|
||||||
if (propertyGroups.contains("ocd")) {
|
|
||||||
auto& ocdProperties = propertyGroups.at("ocd").propertiesMappedByName;
|
|
||||||
|
|
||||||
if (ocdProperties.find("ocd_revision") != ocdProperties.end()) {
|
|
||||||
this->targetParameters->ocdRevision = ocdProperties.find("ocd_revision")
|
|
||||||
->second.value.toUShort(nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ocdProperties.find("ocd_datareg") != ocdProperties.end()) {
|
|
||||||
this->targetParameters->ocdDataRegister = ocdProperties.find("ocd_datareg")
|
|
||||||
->second.value.toUShort(nullptr, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto spmcsRegister = this->targetDescriptionFile->getSpmcsRegister();
|
|
||||||
if (spmcsRegister.has_value()) {
|
|
||||||
this->targetParameters->spmcRegisterStartAddress = spmcsRegister->offset;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
auto spmcRegister = this->targetDescriptionFile->getSpmcRegister();
|
|
||||||
if (spmcRegister.has_value()) {
|
|
||||||
this->targetParameters->spmcRegisterStartAddress = spmcRegister->offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto osccalRegister = this->targetDescriptionFile->getOscillatorCalibrationRegister();
|
|
||||||
if (osccalRegister.has_value()) {
|
|
||||||
this->targetParameters->osccalAddress = osccalRegister->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto eepromAddressRegister = this->targetDescriptionFile->getEepromAddressRegister();
|
|
||||||
if (eepromAddressRegister.has_value()) {
|
|
||||||
this->targetParameters->eepromAddressRegisterLow = eepromAddressRegister->offset;
|
|
||||||
this->targetParameters->eepromAddressRegisterHigh = (eepromAddressRegister->size == 2)
|
|
||||||
? eepromAddressRegister->offset + 1 : eepromAddressRegister->offset;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
auto eepromAddressLowRegister = this->targetDescriptionFile->getEepromAddressLowRegister();
|
|
||||||
if (eepromAddressLowRegister.has_value()) {
|
|
||||||
this->targetParameters->eepromAddressRegisterLow = eepromAddressLowRegister->offset;
|
|
||||||
auto eepromAddressHighRegister = this->targetDescriptionFile->getEepromAddressHighRegister();
|
|
||||||
|
|
||||||
if (eepromAddressHighRegister.has_value()) {
|
|
||||||
this->targetParameters->eepromAddressRegisterHigh = eepromAddressHighRegister->offset;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this->targetParameters->eepromAddressRegisterHigh = eepromAddressLowRegister->offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto eepromDataRegister = this->targetDescriptionFile->getEepromDataRegister();
|
|
||||||
if (eepromDataRegister.has_value()) {
|
|
||||||
this->targetParameters->eepromDataRegisterAddress = eepromDataRegister->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto eepromControlRegister = this->targetDescriptionFile->getEepromControlRegister();
|
|
||||||
if (eepromControlRegister.has_value()) {
|
|
||||||
this->targetParameters->eepromControlRegisterAddress = eepromControlRegister->offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avr8::loadPdiTargetParameters() {
|
|
||||||
auto& peripheralModules = this->targetDescriptionFile->getPeripheralModulesMappedByName();
|
|
||||||
auto& propertyGroups = this->targetDescriptionFile->getPropertyGroupsMappedByName();
|
|
||||||
|
|
||||||
if (propertyGroups.contains("pdi_interface")) {
|
|
||||||
auto& pdiInterfaceProperties = propertyGroups.at("pdi_interface").propertiesMappedByName;
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("app_section_offset")) {
|
|
||||||
this->targetParameters->appSectionPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("app_section_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("boot_section_offset")) {
|
|
||||||
this->targetParameters->bootSectionPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("boot_section_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("datamem_offset")) {
|
|
||||||
this->targetParameters->ramPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("datamem_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("eeprom_offset")) {
|
|
||||||
this->targetParameters->eepromPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("eeprom_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("user_signatures_offset")) {
|
|
||||||
this->targetParameters->userSignaturesPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("user_signatures_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("prod_signatures_offset")) {
|
|
||||||
this->targetParameters->productSignaturesPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("prod_signatures_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("fuse_registers_offset")) {
|
|
||||||
this->targetParameters->fuseRegistersPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("fuse_registers_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdiInterfaceProperties.contains("lock_registers_offset")) {
|
|
||||||
this->targetParameters->lockRegistersPdiOffset = pdiInterfaceProperties
|
|
||||||
.at("lock_registers_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (peripheralModules.contains("nvm")) {
|
|
||||||
auto& nvmModule = peripheralModules.at("nvm");
|
|
||||||
|
|
||||||
if (nvmModule.instancesMappedByName.contains("nvm")) {
|
|
||||||
auto& nvmInstance = nvmModule.instancesMappedByName.at("nvm");
|
|
||||||
|
|
||||||
if (nvmInstance.registerGroupsMappedByName.contains("nvm")) {
|
|
||||||
this->targetParameters->nvmBaseAddress = nvmInstance.registerGroupsMappedByName.at("nvm").offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avr8::loadUpdiTargetParameters() {
|
|
||||||
auto& propertyGroups = this->targetDescriptionFile->getPropertyGroupsMappedByName();
|
|
||||||
auto& peripheralModules = this->targetDescriptionFile->getPeripheralModulesMappedByName();
|
|
||||||
auto modulesByName = this->targetDescriptionFile->getModulesMappedByName();
|
|
||||||
|
|
||||||
if (peripheralModules.contains("nvmctrl")) {
|
|
||||||
auto& nvmCtrlModule = peripheralModules.at("nvmctrl");
|
|
||||||
|
|
||||||
if (nvmCtrlModule.instancesMappedByName.contains("nvmctrl")) {
|
|
||||||
auto& nvmCtrlInstance = nvmCtrlModule.instancesMappedByName.at("nvmctrl");
|
|
||||||
|
|
||||||
if (nvmCtrlInstance.registerGroupsMappedByName.contains("nvmctrl")) {
|
|
||||||
this->targetParameters->nvmBaseAddress = nvmCtrlInstance.registerGroupsMappedByName.at("nvmctrl").offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyGroups.contains("updi_interface")) {
|
|
||||||
auto& updiInterfaceProperties = propertyGroups.at("updi_interface").propertiesMappedByName;
|
|
||||||
|
|
||||||
if (updiInterfaceProperties.contains("ocd_base_addr")) {
|
|
||||||
this->targetParameters->ocdModuleAddress = updiInterfaceProperties
|
|
||||||
.at("ocd_base_addr").value.toUShort(nullptr, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updiInterfaceProperties.contains("progmem_offset")) {
|
|
||||||
this->targetParameters->programMemoryUpdiStartAddress = updiInterfaceProperties
|
|
||||||
.at("progmem_offset").value.toUInt(nullptr, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto signatureMemorySegment = this->targetDescriptionFile->getSignatureMemorySegment();
|
|
||||||
if (signatureMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->signatureSegmentStartAddress = signatureMemorySegment->startAddress;
|
|
||||||
this->targetParameters->signatureSegmentSize = signatureMemorySegment->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto fuseMemorySegment = this->targetDescriptionFile->getFuseMemorySegment();
|
|
||||||
if (fuseMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->fuseSegmentStartAddress = fuseMemorySegment->startAddress;
|
|
||||||
this->targetParameters->fuseSegmentSize = fuseMemorySegment->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lockbitsMemorySegment = this->targetDescriptionFile->getLockbitsMemorySegment();
|
|
||||||
if (lockbitsMemorySegment.has_value()) {
|
|
||||||
this->targetParameters->lockbitsSegmentStartAddress = lockbitsMemorySegment->startAddress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avr8::loadPadDescriptors() {
|
|
||||||
/*
|
|
||||||
* Every port address we extract from the target description will be stored in portAddresses, so that
|
|
||||||
* we can extract the start (min) and end (max) for the target's IO port address
|
|
||||||
* range (TargetParameters::ioPortAddressRangeStart & TargetParameters::ioPortAddressRangeEnd)
|
|
||||||
*/
|
|
||||||
std::vector<std::uint32_t> portAddresses;
|
|
||||||
|
|
||||||
auto& modules = this->targetDescriptionFile->getModulesMappedByName();
|
|
||||||
auto portModule = (modules.contains("port")) ? std::optional(modules.find("port")->second) : std::nullopt;
|
|
||||||
auto& peripheralModules = this->targetDescriptionFile->getPeripheralModulesMappedByName();
|
|
||||||
|
|
||||||
if (peripheralModules.contains("port")) {
|
|
||||||
auto portPeripheralModule = peripheralModules.find("port")->second;
|
|
||||||
|
|
||||||
for (const auto& [instanceName, instance] : portPeripheralModule.instancesMappedByName) {
|
|
||||||
if (instanceName.find("port") == 0) {
|
|
||||||
auto portPeripheralRegisterGroup = (portPeripheralModule.registerGroupsMappedByName.contains(instanceName)) ?
|
|
||||||
std::optional(portPeripheralModule.registerGroupsMappedByName.find(instanceName)->second) :
|
|
||||||
std::nullopt;
|
|
||||||
|
|
||||||
for (const auto& signal : instance.instanceSignals) {
|
|
||||||
if (!signal.index.has_value()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto padDescriptor = PadDescriptor();
|
|
||||||
padDescriptor.name = signal.padName;
|
|
||||||
padDescriptor.gpioPinNumber = signal.index.value();
|
|
||||||
|
|
||||||
if (portModule.has_value() && portModule->registerGroupsMappedByName.contains(instanceName)) {
|
|
||||||
// We have register information for this port
|
|
||||||
auto registerGroup = portModule->registerGroupsMappedByName.find(instanceName)->second;
|
|
||||||
|
|
||||||
for (const auto& [registerName, portRegister] : registerGroup.registersMappedByName) {
|
|
||||||
if (registerName.find("port") == 0) {
|
|
||||||
// This is the data register for the port
|
|
||||||
padDescriptor.gpioPortSetAddress = portRegister.offset;
|
|
||||||
padDescriptor.gpioPortClearAddress = portRegister.offset;
|
|
||||||
|
|
||||||
} else if (registerName.find("pin") == 0) {
|
|
||||||
// This is the input data register for the port
|
|
||||||
padDescriptor.gpioPortInputAddress = portRegister.offset;
|
|
||||||
|
|
||||||
} else if (registerName.find("ddr") == 0) {
|
|
||||||
// This is the data direction register for the port
|
|
||||||
padDescriptor.ddrSetAddress = portRegister.offset;
|
|
||||||
padDescriptor.ddrClearAddress = portRegister.offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (portModule.has_value() && portModule->registerGroupsMappedByName.contains("port")) {
|
|
||||||
// We have generic register information for all ports on the target
|
|
||||||
auto registerGroup = portModule->registerGroupsMappedByName.find("port")->second;
|
|
||||||
|
|
||||||
for (const auto& [registerName, portRegister] : registerGroup.registersMappedByName) {
|
|
||||||
if (registerName.find("outset") == 0) {
|
|
||||||
// Include the port register offset
|
|
||||||
padDescriptor.gpioPortSetAddress = (portPeripheralRegisterGroup.has_value()
|
|
||||||
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
|
||||||
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
|
||||||
|
|
||||||
padDescriptor.gpioPortSetAddress = padDescriptor.gpioPortSetAddress.value()
|
|
||||||
+ portRegister.offset;
|
|
||||||
|
|
||||||
} else if (registerName.find("outclr") == 0) {
|
|
||||||
padDescriptor.gpioPortClearAddress = (portPeripheralRegisterGroup.has_value()
|
|
||||||
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
|
||||||
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
|
||||||
|
|
||||||
padDescriptor.gpioPortClearAddress = padDescriptor.gpioPortClearAddress.value()
|
|
||||||
+ portRegister.offset;
|
|
||||||
|
|
||||||
} else if (registerName.find("dirset") == 0) {
|
|
||||||
padDescriptor.ddrSetAddress = (portPeripheralRegisterGroup.has_value()
|
|
||||||
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
|
||||||
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
|
||||||
|
|
||||||
padDescriptor.ddrSetAddress = padDescriptor.ddrSetAddress.value()
|
|
||||||
+ portRegister.offset;
|
|
||||||
|
|
||||||
} else if (registerName.find("dirclr") == 0) {
|
|
||||||
padDescriptor.ddrClearAddress = (portPeripheralRegisterGroup.has_value()
|
|
||||||
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
|
||||||
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
|
||||||
|
|
||||||
padDescriptor.ddrClearAddress = padDescriptor.ddrClearAddress.value()
|
|
||||||
+ portRegister.offset;
|
|
||||||
|
|
||||||
} else if (registerName == "in") {
|
|
||||||
padDescriptor.gpioPortInputAddress = (portPeripheralRegisterGroup.has_value()
|
|
||||||
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
|
||||||
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
|
||||||
|
|
||||||
padDescriptor.gpioPortInputAddress = padDescriptor.gpioPortInputAddress.value()
|
|
||||||
+ portRegister.offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (padDescriptor.gpioPortSetAddress.has_value()) {
|
|
||||||
portAddresses.push_back(padDescriptor.gpioPortSetAddress.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (padDescriptor.gpioPortClearAddress.has_value()) {
|
|
||||||
portAddresses.push_back(padDescriptor.gpioPortClearAddress.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (padDescriptor.ddrSetAddress.has_value()) {
|
|
||||||
portAddresses.push_back(padDescriptor.ddrSetAddress.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (padDescriptor.ddrClearAddress.has_value()) {
|
|
||||||
portAddresses.push_back(padDescriptor.ddrClearAddress.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
this->padDescriptorsByName.insert(std::pair(padDescriptor.name, padDescriptor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Move this into getTargetParameters()
|
|
||||||
if (!portAddresses.empty()) {
|
|
||||||
this->targetParameters->ioPortAddressRangeStart = *std::min_element(portAddresses.begin(), portAddresses.end());
|
|
||||||
this->targetParameters->ioPortAddressRangeEnd = *std::max_element(portAddresses.begin(), portAddresses.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avr8::loadTargetVariants() {
|
|
||||||
auto tdVariants = this->targetDescriptionFile->getVariants();
|
|
||||||
auto tdPinoutsByName = this->targetDescriptionFile->getPinoutsMappedByName();
|
|
||||||
auto& modules = this->targetDescriptionFile->getModulesMappedByName();
|
|
||||||
|
|
||||||
for (const auto& tdVariant : tdVariants) {
|
|
||||||
if (tdVariant.disabled) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto targetVariant = TargetVariant();
|
|
||||||
targetVariant.id = static_cast<int>(this->targetVariantsById.size());
|
|
||||||
targetVariant.name = tdVariant.name;
|
|
||||||
targetVariant.packageName = tdVariant.package;
|
|
||||||
|
|
||||||
if (tdVariant.package.find("QFP") == 0 || tdVariant.package.find("TQFP") == 0) {
|
|
||||||
targetVariant.package = TargetPackage::QFP;
|
|
||||||
|
|
||||||
} else if (tdVariant.package.find("PDIP") == 0 || tdVariant.package.find("DIP") == 0) {
|
|
||||||
targetVariant.package = TargetPackage::DIP;
|
|
||||||
|
|
||||||
} else if (tdVariant.package.find("QFN") == 0 || tdVariant.package.find("VQFN") == 0) {
|
|
||||||
targetVariant.package = TargetPackage::QFN;
|
|
||||||
|
|
||||||
} else if (tdVariant.package.find("SOIC") == 0) {
|
|
||||||
targetVariant.package = TargetPackage::SOIC;
|
|
||||||
|
|
||||||
} else if (tdVariant.package.find("SSOP") == 0) {
|
|
||||||
targetVariant.package = TargetPackage::SSOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tdPinoutsByName.contains(tdVariant.pinoutName)) {
|
|
||||||
// Missing pinouts in the target description file
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto tdPinout = tdPinoutsByName.find(tdVariant.pinoutName)->second;
|
|
||||||
for (const auto& tdPin : tdPinout.pins) {
|
|
||||||
auto targetPin = TargetPinDescriptor();
|
|
||||||
targetPin.name = tdPin.pad;
|
|
||||||
targetPin.padName = tdPin.pad;
|
|
||||||
targetPin.number = tdPin.position;
|
|
||||||
|
|
||||||
// TODO: REMOVE THIS:
|
|
||||||
if (tdPin.pad.find("vcc") == 0
|
|
||||||
|| tdPin.pad.find("avcc") == 0
|
|
||||||
|| tdPin.pad.find("aref") == 0
|
|
||||||
|| tdPin.pad.find("avdd") == 0
|
|
||||||
|| tdPin.pad.find("vdd") == 0
|
|
||||||
) {
|
|
||||||
targetPin.type = TargetPinType::VCC;
|
|
||||||
|
|
||||||
} else if (tdPin.pad.find("gnd") == 0) {
|
|
||||||
targetPin.type = TargetPinType::GND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->padDescriptorsByName.contains(targetPin.padName)) {
|
|
||||||
auto& pad = this->padDescriptorsByName.at(targetPin.padName);
|
|
||||||
if (pad.gpioPortSetAddress.has_value() && pad.ddrSetAddress.has_value()) {
|
|
||||||
targetPin.type = TargetPinType::GPIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
targetVariant.pinDescriptorsByNumber.insert(std::pair(targetPin.number, targetPin));
|
|
||||||
}
|
|
||||||
|
|
||||||
this->targetVariantsById.insert(std::pair(targetVariant.id, targetVariant));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetSignature Avr8::getId() {
|
TargetSignature Avr8::getId() {
|
||||||
@@ -981,26 +497,20 @@ void Avr8::setPinState(int variantId, const TargetPinDescriptor& pinDescriptor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Avr8::memoryAddressRangeClashesWithIoPortRegisters(TargetMemoryType memoryType, std::uint32_t startAddress, std::uint32_t endAddress) {
|
bool Avr8::memoryAddressRangeClashesWithIoPortRegisters(
|
||||||
|
TargetMemoryType memoryType,
|
||||||
|
std::uint32_t startAddress,
|
||||||
|
std::uint32_t endAddress
|
||||||
|
) {
|
||||||
auto& targetParameters = this->targetParameters.value();
|
auto& targetParameters = this->targetParameters.value();
|
||||||
|
if (targetParameters.mappedIoSegmentStartAddress.has_value() && targetParameters.mappedIoSegmentSize.has_value()) {
|
||||||
|
auto mappedIoSegmentStart = targetParameters.mappedIoSegmentStartAddress.value();
|
||||||
|
auto mappedIoSegmentEnd = mappedIoSegmentStart + targetParameters.mappedIoSegmentSize.value();
|
||||||
|
|
||||||
/*
|
return (startAddress >= mappedIoSegmentStart && startAddress <= mappedIoSegmentEnd)
|
||||||
* We're making an assumption here; that all IO port addresses for all AVR8 targets are aligned. I have no idea
|
|| (endAddress >= mappedIoSegmentStart && endAddress <= mappedIoSegmentEnd)
|
||||||
* how well this will hold.
|
|| (startAddress <= mappedIoSegmentStart && endAddress >= mappedIoSegmentStart)
|
||||||
*
|
;
|
||||||
* If they're not aligned, this function may report false positives.
|
|
||||||
*/
|
|
||||||
if (targetParameters.ioPortAddressRangeStart.has_value() && targetParameters.ioPortAddressRangeEnd.has_value()) {
|
|
||||||
return (
|
|
||||||
startAddress >= targetParameters.ioPortAddressRangeStart
|
|
||||||
&& startAddress <= targetParameters.ioPortAddressRangeEnd
|
|
||||||
) || (
|
|
||||||
endAddress >= targetParameters.ioPortAddressRangeStart
|
|
||||||
&& endAddress <= targetParameters.ioPortAddressRangeEnd
|
|
||||||
) || (
|
|
||||||
startAddress <= targetParameters.ioPortAddressRangeStart
|
|
||||||
&& endAddress >= targetParameters.ioPortAddressRangeStart
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -40,37 +40,6 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
*/
|
*/
|
||||||
void initFromTargetDescriptionFile();
|
void initFromTargetDescriptionFile();
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates this->targetParameters with AVR8 target parameters from the loaded target description file.
|
|
||||||
*/
|
|
||||||
virtual void loadTargetParameters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads target parameters that are specific to debugWire and mega JTAG sessions.
|
|
||||||
*/
|
|
||||||
virtual void loadDebugWireAndJtagTargetParameters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads target parameters that are specific to PDI sessions.
|
|
||||||
*/
|
|
||||||
virtual void loadPdiTargetParameters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads target parameters that are specific to UPDI sessions.
|
|
||||||
*/
|
|
||||||
virtual void loadUpdiTargetParameters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a collection of PadDescriptor object from data in the loaded target description file and
|
|
||||||
* populates this->padDescriptorsByName.
|
|
||||||
*/
|
|
||||||
virtual void loadPadDescriptors();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads all variants for the AVR8 target, from the TDF.
|
|
||||||
*/
|
|
||||||
virtual void loadTargetVariants();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the ID from the target's memory.
|
* Extracts the ID from the target's memory.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using Bloom::Targets::TargetDescription::RegisterGroup;
|
|||||||
using Bloom::Targets::TargetDescription::MemorySegment;
|
using Bloom::Targets::TargetDescription::MemorySegment;
|
||||||
using Bloom::Targets::TargetDescription::MemorySegmentType;
|
using Bloom::Targets::TargetDescription::MemorySegmentType;
|
||||||
using Bloom::Targets::TargetDescription::Register;
|
using Bloom::Targets::TargetDescription::Register;
|
||||||
|
using Bloom::Targets::TargetVariant;
|
||||||
|
|
||||||
TargetDescriptionFile::TargetDescriptionFile(
|
TargetDescriptionFile::TargetDescriptionFile(
|
||||||
const TargetSignature& targetSignature,
|
const TargetSignature& targetSignature,
|
||||||
@@ -90,21 +91,8 @@ void TargetDescriptionFile::init(const QDomDocument& xml) {
|
|||||||
Targets::TargetDescription::TargetDescriptionFile::init(xml);
|
Targets::TargetDescription::TargetDescriptionFile::init(xml);
|
||||||
|
|
||||||
this->loadDebugPhysicalInterfaces();
|
this->loadDebugPhysicalInterfaces();
|
||||||
}
|
this->loadPadDescriptors();
|
||||||
|
this->loadTargetVariants();
|
||||||
void TargetDescriptionFile::loadDebugPhysicalInterfaces() {
|
|
||||||
auto interfaceNamesToInterfaces = std::map<std::string, PhysicalInterface>({
|
|
||||||
{"updi", PhysicalInterface::UPDI},
|
|
||||||
{"debugwire", PhysicalInterface::DEBUG_WIRE},
|
|
||||||
{"jtag", PhysicalInterface::DEBUG_WIRE},
|
|
||||||
{"pdi", PhysicalInterface::PDI},
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const auto& [interfaceName, interface]: this->interfacesByName) {
|
|
||||||
if (interfaceNamesToInterfaces.contains(interfaceName)) {
|
|
||||||
this->supportedDebugPhysicalInterfaces.insert(interfaceNamesToInterfaces.at(interfaceName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() {
|
QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() {
|
||||||
@@ -174,6 +162,305 @@ Family TargetDescriptionFile::getFamily() const {
|
|||||||
return familyNameToEnums.at(familyName);
|
return familyNameToEnums.at(familyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TargetParameters TargetDescriptionFile::getTargetParameters() const {
|
||||||
|
TargetParameters targetParameters;
|
||||||
|
|
||||||
|
auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
||||||
|
auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
||||||
|
|
||||||
|
auto flashMemorySegment = this->getFlashMemorySegment();
|
||||||
|
if (flashMemorySegment.has_value()) {
|
||||||
|
targetParameters.flashSize = flashMemorySegment->size;
|
||||||
|
targetParameters.flashStartAddress = flashMemorySegment->startAddress;
|
||||||
|
|
||||||
|
if (flashMemorySegment->pageSize.has_value()) {
|
||||||
|
targetParameters.flashPageSize = flashMemorySegment->pageSize.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ramMemorySegment = this->getRamMemorySegment();
|
||||||
|
if (ramMemorySegment.has_value()) {
|
||||||
|
targetParameters.ramSize = ramMemorySegment->size;
|
||||||
|
targetParameters.ramStartAddress = ramMemorySegment->startAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ioMemorySegment = this->getIoMemorySegment();
|
||||||
|
if (ioMemorySegment.has_value()) {
|
||||||
|
targetParameters.mappedIoSegmentSize = ioMemorySegment->size;
|
||||||
|
targetParameters.mappedIoSegmentStartAddress = ioMemorySegment->startAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto registerMemorySegment = this->getRegisterMemorySegment();
|
||||||
|
if (registerMemorySegment.has_value()) {
|
||||||
|
targetParameters.gpRegisterSize = registerMemorySegment->size;
|
||||||
|
targetParameters.gpRegisterStartAddress = registerMemorySegment->startAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto eepromMemorySegment = this->getEepromMemorySegment();
|
||||||
|
if (eepromMemorySegment.has_value()) {
|
||||||
|
targetParameters.eepromSize = eepromMemorySegment->size;
|
||||||
|
targetParameters.eepromStartAddress = eepromMemorySegment->startAddress;
|
||||||
|
|
||||||
|
if (eepromMemorySegment->pageSize.has_value()) {
|
||||||
|
targetParameters.eepromPageSize = eepromMemorySegment->pageSize.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto firstBootSectionMemorySegment = this->getFirstBootSectionMemorySegment();
|
||||||
|
if (firstBootSectionMemorySegment.has_value()) {
|
||||||
|
targetParameters.bootSectionStartAddress = firstBootSectionMemorySegment->startAddress / 2;
|
||||||
|
targetParameters.bootSectionSize = firstBootSectionMemorySegment->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t cpuRegistersOffset = 0;
|
||||||
|
|
||||||
|
if (peripheralModules.contains("cpu")) {
|
||||||
|
auto cpuPeripheralModule = peripheralModules.at("cpu");
|
||||||
|
|
||||||
|
if (cpuPeripheralModule.instancesMappedByName.contains("cpu")) {
|
||||||
|
auto cpuInstance = cpuPeripheralModule.instancesMappedByName.at("cpu");
|
||||||
|
|
||||||
|
if (cpuInstance.registerGroupsMappedByName.contains("cpu")) {
|
||||||
|
cpuRegistersOffset = cpuInstance.registerGroupsMappedByName.at("cpu").offset.value_or(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto statusRegister = this->getStatusRegister();
|
||||||
|
if (statusRegister.has_value()) {
|
||||||
|
targetParameters.statusRegisterStartAddress = cpuRegistersOffset + statusRegister->offset;
|
||||||
|
targetParameters.statusRegisterSize = statusRegister->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto stackPointerRegister = this->getStackPointerRegister();
|
||||||
|
if (stackPointerRegister.has_value()) {
|
||||||
|
targetParameters.stackPointerRegisterLowAddress = cpuRegistersOffset + stackPointerRegister->offset;
|
||||||
|
targetParameters.stackPointerRegisterSize = stackPointerRegister->size;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Sometimes the SP register is split into two register nodes, one for low, the other for high
|
||||||
|
auto stackPointerLowRegister = this->getStackPointerLowRegister();
|
||||||
|
auto stackPointerHighRegister = this->getStackPointerHighRegister();
|
||||||
|
|
||||||
|
if (stackPointerLowRegister.has_value()) {
|
||||||
|
targetParameters.stackPointerRegisterLowAddress = cpuRegistersOffset
|
||||||
|
+ stackPointerLowRegister->offset;
|
||||||
|
targetParameters.stackPointerRegisterSize = stackPointerLowRegister->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackPointerHighRegister.has_value()) {
|
||||||
|
targetParameters.stackPointerRegisterSize =
|
||||||
|
targetParameters.stackPointerRegisterSize.has_value() ?
|
||||||
|
targetParameters.stackPointerRegisterSize.value() + stackPointerHighRegister->size :
|
||||||
|
stackPointerHighRegister->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto supportedPhysicalInterfaces = this->getSupportedDebugPhysicalInterfaces();
|
||||||
|
|
||||||
|
if (supportedPhysicalInterfaces.contains(PhysicalInterface::DEBUG_WIRE)
|
||||||
|
|| supportedPhysicalInterfaces.contains(PhysicalInterface::JTAG)
|
||||||
|
) {
|
||||||
|
this->loadDebugWireAndJtagTargetParameters(targetParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportedPhysicalInterfaces.contains(PhysicalInterface::PDI)) {
|
||||||
|
this->loadPdiTargetParameters(targetParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportedPhysicalInterfaces.contains(PhysicalInterface::UPDI)) {
|
||||||
|
this->loadUpdiTargetParameters(targetParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetDescriptionFile::loadDebugPhysicalInterfaces() {
|
||||||
|
auto interfaceNamesToInterfaces = std::map<std::string, PhysicalInterface>({
|
||||||
|
{"updi", PhysicalInterface::UPDI},
|
||||||
|
{"debugwire", PhysicalInterface::DEBUG_WIRE},
|
||||||
|
{"jtag", PhysicalInterface::DEBUG_WIRE},
|
||||||
|
{"pdi", PhysicalInterface::PDI},
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const auto& [interfaceName, interface]: this->interfacesByName) {
|
||||||
|
if (interfaceNamesToInterfaces.contains(interfaceName)) {
|
||||||
|
this->supportedDebugPhysicalInterfaces.insert(interfaceNamesToInterfaces.at(interfaceName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetDescriptionFile::loadPadDescriptors() {
|
||||||
|
auto& modules = this->getModulesMappedByName();
|
||||||
|
auto portModule = (modules.contains("port")) ? std::optional(modules.find("port")->second) : std::nullopt;
|
||||||
|
auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
||||||
|
|
||||||
|
if (peripheralModules.contains("port")) {
|
||||||
|
auto portPeripheralModule = peripheralModules.find("port")->second;
|
||||||
|
|
||||||
|
for (const auto& [instanceName, instance] : portPeripheralModule.instancesMappedByName) {
|
||||||
|
if (instanceName.find("port") == 0) {
|
||||||
|
auto portPeripheralRegisterGroup = (portPeripheralModule.registerGroupsMappedByName.contains(instanceName)) ?
|
||||||
|
std::optional(portPeripheralModule.registerGroupsMappedByName.find(instanceName)->second) :
|
||||||
|
std::nullopt;
|
||||||
|
|
||||||
|
for (const auto& signal : instance.instanceSignals) {
|
||||||
|
if (!signal.index.has_value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto padDescriptor = PadDescriptor();
|
||||||
|
padDescriptor.name = signal.padName;
|
||||||
|
padDescriptor.gpioPinNumber = signal.index.value();
|
||||||
|
|
||||||
|
if (portModule.has_value() && portModule->registerGroupsMappedByName.contains(instanceName)) {
|
||||||
|
// We have register information for this port
|
||||||
|
auto registerGroup = portModule->registerGroupsMappedByName.find(instanceName)->second;
|
||||||
|
|
||||||
|
for (const auto& [registerName, portRegister] : registerGroup.registersMappedByName) {
|
||||||
|
if (registerName.find("port") == 0) {
|
||||||
|
// This is the data register for the port
|
||||||
|
padDescriptor.gpioPortSetAddress = portRegister.offset;
|
||||||
|
padDescriptor.gpioPortClearAddress = portRegister.offset;
|
||||||
|
|
||||||
|
} else if (registerName.find("pin") == 0) {
|
||||||
|
// This is the input data register for the port
|
||||||
|
padDescriptor.gpioPortInputAddress = portRegister.offset;
|
||||||
|
|
||||||
|
} else if (registerName.find("ddr") == 0) {
|
||||||
|
// This is the data direction register for the port
|
||||||
|
padDescriptor.ddrSetAddress = portRegister.offset;
|
||||||
|
padDescriptor.ddrClearAddress = portRegister.offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (portModule.has_value() && portModule->registerGroupsMappedByName.contains("port")) {
|
||||||
|
// We have generic register information for all ports on the target
|
||||||
|
auto registerGroup = portModule->registerGroupsMappedByName.find("port")->second;
|
||||||
|
|
||||||
|
for (const auto& [registerName, portRegister] : registerGroup.registersMappedByName) {
|
||||||
|
if (registerName.find("outset") == 0) {
|
||||||
|
// Include the port register offset
|
||||||
|
padDescriptor.gpioPortSetAddress = (portPeripheralRegisterGroup.has_value()
|
||||||
|
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
||||||
|
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
||||||
|
|
||||||
|
padDescriptor.gpioPortSetAddress = padDescriptor.gpioPortSetAddress.value()
|
||||||
|
+ portRegister.offset;
|
||||||
|
|
||||||
|
} else if (registerName.find("outclr") == 0) {
|
||||||
|
padDescriptor.gpioPortClearAddress = (portPeripheralRegisterGroup.has_value()
|
||||||
|
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
||||||
|
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
||||||
|
|
||||||
|
padDescriptor.gpioPortClearAddress = padDescriptor.gpioPortClearAddress.value()
|
||||||
|
+ portRegister.offset;
|
||||||
|
|
||||||
|
} else if (registerName.find("dirset") == 0) {
|
||||||
|
padDescriptor.ddrSetAddress = (portPeripheralRegisterGroup.has_value()
|
||||||
|
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
||||||
|
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
||||||
|
|
||||||
|
padDescriptor.ddrSetAddress = padDescriptor.ddrSetAddress.value()
|
||||||
|
+ portRegister.offset;
|
||||||
|
|
||||||
|
} else if (registerName.find("dirclr") == 0) {
|
||||||
|
padDescriptor.ddrClearAddress = (portPeripheralRegisterGroup.has_value()
|
||||||
|
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
||||||
|
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
||||||
|
|
||||||
|
padDescriptor.ddrClearAddress = padDescriptor.ddrClearAddress.value()
|
||||||
|
+ portRegister.offset;
|
||||||
|
|
||||||
|
} else if (registerName == "in") {
|
||||||
|
padDescriptor.gpioPortInputAddress = (portPeripheralRegisterGroup.has_value()
|
||||||
|
&& portPeripheralRegisterGroup->offset.has_value()) ?
|
||||||
|
portPeripheralRegisterGroup->offset.value_or(0) : 0;
|
||||||
|
|
||||||
|
padDescriptor.gpioPortInputAddress = padDescriptor.gpioPortInputAddress.value()
|
||||||
|
+ portRegister.offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->padDescriptorsByName.insert(std::pair(padDescriptor.name, padDescriptor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetDescriptionFile::loadTargetVariants() {
|
||||||
|
auto tdVariants = this->getVariants();
|
||||||
|
auto tdPinoutsByName = this->getPinoutsMappedByName();
|
||||||
|
auto& modules = this->getModulesMappedByName();
|
||||||
|
|
||||||
|
for (const auto& tdVariant : tdVariants) {
|
||||||
|
if (tdVariant.disabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto targetVariant = TargetVariant();
|
||||||
|
targetVariant.id = static_cast<int>(variants.size());
|
||||||
|
targetVariant.name = tdVariant.name;
|
||||||
|
targetVariant.packageName = tdVariant.package;
|
||||||
|
|
||||||
|
if (tdVariant.package.find("QFP") == 0 || tdVariant.package.find("TQFP") == 0) {
|
||||||
|
targetVariant.package = TargetPackage::QFP;
|
||||||
|
|
||||||
|
} else if (tdVariant.package.find("PDIP") == 0 || tdVariant.package.find("DIP") == 0) {
|
||||||
|
targetVariant.package = TargetPackage::DIP;
|
||||||
|
|
||||||
|
} else if (tdVariant.package.find("QFN") == 0 || tdVariant.package.find("VQFN") == 0) {
|
||||||
|
targetVariant.package = TargetPackage::QFN;
|
||||||
|
|
||||||
|
} else if (tdVariant.package.find("SOIC") == 0) {
|
||||||
|
targetVariant.package = TargetPackage::SOIC;
|
||||||
|
|
||||||
|
} else if (tdVariant.package.find("SSOP") == 0) {
|
||||||
|
targetVariant.package = TargetPackage::SSOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tdPinoutsByName.contains(tdVariant.pinoutName)) {
|
||||||
|
// Missing pinouts in the target description file
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tdPinout = tdPinoutsByName.find(tdVariant.pinoutName)->second;
|
||||||
|
for (const auto& tdPin : tdPinout.pins) {
|
||||||
|
auto targetPin = TargetPinDescriptor();
|
||||||
|
targetPin.name = tdPin.pad;
|
||||||
|
targetPin.padName = tdPin.pad;
|
||||||
|
targetPin.number = tdPin.position;
|
||||||
|
|
||||||
|
// TODO: REMOVE THIS:
|
||||||
|
if (tdPin.pad.find("vcc") == 0
|
||||||
|
|| tdPin.pad.find("avcc") == 0
|
||||||
|
|| tdPin.pad.find("aref") == 0
|
||||||
|
|| tdPin.pad.find("avdd") == 0
|
||||||
|
|| tdPin.pad.find("vdd") == 0
|
||||||
|
) {
|
||||||
|
targetPin.type = TargetPinType::VCC;
|
||||||
|
|
||||||
|
} else if (tdPin.pad.find("gnd") == 0) {
|
||||||
|
targetPin.type = TargetPinType::GND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->padDescriptorsByName.contains(targetPin.padName)) {
|
||||||
|
auto& pad = this->padDescriptorsByName.at(targetPin.padName);
|
||||||
|
if (pad.gpioPortSetAddress.has_value() && pad.ddrSetAddress.has_value()) {
|
||||||
|
targetPin.type = TargetPinType::GPIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetVariant.pinDescriptorsByNumber.insert(std::pair(targetPin.number, targetPin));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->targetVariantsById.insert(std::pair(targetVariant.id, targetVariant));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::optional<MemorySegment> TargetDescriptionFile::getFlashMemorySegment() const {
|
std::optional<MemorySegment> TargetDescriptionFile::getFlashMemorySegment() const {
|
||||||
auto& addressMapping = this->addressSpacesMappedById;
|
auto& addressMapping = this->addressSpacesMappedById;
|
||||||
auto programAddressSpaceIt = addressMapping.find("prog");
|
auto programAddressSpaceIt = addressMapping.find("prog");
|
||||||
@@ -604,3 +891,180 @@ std::optional<Register> TargetDescriptionFile::getEepromControlRegister() const
|
|||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TargetDescriptionFile::loadDebugWireAndJtagTargetParameters(TargetParameters& targetParameters) const {
|
||||||
|
auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
||||||
|
auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
||||||
|
|
||||||
|
// OCD attributes can be found in property groups
|
||||||
|
if (propertyGroups.contains("ocd")) {
|
||||||
|
auto& ocdProperties = propertyGroups.at("ocd").propertiesMappedByName;
|
||||||
|
|
||||||
|
if (ocdProperties.find("ocd_revision") != ocdProperties.end()) {
|
||||||
|
targetParameters.ocdRevision = ocdProperties.find("ocd_revision")
|
||||||
|
->second.value.toUShort(nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocdProperties.find("ocd_datareg") != ocdProperties.end()) {
|
||||||
|
targetParameters.ocdDataRegister = ocdProperties.find("ocd_datareg")
|
||||||
|
->second.value.toUShort(nullptr, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spmcsRegister = this->getSpmcsRegister();
|
||||||
|
if (spmcsRegister.has_value()) {
|
||||||
|
targetParameters.spmcRegisterStartAddress = spmcsRegister->offset;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
auto spmcRegister = this->getSpmcRegister();
|
||||||
|
if (spmcRegister.has_value()) {
|
||||||
|
targetParameters.spmcRegisterStartAddress = spmcRegister->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto osccalRegister = this->getOscillatorCalibrationRegister();
|
||||||
|
if (osccalRegister.has_value()) {
|
||||||
|
targetParameters.osccalAddress = osccalRegister->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto eepromAddressRegister = this->getEepromAddressRegister();
|
||||||
|
if (eepromAddressRegister.has_value()) {
|
||||||
|
targetParameters.eepromAddressRegisterLow = eepromAddressRegister->offset;
|
||||||
|
targetParameters.eepromAddressRegisterHigh = (eepromAddressRegister->size == 2)
|
||||||
|
? eepromAddressRegister->offset + 1 : eepromAddressRegister->offset;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
auto eepromAddressLowRegister = this->getEepromAddressLowRegister();
|
||||||
|
if (eepromAddressLowRegister.has_value()) {
|
||||||
|
targetParameters.eepromAddressRegisterLow = eepromAddressLowRegister->offset;
|
||||||
|
auto eepromAddressHighRegister = this->getEepromAddressHighRegister();
|
||||||
|
|
||||||
|
if (eepromAddressHighRegister.has_value()) {
|
||||||
|
targetParameters.eepromAddressRegisterHigh = eepromAddressHighRegister->offset;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
targetParameters.eepromAddressRegisterHigh = eepromAddressLowRegister->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto eepromDataRegister = this->getEepromDataRegister();
|
||||||
|
if (eepromDataRegister.has_value()) {
|
||||||
|
targetParameters.eepromDataRegisterAddress = eepromDataRegister->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto eepromControlRegister = this->getEepromControlRegister();
|
||||||
|
if (eepromControlRegister.has_value()) {
|
||||||
|
targetParameters.eepromControlRegisterAddress = eepromControlRegister->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetDescriptionFile::loadPdiTargetParameters(TargetParameters& targetParameters) const {
|
||||||
|
auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
||||||
|
auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
||||||
|
|
||||||
|
if (propertyGroups.contains("pdi_interface")) {
|
||||||
|
auto& pdiInterfaceProperties = propertyGroups.at("pdi_interface").propertiesMappedByName;
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("app_section_offset")) {
|
||||||
|
targetParameters.appSectionPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("app_section_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("boot_section_offset")) {
|
||||||
|
targetParameters.bootSectionPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("boot_section_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("datamem_offset")) {
|
||||||
|
targetParameters.ramPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("datamem_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("eeprom_offset")) {
|
||||||
|
targetParameters.eepromPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("eeprom_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("user_signatures_offset")) {
|
||||||
|
targetParameters.userSignaturesPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("user_signatures_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("prod_signatures_offset")) {
|
||||||
|
targetParameters.productSignaturesPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("prod_signatures_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("fuse_registers_offset")) {
|
||||||
|
targetParameters.fuseRegistersPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("fuse_registers_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdiInterfaceProperties.contains("lock_registers_offset")) {
|
||||||
|
targetParameters.lockRegistersPdiOffset = pdiInterfaceProperties
|
||||||
|
.at("lock_registers_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peripheralModules.contains("nvm")) {
|
||||||
|
auto& nvmModule = peripheralModules.at("nvm");
|
||||||
|
|
||||||
|
if (nvmModule.instancesMappedByName.contains("nvm")) {
|
||||||
|
auto& nvmInstance = nvmModule.instancesMappedByName.at("nvm");
|
||||||
|
|
||||||
|
if (nvmInstance.registerGroupsMappedByName.contains("nvm")) {
|
||||||
|
targetParameters.nvmBaseAddress = nvmInstance.registerGroupsMappedByName.at("nvm").offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetDescriptionFile::loadUpdiTargetParameters(TargetParameters& targetParameters) const {
|
||||||
|
auto& propertyGroups = this->getPropertyGroupsMappedByName();
|
||||||
|
auto& peripheralModules = this->getPeripheralModulesMappedByName();
|
||||||
|
auto modulesByName = this->getModulesMappedByName();
|
||||||
|
|
||||||
|
if (peripheralModules.contains("nvmctrl")) {
|
||||||
|
auto& nvmCtrlModule = peripheralModules.at("nvmctrl");
|
||||||
|
|
||||||
|
if (nvmCtrlModule.instancesMappedByName.contains("nvmctrl")) {
|
||||||
|
auto& nvmCtrlInstance = nvmCtrlModule.instancesMappedByName.at("nvmctrl");
|
||||||
|
|
||||||
|
if (nvmCtrlInstance.registerGroupsMappedByName.contains("nvmctrl")) {
|
||||||
|
targetParameters.nvmBaseAddress = nvmCtrlInstance.registerGroupsMappedByName.at("nvmctrl").offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyGroups.contains("updi_interface")) {
|
||||||
|
auto& updiInterfaceProperties = propertyGroups.at("updi_interface").propertiesMappedByName;
|
||||||
|
|
||||||
|
if (updiInterfaceProperties.contains("ocd_base_addr")) {
|
||||||
|
targetParameters.ocdModuleAddress = updiInterfaceProperties
|
||||||
|
.at("ocd_base_addr").value.toUShort(nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updiInterfaceProperties.contains("progmem_offset")) {
|
||||||
|
targetParameters.programMemoryUpdiStartAddress = updiInterfaceProperties
|
||||||
|
.at("progmem_offset").value.toUInt(nullptr, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto signatureMemorySegment = this->getSignatureMemorySegment();
|
||||||
|
if (signatureMemorySegment.has_value()) {
|
||||||
|
targetParameters.signatureSegmentStartAddress = signatureMemorySegment->startAddress;
|
||||||
|
targetParameters.signatureSegmentSize = signatureMemorySegment->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fuseMemorySegment = this->getFuseMemorySegment();
|
||||||
|
if (fuseMemorySegment.has_value()) {
|
||||||
|
targetParameters.fuseSegmentStartAddress = fuseMemorySegment->startAddress;
|
||||||
|
targetParameters.fuseSegmentSize = fuseMemorySegment->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lockbitsMemorySegment = this->getLockbitsMemorySegment();
|
||||||
|
if (lockbitsMemorySegment.has_value()) {
|
||||||
|
targetParameters.lockbitsSegmentStartAddress = lockbitsMemorySegment->startAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
|
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
|
||||||
#include "src/Targets/Microchip/AVR/AVR8/Family.hpp"
|
#include "src/Targets/Microchip/AVR/AVR8/Family.hpp"
|
||||||
#include "src/Targets/Microchip/AVR/AVR8/PhysicalInterface.hpp"
|
#include "src/Targets/Microchip/AVR/AVR8/PhysicalInterface.hpp"
|
||||||
|
#include "src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp"
|
||||||
|
#include "src/Targets/Microchip/AVR/AVR8/PadDescriptor.hpp"
|
||||||
|
#include "src/Targets/TargetVariant.hpp"
|
||||||
|
|
||||||
namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
||||||
{
|
{
|
||||||
@@ -49,48 +52,23 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|||||||
|
|
||||||
std::set<PhysicalInterface> supportedDebugPhysicalInterfaces;
|
std::set<PhysicalInterface> supportedDebugPhysicalInterfaces;
|
||||||
|
|
||||||
|
std::map<std::string, PadDescriptor> padDescriptorsByName;
|
||||||
|
std::map<int, TargetVariant> targetVariantsById;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates this->supportedDebugPhysicalInterfaces with physical interfaces defined in the TDF.
|
* Populates this->supportedDebugPhysicalInterfaces with physical interfaces defined in the TDF.
|
||||||
*/
|
*/
|
||||||
void loadDebugPhysicalInterfaces();
|
void loadDebugPhysicalInterfaces();
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
/**
|
||||||
* Will resolve the target description file using the target description JSON mapping and a given target signature.
|
* Generates a collection of PadDescriptor objects from data in the TDF and populates this->padDescriptorsByName.
|
||||||
*
|
|
||||||
* @param targetSignatureHex
|
|
||||||
* @param targetName
|
|
||||||
*/
|
*/
|
||||||
TargetDescriptionFile(const TargetSignature& targetSignature, std::optional<std::string> targetName);
|
void loadPadDescriptors();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among
|
* Loads all variants for the AVR8 target, from the TDF, and populates this->targetVariantsById.
|
||||||
* other things.
|
|
||||||
*
|
|
||||||
* @param xml
|
|
||||||
*/
|
*/
|
||||||
void init(const QDomDocument& xml) override;
|
void loadTargetVariants();
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the AVR8 target description JSON mapping file.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static QJsonObject getTargetDescriptionMapping();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the AVR8 target signature from the target description XML.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TargetSignature getTargetSignature() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the AVR8 target family from the target description XML.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
[[nodiscard]] Family getFamily() const;
|
|
||||||
|
|
||||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getFlashMemorySegment() const;
|
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getFlashMemorySegment() const;
|
||||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getRamMemorySegment() const;
|
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getRamMemorySegment() const;
|
||||||
@@ -118,13 +96,87 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
|||||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromDataRegister() const;
|
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromDataRegister() const;
|
||||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromControlRegister() const;
|
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromControlRegister() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads target parameters that are specific to debugWire and mega JTAG sessions.
|
||||||
|
*
|
||||||
|
* @param targetParameters
|
||||||
|
*/
|
||||||
|
virtual void loadDebugWireAndJtagTargetParameters(TargetParameters& targetParameters) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads target parameters that are specific to PDI sessions.
|
||||||
|
*
|
||||||
|
* @param targetParameters
|
||||||
|
*/
|
||||||
|
virtual void loadPdiTargetParameters(TargetParameters& targetParameters) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads target parameters that are specific to UPDI sessions.
|
||||||
|
*
|
||||||
|
* @param targetParameters
|
||||||
|
*/
|
||||||
|
virtual void loadUpdiTargetParameters(TargetParameters& targetParameters) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Will resolve the target description file using the target description JSON mapping and a given target signature.
|
||||||
|
*
|
||||||
|
* @param targetSignatureHex
|
||||||
|
* @param targetName
|
||||||
|
*/
|
||||||
|
TargetDescriptionFile(const TargetSignature& targetSignature, std::optional<std::string> targetName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among
|
||||||
|
* other things.
|
||||||
|
*
|
||||||
|
* @param xml
|
||||||
|
*/
|
||||||
|
void init(const QDomDocument& xml) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the AVR8 target description JSON mapping file.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static QJsonObject getTargetDescriptionMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the AVR8 target signature from the TDF.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TargetSignature getTargetSignature() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the AVR8 target family from the TDF.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
[[nodiscard]] Family getFamily() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an instance of TargetParameters, for the AVR8 target, with data from the TDF.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
[[nodiscard]] TargetParameters getTargetParameters() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a set of all supported physical interfaces for debugging.
|
* Returns a set of all supported physical interfaces for debugging.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
const auto& getSupportedDebugPhysicalInterfaces() {
|
[[nodiscard]] const auto& getSupportedDebugPhysicalInterfaces() const {
|
||||||
return this->supportedDebugPhysicalInterfaces;
|
return this->supportedDebugPhysicalInterfaces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] const auto& getPadDescriptorsMappedByName() const {
|
||||||
|
return this->padDescriptorsByName;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] const auto& getVariantsMappedById() const {
|
||||||
|
return this->targetVariantsById;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,16 @@
|
|||||||
|
|
||||||
namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Holds all parameters that would be required for configuring a debug tool, for an AVR8 target.
|
||||||
|
*
|
||||||
|
* This can usually be extracted from the AVR8 TDF.
|
||||||
|
* See Targets::Microchip::Avr::Avr8Bit::TargetDescription::TargetDescriptionFile::getTargetParameters();
|
||||||
|
*/
|
||||||
struct TargetParameters
|
struct TargetParameters
|
||||||
{
|
{
|
||||||
std::optional<std::uint32_t> mappedIoStartAddress;
|
std::optional<std::uint32_t> mappedIoSegmentStartAddress;
|
||||||
|
std::optional<std::uint16_t> mappedIoSegmentSize;
|
||||||
std::optional<std::uint32_t> bootSectionStartAddress;
|
std::optional<std::uint32_t> bootSectionStartAddress;
|
||||||
std::optional<std::uint32_t> gpRegisterStartAddress;
|
std::optional<std::uint32_t> gpRegisterStartAddress;
|
||||||
std::optional<std::uint32_t> gpRegisterSize;
|
std::optional<std::uint32_t> gpRegisterSize;
|
||||||
@@ -55,8 +62,5 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
std::optional<std::uint16_t> fuseSegmentStartAddress;
|
std::optional<std::uint16_t> fuseSegmentStartAddress;
|
||||||
std::optional<std::uint16_t> fuseSegmentSize;
|
std::optional<std::uint16_t> fuseSegmentSize;
|
||||||
std::optional<std::uint16_t> lockbitsSegmentStartAddress;
|
std::optional<std::uint16_t> lockbitsSegmentStartAddress;
|
||||||
|
|
||||||
std::optional<std::uint32_t> ioPortAddressRangeStart;
|
|
||||||
std::optional<std::uint32_t> ioPortAddressRangeEnd;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user