From d8f53e4f9f40b49f79279ef18d9632c6f54d6a42 Mon Sep 17 00:00:00 2001 From: Nav Date: Tue, 6 Jul 2021 20:07:41 +0100 Subject: [PATCH] Moved AVR8 TDF data extraction into AVR8 TDF class. --- .../EDBG/AVR/EdbgAvr8Interface.cpp | 2 +- src/Targets/Microchip/AVR/AVR8/Avr8.cpp | 522 +----------------- src/Targets/Microchip/AVR/AVR8/Avr8.hpp | 31 -- .../TargetDescriptionFile.cpp | 494 ++++++++++++++++- .../TargetDescriptionFile.hpp | 118 ++-- .../Microchip/AVR/AVR8/TargetParameters.hpp | 12 +- 6 files changed, 589 insertions(+), 590 deletions(-) diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp index 4ef073c9..63aed875 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp @@ -138,7 +138,7 @@ void EdbgAvr8Interface::setDebugWireAndJtagParameters() { * * 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()) { Logger::debug("Setting DEVICE_OCD_DATA_REGISTER AVR8 parameter"); diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp index 1a156f62..13676c31 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp @@ -32,497 +32,13 @@ void Avr8::loadTargetDescriptionFile() { } void Avr8::initFromTargetDescriptionFile() { + assert(this->targetDescriptionFile.has_value()); this->name = this->targetDescriptionFile->getTargetName(); this->family = this->targetDescriptionFile->getFamily(); - this->loadTargetParameters(); - this->loadPadDescriptors(); - this->loadTargetVariants(); -} - -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 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(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)); - } + this->targetParameters = this->targetDescriptionFile->getTargetParameters(); + this->padDescriptorsByName = this->targetDescriptionFile->getPadDescriptorsMappedByName(); + this->targetVariantsById = this->targetDescriptionFile->getVariantsMappedById(); } 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(); + if (targetParameters.mappedIoSegmentStartAddress.has_value() && targetParameters.mappedIoSegmentSize.has_value()) { + auto mappedIoSegmentStart = targetParameters.mappedIoSegmentStartAddress.value(); + auto mappedIoSegmentEnd = mappedIoSegmentStart + targetParameters.mappedIoSegmentSize.value(); - /* - * We're making an assumption here; that all IO port addresses for all AVR8 targets are aligned. I have no idea - * how well this will hold. - * - * 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 (startAddress >= mappedIoSegmentStart && startAddress <= mappedIoSegmentEnd) + || (endAddress >= mappedIoSegmentStart && endAddress <= mappedIoSegmentEnd) + || (startAddress <= mappedIoSegmentStart && endAddress >= mappedIoSegmentStart) + ; } return false; diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8.hpp b/src/Targets/Microchip/AVR/AVR8/Avr8.hpp index 980871ef..a490aaf7 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8.hpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8.hpp @@ -40,37 +40,6 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit */ 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. * diff --git a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp index 075ef4f1..65a569e3 100644 --- a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp +++ b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp @@ -16,6 +16,7 @@ using Bloom::Targets::TargetDescription::RegisterGroup; using Bloom::Targets::TargetDescription::MemorySegment; using Bloom::Targets::TargetDescription::MemorySegmentType; using Bloom::Targets::TargetDescription::Register; +using Bloom::Targets::TargetVariant; TargetDescriptionFile::TargetDescriptionFile( const TargetSignature& targetSignature, @@ -90,21 +91,8 @@ void TargetDescriptionFile::init(const QDomDocument& xml) { Targets::TargetDescription::TargetDescriptionFile::init(xml); this->loadDebugPhysicalInterfaces(); -} - -void TargetDescriptionFile::loadDebugPhysicalInterfaces() { - auto interfaceNamesToInterfaces = std::map({ - {"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)); - } - } + this->loadPadDescriptors(); + this->loadTargetVariants(); } QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() { @@ -174,6 +162,305 @@ Family TargetDescriptionFile::getFamily() const { 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({ + {"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(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 TargetDescriptionFile::getFlashMemorySegment() const { auto& addressMapping = this->addressSpacesMappedById; auto programAddressSpaceIt = addressMapping.find("prog"); @@ -604,3 +891,180 @@ std::optional TargetDescriptionFile::getEepromControlRegister() const 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; + } +} diff --git a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp index ab967897..90928cce 100644 --- a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp +++ b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp @@ -7,6 +7,9 @@ #include "src/Targets/Microchip/AVR/TargetSignature.hpp" #include "src/Targets/Microchip/AVR/AVR8/Family.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 { @@ -49,48 +52,23 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription std::set supportedDebugPhysicalInterfaces; + std::map padDescriptorsByName; + std::map targetVariantsById; + /** * Populates this->supportedDebugPhysicalInterfaces with physical interfaces defined in the TDF. */ void loadDebugPhysicalInterfaces(); - public: /** - * Will resolve the target description file using the target description JSON mapping and a given target signature. - * - * @param targetSignatureHex - * @param targetName + * Generates a collection of PadDescriptor objects from data in the TDF and populates this->padDescriptorsByName. */ - TargetDescriptionFile(const TargetSignature& targetSignature, std::optional targetName); + void loadPadDescriptors(); /** - * Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among - * other things. - * - * @param xml + * Loads all variants for the AVR8 target, from the TDF, and populates this->targetVariantsById. */ - 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 target description XML. - * - * @return - */ - [[nodiscard]] TargetSignature getTargetSignature() const; - - /** - * Extracts the AVR8 target family from the target description XML. - * - * @return - */ - [[nodiscard]] Family getFamily() const; + void loadTargetVariants(); [[nodiscard]] std::optional getFlashMemorySegment() const; [[nodiscard]] std::optional getRamMemorySegment() const; @@ -118,13 +96,87 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription [[nodiscard]] std::optional getEepromDataRegister() const; [[nodiscard]] std::optional 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 targetName); + + /** + * Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among + * other things. + * + * @param xml + */ + void init(const QDomDocument& xml) override; + + /** + * Loads the AVR8 target description JSON mapping file. + * + * @return + */ + static QJsonObject getTargetDescriptionMapping(); + + /** + * Extracts the AVR8 target signature from the TDF. + * + * @return + */ + [[nodiscard]] TargetSignature getTargetSignature() const; + + /** + * Extracts the AVR8 target family from the TDF. + * + * @return + */ + [[nodiscard]] Family getFamily() const; + + /** + * Constructs an instance of TargetParameters, for the AVR8 target, with data from the TDF. + * + * @return + */ + [[nodiscard]] TargetParameters getTargetParameters() const; + /** * Returns a set of all supported physical interfaces for debugging. * * @return */ - const auto& getSupportedDebugPhysicalInterfaces() { + [[nodiscard]] const auto& getSupportedDebugPhysicalInterfaces() const { return this->supportedDebugPhysicalInterfaces; }; + + [[nodiscard]] const auto& getPadDescriptorsMappedByName() const { + return this->padDescriptorsByName; + }; + + [[nodiscard]] const auto& getVariantsMappedById() const { + return this->targetVariantsById; + }; }; } diff --git a/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp b/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp index c710b88f..388c8abf 100644 --- a/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp +++ b/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp @@ -8,9 +8,16 @@ 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 { - std::optional mappedIoStartAddress; + std::optional mappedIoSegmentStartAddress; + std::optional mappedIoSegmentSize; std::optional bootSectionStartAddress; std::optional gpRegisterStartAddress; std::optional gpRegisterSize; @@ -55,8 +62,5 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit std::optional fuseSegmentStartAddress; std::optional fuseSegmentSize; std::optional lockbitsSegmentStartAddress; - - std::optional ioPortAddressRangeStart; - std::optional ioPortAddressRangeEnd; }; }