From 1971f0a89e6f2eda734aa1268b443a786b561333 Mon Sep 17 00:00:00 2001 From: Nav Date: Sun, 27 Jun 2021 20:09:15 +0100 Subject: [PATCH] Refactored AVR8 TDF loading Refactored EDBG AVR8 target parameter uploading Implemented UPDI parameter extraction (from TDF) and uploading to debug tool Introduced supported physical interfaces in AVR8 TDFs --- .../VendorSpecific/EDBG/AVR/Avr8Generic.hpp | 31 +- .../EDBG/AVR/EdbgAvr8Interface.cpp | 593 +++++++++++++----- .../EDBG/AVR/EdbgAvr8Interface.hpp | 29 +- src/Targets/Microchip/AVR/AVR8/Avr8.cpp | 549 +++++++++------- src/Targets/Microchip/AVR/AVR8/Avr8.hpp | 44 +- .../TargetDescriptionFile.cpp | 80 ++- .../TargetDescriptionFile.hpp | 30 + .../Microchip/AVR/AVR8/TargetParameters.hpp | 12 + 8 files changed, 939 insertions(+), 429 deletions(-) diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/Avr8Generic.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/Avr8Generic.hpp index 906a467c..a9482733 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/Avr8Generic.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/Avr8Generic.hpp @@ -20,7 +20,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr constexpr static Avr8EdbgParameter CONFIG_FUNCTION {0x00, 0x01}; constexpr static Avr8EdbgParameter PHYSICAL_INTERFACE {0x01, 0x00}; constexpr static Avr8EdbgParameter DW_CLOCK_DIVISION_FACTOR {0x01, 0x10}; - constexpr static Avr8EdbgParameter XMEGA_PDI_CLOCK {0x01, 0x31}; + constexpr static Avr8EdbgParameter PDI_CLOCK_SPEED {0x01, 0x31}; constexpr static Avr8EdbgParameter MEGA_DEBUG_CLOCK {0x01, 0x21}; constexpr static Avr8EdbgParameter JTAG_DAISY_CHAIN_SETTINGS {0x01, 0x01}; @@ -58,7 +58,28 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr constexpr static Avr8EdbgParameter DEVICE_XMEGA_EEPROM_SIZE {0x02, 0x28}; constexpr static Avr8EdbgParameter DEVICE_XMEGA_EEPROM_PAGE_SIZE {0x02, 0x2A}; + // UPDI device parameters + constexpr static Avr8EdbgParameter DEVICE_UPDI_PROGMEM_BASE_ADDR {0x02, 0x00}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_FLASH_PAGE_SIZE {0x02, 0x02}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_EEPROM_PAGE_SIZE {0x02, 0x03}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_NVMCTRL_ADDR {0x02, 0x04}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_OCD_ADDR {0x02, 0x06}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_FLASH_SIZE {0x02, 0x12}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_EEPROM_SIZE {0x02, 0x16}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_USER_SIG_SIZE {0x02, 0x18}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_FUSE_SIZE {0x02, 0x1A}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_EEPROM_BASE_ADDR {0x02, 0x20}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_USER_SIG_BASE_ADDR {0x02, 0x22}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_SIG_BASE_ADDR {0x02, 0x24}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_FUSE_BASE_ADDR {0x02, 0x26}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_LOCK_BASE_ADDR {0x02, 0x28}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_DEVICE_ID {0x02, 0x2A}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB {0x02, 0x2C}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_FLASH_PAGE_SIZE_MSB {0x02, 0x2D}; + constexpr static Avr8EdbgParameter DEVICE_UPDI_24_BIT_ADDRESSING_ENABLE {0x02, 0x2E}; + constexpr static Avr8EdbgParameter RUN_TIMERS_WHILST_STOPPED {0x03, 0x00}; + constexpr static Avr8EdbgParameter ENABLE_HIGH_VOLTAGE_UPDI {0x03, 0x06}; }; enum class Avr8ConfigVariant: unsigned char @@ -148,4 +169,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr DATA = 0x84, FAILED = 0xA0, }; + + inline bool operator == (unsigned char rawId, Avr8ResponseId id) { + return static_cast(id) == rawId; + } + + inline bool operator == (Avr8ResponseId id, unsigned char rawId) { + return rawId == id; + } } 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 28065dab..595c7413 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp @@ -66,6 +66,408 @@ std::vector EdbgAvr8Interface::getParameter(const Avr8EdbgParamet return response.getPayloadData(); } +void EdbgAvr8Interface::setDebugWireAndJtagParameters() { + if (this->targetParameters.flashPageSize.has_value()) { + Logger::debug("Setting DEVICE_FLASH_PAGE_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_FLASH_PAGE_SIZE, + this->targetParameters.flashPageSize.value() + ); + } + + if (this->targetParameters.flashSize.has_value()) { + Logger::debug("Setting DEVICE_FLASH_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_FLASH_SIZE, + this->targetParameters.flashSize.value() + ); + } + + if (this->targetParameters.flashStartAddress.has_value()) { + Logger::debug("Setting DEVICE_FLASH_BASE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_FLASH_BASE, + this->targetParameters.flashStartAddress.value() + ); + } + + if (this->targetParameters.ramStartAddress.has_value()) { + Logger::debug("Setting DEVICE_SRAM_START AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_SRAM_START, + this->targetParameters.ramStartAddress.value() + ); + } + + if (this->targetParameters.eepromSize.has_value()) { + Logger::debug("Setting DEVICE_EEPROM_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_EEPROM_SIZE, + this->targetParameters.eepromSize.value() + ); + } + + if (this->targetParameters.eepromPageSize.has_value()) { + Logger::debug("Setting DEVICE_EEPROM_PAGE_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_EEPROM_PAGE_SIZE, + this->targetParameters.eepromPageSize.value() + ); + } + + if (this->targetParameters.ocdRevision.has_value()) { + Logger::debug("Setting DEVICE_OCD_REVISION AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_OCD_REVISION, + this->targetParameters.ocdRevision.value() + ); + } + + if (this->targetParameters.ocdDataRegister.has_value()) { + Logger::debug("Setting DEVICE_OCD_DATA_REGISTER AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_OCD_DATA_REGISTER, + this->targetParameters.ocdDataRegister.value() + ); + } + + if (this->targetParameters.spmcRegisterStartAddress.has_value()) { + Logger::debug("Setting DEVICE_SPMCR_REGISTER AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_SPMCR_REGISTER, + this->targetParameters.spmcRegisterStartAddress.value() + ); + } + + if (this->targetParameters.osccalAddress.has_value()) { + Logger::debug("Setting DEVICE_OSCCAL_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_OSCCAL_ADDR, + this->targetParameters.osccalAddress.value() + ); + } + + if (this->targetParameters.eepromAddressRegisterLow.has_value()) { + Logger::debug("Setting DEVICE_EEARL_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_EEARL_ADDR, + this->targetParameters.eepromAddressRegisterLow.value() + ); + } + + if (this->targetParameters.eepromAddressRegisterHigh.has_value()) { + Logger::debug("Setting DEVICE_EEARH_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_EEARH_ADDR, + this->targetParameters.eepromAddressRegisterHigh.value() + ); + } + + if (this->targetParameters.eepromControlRegisterAddress.has_value()) { + Logger::debug("Setting DEVICE_EECR_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_EECR_ADDR, + this->targetParameters.eepromControlRegisterAddress.value() + ); + } + + if (this->targetParameters.eepromDataRegisterAddress.has_value()) { + Logger::debug("Setting DEVICE_EEDR_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_EEDR_ADDR, + this->targetParameters.eepromDataRegisterAddress.value() + ); + } + + if (this->targetParameters.bootSectionStartAddress.has_value()) { + Logger::debug("Setting DEVICE_BOOT_START_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_BOOT_START_ADDR, + this->targetParameters.bootSectionStartAddress.value() + ); + } +} + +void EdbgAvr8Interface::setPdiParameters() { + if (!this->targetParameters.appSectionPdiOffset.has_value()) { + throw Exception("Missing required parameter: APPL_BASE_ADDR"); + } + + if (!this->targetParameters.bootSectionPdiOffset.has_value()) { + throw Exception("Missing required parameter: BOOT_BASE_ADDR"); + } + + if (!this->targetParameters.bootSectionSize.has_value()) { + throw Exception("Missing required parameter: BOOT_BYTES"); + } + + if (!this->targetParameters.flashSize.has_value()) { + throw Exception("Missing required parameter: APPLICATION_BYTES"); + } + + if (!this->targetParameters.eepromPdiOffset.has_value()) { + throw Exception("Missing required parameter: EEPROM_BASE_ADDR"); + } + + if (!this->targetParameters.fuseRegistersPdiOffset.has_value()) { + throw Exception("Missing required parameter: FUSE_BASE_ADDR"); + } + + if (!this->targetParameters.lockRegistersPdiOffset.has_value()) { + throw Exception("Missing required parameter: LOCKBIT_BASE_ADDR"); + } + + if (!this->targetParameters.userSignaturesPdiOffset.has_value()) { + throw Exception("Missing required parameter: USER_SIGN_BASE_ADDR"); + } + + if (!this->targetParameters.productSignaturesPdiOffset.has_value()) { + throw Exception("Missing required parameter: PROD_SIGN_BASE_ADDR"); + } + + if (!this->targetParameters.ramPdiOffset.has_value()) { + throw Exception("Missing required parameter: DATA_BASE_ADDR"); + } + + if (!this->targetParameters.flashPageSize.has_value()) { + throw Exception("Missing required parameter: FLASH_PAGE_BYTES"); + } + + if (!this->targetParameters.eepromSize.has_value()) { + throw Exception("Missing required parameter: EEPROM_SIZE"); + } + + if (!this->targetParameters.eepromPageSize.has_value()) { + throw Exception("Missing required parameter: EEPROM_PAGE_SIZE"); + } + + if (!this->targetParameters.nvmBaseAddress.has_value()) { + throw Exception("Missing required parameter: NVM_BASE"); + } + + Logger::debug("Setting APPL_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_APPL_BASE_ADDR, + this->targetParameters.appSectionPdiOffset.value() + ); + + Logger::debug("Setting BOOT_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BASE_ADDR, + this->targetParameters.bootSectionPdiOffset.value() + ); + + Logger::debug("Setting EEPROM_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_BASE_ADDR, + this->targetParameters.eepromPdiOffset.value() + ); + + Logger::debug("Setting FUSE_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_FUSE_BASE_ADDR, + this->targetParameters.fuseRegistersPdiOffset.value() + ); + + Logger::debug("Setting LOCKBIT_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_LOCKBIT_BASE_ADDR, + this->targetParameters.lockRegistersPdiOffset.value() + ); + + Logger::debug("Setting USER_SIGN_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_USER_SIGN_BASE_ADDR, + this->targetParameters.userSignaturesPdiOffset.value() + ); + + Logger::debug("Setting PROD_SIGN_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_PROD_SIGN_BASE_ADDR, + this->targetParameters.productSignaturesPdiOffset.value() + ); + + Logger::debug("Setting DATA_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_DATA_BASE_ADDR, + this->targetParameters.ramPdiOffset.value() + ); + + Logger::debug("Setting APPLICATION_BYTES AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_APPLICATION_BYTES, + this->targetParameters.flashSize.value() + ); + + Logger::debug("Setting BOOT_BYTES AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BYTES, + this->targetParameters.bootSectionSize.value() + ); + + Logger::debug("Setting FLASH_PAGE_BYTES AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_FLASH_PAGE_BYTES, + this->targetParameters.flashPageSize.value() + ); + + Logger::debug("Setting EEPROM_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_SIZE, + this->targetParameters.eepromSize.value() + ); + + Logger::debug("Setting EEPROM_PAGE_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_PAGE_SIZE, + static_cast(this->targetParameters.eepromPageSize.value()) + ); + + Logger::debug("Setting NVM_BASE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_XMEGA_NVM_BASE, + this->targetParameters.nvmBaseAddress.value() + ); +} + +void EdbgAvr8Interface::setUpdiParameters() { + if (!this->targetParameters.signatureSegmentStartAddress.has_value()) { + throw Exception("Missing required parameter: SIGNATURE BASE ADDRESS"); + } + + if (this->targetParameters.programMemoryUpdiStartAddress.has_value()) { + /* + * The program memory base address field for UPDI sessions (DEVICE_UPDI_PROGMEM_BASE_ADDR) seems to be limited + * to two bytes in size, as opposed to the four byte size for the debugWire, JTAG and PDI equivalent fields. + * This is why, I suspect, another field was required for the most significant byte of the program memory base + * address (DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB). + * + * The additional DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB field is only one byte in size, so it brings the total + * capacity for the program memory base address to three bytes. Because of this, we ensure that all TDFs, for + * targets that support UPDI, specify an address that does not exceed the maximum value of a 24 bit unsigned + * integer. This is done in our TDF validation script (see src/Targets/TargetDescription/README.md for more). + */ + auto programMemBaseAddress = this->targetParameters.programMemoryUpdiStartAddress.value(); + Logger::debug("Setting DEVICE_UPDI_PROGMEM_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR, + static_cast(programMemBaseAddress) + ); + + Logger::debug("Setting DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB, + static_cast(programMemBaseAddress >> 16) + ); + } + + if (this->targetParameters.flashPageSize.has_value()) { + /* + * See the comment above regarding capacity limitations of the DEVICE_UPDI_PROGMEM_BASE_ADDR field. + * + * The same applies here, for the flash page size field (DEVICE_UPDI_FLASH_PAGE_SIZE). + */ + auto flashPageSize = this->targetParameters.flashPageSize.value(); + Logger::debug("Setting DEVICE_UPDI_FLASH_PAGE_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE, + static_cast(flashPageSize) + ); + + Logger::debug("Setting DEVICE_UPDI_FLASH_PAGE_SIZE_MSB AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE_MSB, + static_cast(flashPageSize >> 8) + ); + } + + if (this->targetParameters.eepromPageSize.has_value()) { + Logger::debug("Setting DEVICE_UPDI_EEPROM_PAGE_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_EEPROM_PAGE_SIZE, + this->targetParameters.eepromPageSize.value() + ); + } + + if (this->targetParameters.nvmBaseAddress.has_value()) { + Logger::debug("Setting DEVICE_UPDI_NVMCTRL_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_NVMCTRL_ADDR, + this->targetParameters.nvmBaseAddress.value() + ); + } + + if (this->targetParameters.ocdModuleAddress.has_value()) { + Logger::debug("Setting DEVICE_UPDI_OCD_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_OCD_ADDR, + this->targetParameters.ocdModuleAddress.value() + ); + } + + if (this->targetParameters.flashSize.has_value()) { + Logger::debug("Setting DEVICE_UPDI_FLASH_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_FLASH_SIZE, + this->targetParameters.flashSize.value() + ); + } + + if (this->targetParameters.eepromSize.has_value()) { + Logger::debug("Setting DEVICE_UPDI_EEPROM_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_EEPROM_SIZE, + this->targetParameters.eepromSize.value() + ); + } + + if (this->targetParameters.eepromStartAddress.has_value()) { + Logger::debug("Setting DEVICE_UPDI_EEPROM_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_EEPROM_BASE_ADDR, + this->targetParameters.eepromStartAddress.value() + ); + } + + if (this->targetParameters.signatureSegmentStartAddress.has_value()) { + Logger::debug("Setting DEVICE_UPDI_SIG_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_SIG_BASE_ADDR, + this->targetParameters.signatureSegmentStartAddress.value() + ); + } + + if (this->targetParameters.fuseSegmentStartAddress.has_value()) { + Logger::debug("Setting DEVICE_UPDI_FUSE_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_FUSE_BASE_ADDR, + this->targetParameters.fuseSegmentStartAddress.value() + ); + } + + if (this->targetParameters.fuseSegmentSize.has_value()) { + Logger::debug("Setting DEVICE_UPDI_FUSE_SIZE AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_FUSE_SIZE, + this->targetParameters.fuseSegmentSize.value() + ); + } + + if (this->targetParameters.lockbitsSegmentStartAddress.has_value()) { + Logger::debug("Setting DEVICE_UPDI_LOCK_BASE_ADDR AVR8 parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_LOCK_BASE_ADDR, + this->targetParameters.lockbitsSegmentStartAddress.value() + ); + } + + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_24_BIT_ADDRESSING_ENABLE, + this->targetParameters.programMemoryUpdiStartAddress.value_or(0) > 0xFFFF ? + static_cast(1) : static_cast(0) + ); +} + void EdbgAvr8Interface::configure(const TargetConfig& targetConfig) { auto physicalInterface = targetConfig.jsonObject.find("physicalInterface")->toString().toLower().toStdString(); @@ -124,179 +526,22 @@ void EdbgAvr8Interface::setTargetParameters(const Avr8Bit::TargetParameters& con this->configVariant = configVariant.value(); } - if (this->configVariant == Avr8ConfigVariant::XMEGA) { - if (!config.appSectionPdiOffset.has_value()) { - throw Exception("Missing required parameter: APPL_BASE_ADDR"); + switch (this->configVariant) { + case Avr8ConfigVariant::DEBUG_WIRE: + case Avr8ConfigVariant::MEGAJTAG: { + this->setDebugWireAndJtagParameters(); + break; } - - if (!config.bootSectionPdiOffset.has_value()) { - throw Exception("Missing required parameter: BOOT_BASE_ADDR"); + case Avr8ConfigVariant::XMEGA: { + this->setPdiParameters(); + break; } - - if (!config.bootSectionSize.has_value()) { - throw Exception("Missing required parameter: BOOT_BYTES"); + case Avr8ConfigVariant::UPDI: { + this->setUpdiParameters(); + break; } - - if (!config.flashSize.has_value()) { - throw Exception("Missing required parameter: APPLICATION_BYTES"); - } - - if (!config.eepromPdiOffset.has_value()) { - throw Exception("Missing required parameter: EEPROM_BASE_ADDR"); - } - - if (!config.fuseRegistersPdiOffset.has_value()) { - throw Exception("Missing required parameter: FUSE_BASE_ADDR"); - } - - if (!config.lockRegistersPdiOffset.has_value()) { - throw Exception("Missing required parameter: LOCKBIT_BASE_ADDR"); - } - - if (!config.userSignaturesPdiOffset.has_value()) { - throw Exception("Missing required parameter: USER_SIGN_BASE_ADDR"); - } - - if (!config.productSignaturesPdiOffset.has_value()) { - throw Exception("Missing required parameter: PROD_SIGN_BASE_ADDR"); - } - - if (!config.ramPdiOffset.has_value()) { - throw Exception("Missing required parameter: DATA_BASE_ADDR"); - } - - if (!config.flashPageSize.has_value()) { - throw Exception("Missing required parameter: FLASH_PAGE_BYTES"); - } - - if (!config.eepromSize.has_value()) { - throw Exception("Missing required parameter: EEPROM_SIZE"); - } - - if (!config.eepromPageSize.has_value()) { - throw Exception("Missing required parameter: EEPROM_PAGE_SIZE"); - } - - if (!config.nvmBaseAddress.has_value()) { - throw Exception("Missing required parameter: NVM_BASE"); - } - - Logger::debug("Setting APPL_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_APPL_BASE_ADDR, config.appSectionPdiOffset.value()); - - Logger::debug("Setting BOOT_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BASE_ADDR, config.bootSectionPdiOffset.value()); - - Logger::debug("Setting EEPROM_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_BASE_ADDR, config.eepromPdiOffset.value()); - - Logger::debug("Setting FUSE_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_FUSE_BASE_ADDR, config.fuseRegistersPdiOffset.value()); - - Logger::debug("Setting LOCKBIT_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_LOCKBIT_BASE_ADDR, config.lockRegistersPdiOffset.value()); - - Logger::debug("Setting USER_SIGN_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_USER_SIGN_BASE_ADDR, config.userSignaturesPdiOffset.value()); - - Logger::debug("Setting PROD_SIGN_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_PROD_SIGN_BASE_ADDR, config.productSignaturesPdiOffset.value()); - - Logger::debug("Setting DATA_BASE_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_DATA_BASE_ADDR, config.ramPdiOffset.value()); - - Logger::debug("Setting APPLICATION_BYTES AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_APPLICATION_BYTES, config.flashSize.value()); - - Logger::debug("Setting BOOT_BYTES AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BYTES, config.bootSectionSize.value()); - - Logger::debug("Setting FLASH_PAGE_BYTES AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_FLASH_PAGE_BYTES, config.flashPageSize.value()); - - Logger::debug("Setting EEPROM_SIZE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_SIZE, config.eepromSize.value()); - - Logger::debug("Setting EEPROM_PAGE_SIZE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_PAGE_SIZE, static_cast(config.eepromPageSize.value())); - - Logger::debug("Setting NVM_BASE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_NVM_BASE, config.nvmBaseAddress.value()); - - } else { - if (config.flashPageSize.has_value()) { - Logger::debug("Setting DEVICE_FLASH_PAGE_SIZE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_FLASH_PAGE_SIZE, config.flashPageSize.value()); - } - - if (config.flashSize.has_value()) { - Logger::debug("Setting DEVICE_FLASH_SIZE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_FLASH_SIZE, config.flashSize.value()); - } - - if (config.flashStartAddress.has_value()) { - Logger::debug("Setting DEVICE_FLASH_BASE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_FLASH_BASE, config.flashStartAddress.value()); - } - - if (config.ramStartAddress.has_value()) { - Logger::debug("Setting DEVICE_SRAM_START AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_SRAM_START, config.ramStartAddress.value()); - } - - if (config.eepromSize.has_value()) { - Logger::debug("Setting DEVICE_EEPROM_SIZE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_EEPROM_SIZE, config.eepromSize.value()); - } - - if (config.eepromPageSize.has_value()) { - Logger::debug("Setting DEVICE_EEPROM_PAGE_SIZE AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_EEPROM_PAGE_SIZE, config.eepromPageSize.value()); - } - - if (config.ocdRevision.has_value()) { - Logger::debug("Setting DEVICE_OCD_REVISION AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_OCD_REVISION, config.ocdRevision.value()); - } - - if (config.ocdDataRegister.has_value()) { - Logger::debug("Setting DEVICE_OCD_DATA_REGISTER AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_OCD_DATA_REGISTER, config.ocdDataRegister.value()); - } - - if (config.spmcRegisterStartAddress.has_value()) { - Logger::debug("Setting DEVICE_SPMCR_REGISTER AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_SPMCR_REGISTER, config.spmcRegisterStartAddress.value()); - } - - if (config.osccalAddress.has_value()) { - Logger::debug("Setting DEVICE_OSCCAL_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_OSCCAL_ADDR, config.osccalAddress.value()); - } - - if (config.eepromAddressRegisterLow.has_value()) { - Logger::debug("Setting DEVICE_EEARL_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_EEARL_ADDR, config.eepromAddressRegisterLow.value()); - } - - if (config.eepromAddressRegisterHigh.has_value()) { - Logger::debug("Setting DEVICE_EEARH_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_EEARH_ADDR, config.eepromAddressRegisterHigh.value()); - } - - if (config.eepromControlRegisterAddress.has_value()) { - Logger::debug("Setting DEVICE_EECR_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_EECR_ADDR, config.eepromControlRegisterAddress.value()); - } - - if (config.eepromDataRegisterAddress.has_value()) { - Logger::debug("Setting DEVICE_EEDR_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_EEDR_ADDR, config.eepromDataRegisterAddress.value()); - } - - if (config.bootSectionStartAddress.has_value()) { - Logger::debug("Setting DEVICE_BOOT_START_ADDR AVR8 parameter"); - this->setParameter(Avr8EdbgParameters::DEVICE_BOOT_START_ADDR, config.bootSectionStartAddress.value()); + default: { + break; } } } @@ -305,7 +550,13 @@ void EdbgAvr8Interface::init() { if (this->configVariant == Avr8ConfigVariant::XMEGA) { // Default PDI clock to 4MHz // TODO: Make this adjustable via a target config parameter - this->setParameter(Avr8EdbgParameters::XMEGA_PDI_CLOCK, static_cast(0x0FA0)); + this->setParameter(Avr8EdbgParameters::PDI_CLOCK_SPEED, static_cast(0x0FA0)); + } + + if (this->configVariant == Avr8ConfigVariant::UPDI) { + // Default UPDI clock to 1.8MHz + this->setParameter(Avr8EdbgParameters::PDI_CLOCK_SPEED, static_cast(0x0708)); + this->setParameter(Avr8EdbgParameters::ENABLE_HIGH_VOLTAGE_UPDI, static_cast(0x00)); } if (this->configVariant == Avr8ConfigVariant::MEGAJTAG) { diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp index c60080ab..c3ccbc56 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp @@ -14,14 +14,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr { - inline bool operator==(unsigned char rawId, Avr8ResponseId id) { - return static_cast(id) == rawId; - } - - inline bool operator==(Avr8ResponseId id, unsigned char rawId) { - return rawId == id; - } - /** * The EdbgAvr8Interface implements the AVR8 Generic EDBG/CMSIS-DAP protocol, as an Avr8Interface. * @@ -291,6 +283,27 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr */ std::vector getParameter(const Avr8EdbgParameter& parameter, std::uint8_t size); + /** + * EDBG-based debug tools require target specific parameters such as memory locations, page sizes and + * register addresses. These parameters can be sent to the tool before and during a session. + * + * What parameters we need to send depend on the physical interface (and config variant) selected by the user. + * For target parameters, the address (ID) of the parameter also varies across config variants. This is why + * we sometimes have separate parameters for sending the same data, where they differ only in parameter IDs. + * For example, the Avr8EdbgParameters::DEVICE_FLASH_BASE parameter is used to send the base address for + * the target's flash memory segment. The parameter is assigned an address (ID) of 0x06. But the + * Avr8EdbgParameters::DEVICE_UPDI_PROG_BASE is used to send the same data (base address of the target's flash + * segment), but only for sessions with the UPDI physical interface. The address is 0x00. + * + * - The setDebugWireAndJtagParameters() function sends the required target parameters for debugWire and JTAG + * sessions. Both sessions are covered in a single function because they require the same parameters. + * - The setPdiParameters() function sends the required target parameters for PDI sessions. + * - The setUpdiParameters() function sends the required target parameters for UPDI sessions. + */ + void setDebugWireAndJtagParameters(); + void setPdiParameters(); + void setUpdiParameters(); + /** * Sends the "Activate Physical" command to the debug tool, activating the physical interface and thus enabling * communication between the debug tool and the target. diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp index a1a94109..4154adc5 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp @@ -24,13 +24,6 @@ using namespace Bloom::Targets::Microchip::Avr; using namespace Bloom::Targets::Microchip::Avr::Avr8Bit; using namespace Exceptions; -/** - * Initialises the target from config parameters extracted from user's config file. - * - * @see Application::extractConfig(); for more on config extraction. - * - * @param targetConfig - */ void Avr8::preActivationConfigure(const TargetConfig& targetConfig) { Target::preActivationConfigure(targetConfig); @@ -44,6 +37,7 @@ void Avr8::preActivationConfigure(const TargetConfig& targetConfig) { void Avr8::postActivationConfigure() { if (!this->targetDescriptionFile.has_value()) { this->loadTargetDescriptionFile(); + this->initFromTargetDescriptionFile(); } /* @@ -71,27 +65,291 @@ void Avr8::postPromotionConfigure() { } this->avr8Interface->setFamily(this->family.value()); - this->avr8Interface->setTargetParameters(this->getTargetParameters()); + this->avr8Interface->setTargetParameters(this->targetParameters.value()); } void Avr8::loadTargetDescriptionFile() { - auto targetSignature = this->getId(); - auto targetDescriptionFile = TargetDescription::TargetDescriptionFile( - targetSignature, + this->targetDescriptionFile = TargetDescription::TargetDescriptionFile( + this->getId(), (!this->name.empty()) ? std::optional(this->name) : std::nullopt ); +} - this->targetDescriptionFile = targetDescriptionFile; - this->name = targetDescriptionFile.getTargetName(); - this->family = targetDescriptionFile.getFamily(); +void Avr8::initFromTargetDescriptionFile() { + this->name = this->targetDescriptionFile->getTargetName(); + this->family = this->targetDescriptionFile->getFamily(); + this->loadTargetParameters(); this->loadPadDescriptors(); this->loadTargetVariants(); } -void Avr8::loadPadDescriptors() { - auto& targetParameters = this->getTargetParameters(); +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 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; + } + + auto statusRegister = this->targetDescriptionFile->getStatusRegister(); + if (statusRegister.has_value()) { + this->targetParameters->statusRegisterStartAddress = statusRegister->offset; + this->targetParameters->statusRegisterSize = statusRegister->size; + } + + auto stackPointerRegister = this->targetDescriptionFile->getStackPointerRegister(); + if (stackPointerRegister.has_value()) { + this->targetParameters->stackPointerRegisterStartAddress = 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->stackPointerRegisterStartAddress = 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 @@ -215,8 +473,8 @@ void Avr8::loadPadDescriptors() { // TODO: Move this into getTargetParameters() if (!portAddresses.empty()) { - targetParameters.ioPortAddressRangeStart = *std::min_element(portAddresses.begin(), portAddresses.end()); - targetParameters.ioPortAddressRangeEnd = *std::max_element(portAddresses.begin(), portAddresses.end()); + this->targetParameters->ioPortAddressRangeStart = *std::min_element(portAddresses.begin(), portAddresses.end()); + this->targetParameters->ioPortAddressRangeEnd = *std::max_element(portAddresses.begin(), portAddresses.end()); } } @@ -290,198 +548,12 @@ void Avr8::loadTargetVariants() { } } -TargetParameters& Avr8::getTargetParameters() { - if (!this->targetParameters.has_value()) { - assert(this->targetDescriptionFile.has_value()); - auto supportedPhysicalInterfaces = this->targetDescriptionFile->getSupportedDebugPhysicalInterfaces(); - 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 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; - - 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; - } - - // 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 statusRegister = this->targetDescriptionFile->getStatusRegister(); - if (statusRegister.has_value()) { - this->targetParameters->statusRegisterStartAddress = statusRegister->offset; - this->targetParameters->statusRegisterSize = statusRegister->size; - } - - auto stackPointerRegister = this->targetDescriptionFile->getStackPointerRegister(); - if (stackPointerRegister.has_value()) { - this->targetParameters->stackPointerRegisterStartAddress = 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->stackPointerRegisterStartAddress = 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 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; - } - - 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; - } - } - } - } +TargetSignature Avr8::getId() { + if (!this->id.has_value()) { + this->id = this->avr8Interface->getDeviceId(); } - return this->targetParameters.value(); + return this->id.value(); } void Avr8::activate() { @@ -492,7 +564,7 @@ void Avr8::activate() { this->avr8Interface->init(); if (this->targetDescriptionFile.has_value()) { - this->avr8Interface->setTargetParameters(this->getTargetParameters()); + this->avr8Interface->setTargetParameters(this->targetParameters.value()); } this->avr8Interface->activate(); @@ -539,21 +611,11 @@ void Avr8::deactivate() { } } -TargetSignature Avr8::getId() { - if (!this->id.has_value()) { - this->id = this->avr8Interface->getDeviceId(); - } - - return this->id.value(); -} - TargetDescriptor Avr8Bit::Avr8::getDescriptor() { - auto parameters = this->getTargetParameters(); - auto descriptor = TargetDescriptor(); descriptor.id = this->getHumanReadableId(); descriptor.name = this->getName(); - descriptor.ramSize = parameters.ramSize.value_or(0); + descriptor.ramSize = this->targetParameters.value().ramSize.value_or(0); std::transform( this->targetVariantsById.begin(), @@ -843,25 +905,38 @@ void Avr8::setPinState(int variantId, const TargetPinDescriptor& pinDescriptor, if (ioState.has_value()) { auto portSetAddress = padDescriptor.gpioPortSetAddress.value(); - auto portSetRegisterValue = this->readMemory(TargetMemoryType::RAM, portSetAddress, 1); - if (portSetRegisterValue.empty()) { - throw Exception("Failed to read PORT register value"); + if (ioState == TargetPinState::IoState::HIGH + || !padDescriptor.gpioPortClearAddress.has_value() + || padDescriptor.gpioPortClearAddress == portSetAddress + ) { + auto portSetRegisterValue = this->readMemory(TargetMemoryType::RAM, portSetAddress, 1); + + if (portSetRegisterValue.empty()) { + throw Exception("Failed to read PORT register value"); + } + + auto portSetBitset = std::bitset::digits>(portSetRegisterValue.front()); + if (portSetBitset.test(pinNumber) != (ioState == TargetPinState::IoState::HIGH)) { + // PORT set register needs updating + portSetBitset.set(pinNumber, (ioState == TargetPinState::IoState::HIGH)); + + this->writeMemory( + TargetMemoryType::RAM, + portSetAddress, + {static_cast(portSetBitset.to_ulong())} + ); + } } - auto portSetBitset = std::bitset::digits>(portSetRegisterValue.front()); - if (portSetBitset.test(pinNumber) != (ioState == TargetPinState::IoState::HIGH)) { - // PORT set register needs updating - portSetBitset.set(pinNumber, (ioState == TargetPinState::IoState::HIGH)); - - this->writeMemory( - TargetMemoryType::RAM, - portSetAddress, - {static_cast(portSetBitset.to_ulong())} - ); - } - - if (padDescriptor.gpioPortClearAddress.has_value() && padDescriptor.gpioPortClearAddress != portSetAddress) { + /* + * We only need to update the PORT clear register if the IO state was set to LOW, and the clear register is + * not the same register as the set register. + */ + if (ioState == TargetPinState::IoState::LOW + && padDescriptor.gpioPortClearAddress.has_value() + && padDescriptor.gpioPortClearAddress != portSetAddress + ) { // We also need to ensure the PORT clear register value is correct auto portClearAddress = padDescriptor.gpioPortClearAddress.value(); auto portClearRegisterValue = this->readMemory(TargetMemoryType::RAM, portClearAddress, 1); @@ -886,7 +961,7 @@ void Avr8::setPinState(int variantId, const TargetPinDescriptor& pinDescriptor, } bool Avr8::memoryAddressRangeClashesWithIoPortRegisters(TargetMemoryType memoryType, std::uint32_t startAddress, std::uint32_t endAddress) { - auto& targetParameters = this->getTargetParameters(); + auto& targetParameters = this->targetParameters.value(); /* * We're making an assumption here; that all IO port addresses for all AVR8 targets are aligned. I have no idea diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8.hpp b/src/Targets/Microchip/AVR/AVR8/Avr8.hpp index c2051119..980871ef 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8.hpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8.hpp @@ -31,20 +31,34 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit std::map targetVariantsById; /** - * Extracts the ID from the target's memory. - * - * This function will cache the ID value and use the cached version for any subsequent calls. - * - * @return + * Resolves the appropriate TDF for the AVR8 target and populates this->targetDescriptionFile. */ - TargetSignature getId() override; + void loadTargetDescriptionFile(); /** - * Extracts the AVR8 target parameters from the loaded target description file. - * - * @return + * Initiates the AVR8 instance from data extracted from the TDF. */ - virtual TargetParameters& getTargetParameters(); + 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 @@ -57,13 +71,21 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit */ virtual void loadTargetVariants(); - void loadTargetDescriptionFile(); + /** + * Extracts the ID from the target's memory. + * + * This function will cache the ID value and use the cached version for any subsequent calls. + * + * @return + */ + TargetSignature getId() override; public: explicit Avr8() = default; Avr8(std::string name, const TargetSignature& signature): name(std::move(name)) { this->id = signature; this->loadTargetDescriptionFile(); + this->initFromTargetDescriptionFile(); }; /* diff --git a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp index 909537df..f3a34107 100644 --- a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp +++ b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp @@ -51,7 +51,7 @@ TargetDescriptionFile::TargetDescriptionFile( + matchingDescriptionFiles.front().toObject().find("targetDescriptionFilePath")->toString(); Logger::debug("Loading AVR8 target description file: " + descriptionFilePath.toStdString()); - this->init(descriptionFilePath); + Targets::TargetDescription::TargetDescriptionFile::init(descriptionFilePath); } else if (matchingDescriptionFiles.size() > 1) { /* @@ -86,6 +86,27 @@ TargetDescriptionFile::TargetDescriptionFile( } } +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)); + } + } +} + QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() { auto mappingFile = QFile( QString::fromStdString(Paths::resourcesDirPath() + "/TargetDescriptionFiles/AVR/Mapping.json") @@ -276,6 +297,63 @@ std::optional TargetDescriptionFile::getFirstBootSectionMemorySeg return std::nullopt; } +std::optional TargetDescriptionFile::getSignatureMemorySegment() const { + if (this->addressSpacesMappedById.contains("signatures")) { + auto& signaturesAddressSpace = this->addressSpacesMappedById.at("signatures"); + auto& signaturesAddressSpaceSegments = signaturesAddressSpace.memorySegmentsByTypeAndName; + + if (signaturesAddressSpaceSegments.contains(MemorySegmentType::SIGNATURES)) { + return signaturesAddressSpaceSegments.at(MemorySegmentType::SIGNATURES).begin()->second; + } + + } else { + // The signatures memory segment may be part of the data address space + if (this->addressSpacesMappedById.contains("data")) { + auto dataAddressSpace = this->addressSpacesMappedById.at("data"); + + if (dataAddressSpace.memorySegmentsByTypeAndName.contains(MemorySegmentType::SIGNATURES)) { + auto& signatureSegmentsByName = dataAddressSpace.memorySegmentsByTypeAndName.at( + MemorySegmentType::SIGNATURES + ); + + if (signatureSegmentsByName.contains("signatures")) { + return signatureSegmentsByName.at("signatures"); + } + } + } + } + + return std::nullopt; +} + +std::optional TargetDescriptionFile::getFuseMemorySegment() const { + if (this->addressSpacesMappedById.contains("data")) { + auto dataAddressSpace = this->addressSpacesMappedById.at("data"); + + if (dataAddressSpace.memorySegmentsByTypeAndName.contains(MemorySegmentType::FUSES)) { + return dataAddressSpace.memorySegmentsByTypeAndName.at( + MemorySegmentType::SIGNATURES + ).begin()->second; + } + } + + return std::nullopt; +} + +std::optional TargetDescriptionFile::getLockbitsMemorySegment() const { + if (this->addressSpacesMappedById.contains("data")) { + auto dataAddressSpace = this->addressSpacesMappedById.at("data"); + + if (dataAddressSpace.memorySegmentsByTypeAndName.contains(MemorySegmentType::LOCKBITS)) { + return dataAddressSpace.memorySegmentsByTypeAndName.at( + MemorySegmentType::LOCKBITS + ).begin()->second; + } + } + + return std::nullopt; +} + std::optional TargetDescriptionFile::getCpuRegisterGroup() const { auto& modulesByName = this->modulesMappedByName; diff --git a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp index 6024fd69..528a5e9e 100644 --- a/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp +++ b/src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp @@ -1,9 +1,12 @@ #pragma once +#include + #include "src/Targets/TargetDescription/TargetDescriptionFile.hpp" #include "src/Targets/Microchip/AVR/TargetSignature.hpp" #include "src/Targets/Microchip/AVR/AVR8/Family.hpp" +#include "src/Targets/Microchip/AVR/AVR8/PhysicalInterface.hpp" namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription { @@ -44,6 +47,13 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription }; }; + std::set supportedDebugPhysicalInterfaces; + + /** + * 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. @@ -53,6 +63,14 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription */ 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. * @@ -79,6 +97,9 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription [[nodiscard]] std::optional getRegisterMemorySegment() const; [[nodiscard]] std::optional getEepromMemorySegment() const; [[nodiscard]] std::optional getFirstBootSectionMemorySegment() const; + [[nodiscard]] std::optional getSignatureMemorySegment() const; + [[nodiscard]] std::optional getFuseMemorySegment() const; + [[nodiscard]] std::optional getLockbitsMemorySegment() const; [[nodiscard]] std::optional getCpuRegisterGroup() const; [[nodiscard]] std::optional getBootLoadRegisterGroup() const; [[nodiscard]] std::optional getEepromRegisterGroup() const; @@ -95,5 +116,14 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription [[nodiscard]] std::optional getEepromAddressHighRegister() const; [[nodiscard]] std::optional getEepromDataRegister() const; [[nodiscard]] std::optional getEepromControlRegister() const; + + /** + * Returns a set of all supported physical interfaces for debugging. + * + * @return + */ + const auto& getSupportedDebugPhysicalInterfaces() { + return this->supportedDebugPhysicalInterfaces; + }; }; } diff --git a/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp b/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp index 7ddaefee..2c55c29c 100644 --- a/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp +++ b/src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp @@ -18,6 +18,7 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit std::optional flashStartAddress; std::optional ramStartAddress; std::optional ramSize; + std::optional eepromStartAddress; std::optional eepromSize; std::optional eepromPageSize; std::optional eepromAddressRegisterHigh; @@ -45,6 +46,17 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit std::optional productSignaturesPdiOffset; std::optional nvmBaseAddress; + // UPDI specific target params + std::optional ocdModuleAddress; + std::optional programMemoryUpdiStartAddress; + std::optional signatureSegmentStartAddress; + std::optional signatureSegmentSize; + std::optional userSignatureSegmentStartAddress; + std::optional userSignatureSegmentSize; + std::optional fuseSegmentStartAddress; + std::optional fuseSegmentSize; + std::optional lockbitsSegmentStartAddress; + std::optional ioPortAddressRangeStart; std::optional ioPortAddressRangeEnd; };