From 3c8efa60a6dd93b74a16bf8740be8e35b296f87d Mon Sep 17 00:00:00 2001 From: Nav Date: Mon, 25 Mar 2024 18:59:15 +0000 Subject: [PATCH] Added EDBG parameter structs with TDF-based initialisation --- src/DebugToolDrivers/CMakeLists.txt | 3 + .../Protocols/EDBG/AVR/EdbgAvr8Interface.cpp | 458 +++++------------- .../AVR8Generic/DebugWireJtagParameters.cpp | 130 +++++ .../AVR8Generic/DebugWireJtagParameters.hpp | 35 ++ .../Parameters/AVR8Generic/PdiParameters.cpp | 37 ++ .../Parameters/AVR8Generic/PdiParameters.hpp | 34 ++ .../Parameters/AVR8Generic/UpdiParameters.cpp | 39 ++ .../Parameters/AVR8Generic/UpdiParameters.hpp | 33 ++ 8 files changed, 421 insertions(+), 348 deletions(-) create mode 100644 src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.cpp create mode 100644 src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.hpp create mode 100644 src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.cpp create mode 100644 src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.hpp create mode 100644 src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.cpp create mode 100644 src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.hpp diff --git a/src/DebugToolDrivers/CMakeLists.txt b/src/DebugToolDrivers/CMakeLists.txt index 6ab87fe6..81856dc0 100755 --- a/src/DebugToolDrivers/CMakeLists.txt +++ b/src/DebugToolDrivers/CMakeLists.txt @@ -19,6 +19,9 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/AVR/ResponseFrames/EDBGControl/EdbgControlResponseFrame.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/AVR/AvrEvent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/AVR/Events/AVR8Generic/BreakEvent.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/EdbgInterface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/EdbgTargetPowerManagementInterface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/Protocols/EDBG/AVR/EdbgAvr8Interface.cpp diff --git a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/EdbgAvr8Interface.cpp b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/EdbgAvr8Interface.cpp index 179883bf..df9d44d3 100644 --- a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/EdbgAvr8Interface.cpp +++ b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/EdbgAvr8Interface.cpp @@ -39,6 +39,10 @@ #include "CommandFrames/AVR8Generic/LeaveProgrammingMode.hpp" #include "CommandFrames/AVR8Generic/EraseMemory.hpp" +#include "Parameters/AVR8Generic/DebugWireJtagParameters.hpp" +#include "Parameters/AVR8Generic/PdiParameters.hpp" +#include "Parameters/AVR8Generic/UpdiParameters.hpp" + // AVR events #include "Events/AVR8Generic/BreakEvent.hpp" @@ -1048,447 +1052,205 @@ namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr } void EdbgAvr8Interface::setDebugWireAndJtagParameters() { - if (this->targetParameters.flashPageSize.has_value()) { - Logger::debug("Setting FLASH_PAGE_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_FLASH_PAGE_SIZE, - this->targetParameters.flashPageSize.value() - ); - } + const auto parameters = Parameters::Avr8Generic::DebugWireJtagParameters(this->targetDescriptionFile); - if (this->targetParameters.flashSize.has_value()) { - Logger::debug("Setting FLASH_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_FLASH_SIZE, - this->targetParameters.flashSize.value() - ); - } + Logger::debug("Setting FLASH_PAGE_SIZE AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_FLASH_PAGE_SIZE, parameters.flashPageSize); - if (this->targetParameters.flashStartAddress.has_value()) { - Logger::debug("Setting FLASH_BASE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_FLASH_BASE, - this->targetParameters.flashStartAddress.value() - ); - } + Logger::debug("Setting FLASH_SIZE AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_FLASH_SIZE, parameters.flashSize); - if (this->targetParameters.ramStartAddress.has_value()) { - Logger::debug("Setting SRAM_START AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_SRAM_START, - this->targetParameters.ramStartAddress.value() - ); - } + Logger::debug("Setting FLASH_BASE AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_FLASH_BASE, parameters.flashStartWordAddress); - if (this->targetParameters.eepromSize.has_value()) { - Logger::debug("Setting EEPROM_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_EEPROM_SIZE, - this->targetParameters.eepromSize.value() - ); - } - - if (this->targetParameters.eepromPageSize.has_value()) { - Logger::debug("Setting EEPROM_PAGE_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_EEPROM_PAGE_SIZE, - this->targetParameters.eepromPageSize.value() - ); - } - - if (this->targetParameters.ocdRevision.has_value()) { - Logger::debug("Setting OCD_REVISION AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_OCD_REVISION, - this->targetParameters.ocdRevision.value() - ); - } - - if (this->targetParameters.ocdDataRegister.has_value()) { - Logger::debug("Setting OCD_DATA_REGISTER AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_OCD_DATA_REGISTER, - this->targetParameters.ocdDataRegister.value() - ); - } - - if (this->targetParameters.spmcRegisterStartAddress.has_value()) { - Logger::debug("Setting SPMCR_REGISTER AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_SPMCR_REGISTER, - this->targetParameters.spmcRegisterStartAddress.value() - ); - } - - if (this->targetParameters.bootSectionStartAddress.has_value()) { + if (parameters.bootSectionStartWordAddress.has_value()) { Logger::debug("Setting BOOT_START_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_BOOT_START_ADDR, - this->targetParameters.bootSectionStartAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_BOOT_START_ADDR, *(parameters.bootSectionStartWordAddress)); } - /* - * All addresses for registers that reside in the mapped IO memory segment include the mapped IO segment offset - * (start address). But the EDBG protocol requires *some* of these addresses to be stripped of this offset - * before sending them as target parameters. - * - * This applies to the following addresses: - * - * - OSCALL Address - * - EEARL Address - * - EEARH Address - * - EECR Address - * - EEDR Address - * - * It *doesn't* seem to apply to the SPMCR or OCDDR address. - */ - auto mappedIoStartAddress = this->targetParameters.mappedIoSegmentStartAddress.value_or(0); + Logger::debug("Setting SRAM_START AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_SRAM_START, parameters.ramStartAddress); - if (this->targetParameters.osccalAddress.has_value()) { - Logger::debug("Setting OSCCAL_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_OSCCAL_ADDR, - static_cast( - this->targetParameters.osccalAddress.value() - mappedIoStartAddress - ) - ); - } + Logger::debug("Setting EEPROM_SIZE AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_EEPROM_SIZE, parameters.eepromSize); - if (this->targetParameters.eepromAddressRegisterLow.has_value()) { - Logger::debug("Setting EEARL_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_EEARL_ADDR, - static_cast( - this->targetParameters.eepromAddressRegisterLow.value() - mappedIoStartAddress - ) - ); - } + Logger::debug("Setting EEPROM_PAGE_SIZE AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_EEPROM_PAGE_SIZE, parameters.eepromPageSize); - if (this->targetParameters.eepromAddressRegisterHigh.has_value()) { - Logger::debug("Setting EEARH_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_EEARH_ADDR, - static_cast( - this->targetParameters.eepromAddressRegisterHigh.value() - mappedIoStartAddress - ) - ); - } + Logger::debug("Setting OCD_REVISION AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_OCD_REVISION, parameters.ocdRevision); - if (this->targetParameters.eepromControlRegisterAddress.has_value()) { - Logger::debug("Setting EECR_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_EECR_ADDR, - static_cast( - this->targetParameters.eepromControlRegisterAddress.value() - mappedIoStartAddress - ) - ); - } + Logger::debug("Setting OCD_DATA_REGISTER AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_OCD_DATA_REGISTER, parameters.ocdDataRegister); - if (this->targetParameters.eepromDataRegisterAddress.has_value()) { - Logger::debug("Setting EEDR_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_EEDR_ADDR, - static_cast( - this->targetParameters.eepromDataRegisterAddress.value() - mappedIoStartAddress - ) - ); - } + Logger::debug("Setting EEARL_ADDR AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_EEARL_ADDR, parameters.eepromAddressRegisterLow); + + Logger::debug("Setting EEARH_ADDR AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_EEARH_ADDR, parameters.eepromAddressRegisterHigh); + + Logger::debug("Setting EECR_ADDR AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_EECR_ADDR, parameters.eepromControlRegisterAddress); + + Logger::debug("Setting EEDR_ADDR AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_EEDR_ADDR, parameters.eepromDataRegisterAddress); + + Logger::debug("Setting SPMCR_REGISTER AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_SPMCR_REGISTER, parameters.spmcRegisterStartAddress); + + Logger::debug("Setting OSCCAL_ADDR AVR8 device parameter"); + this->setParameter(Avr8EdbgParameters::DEVICE_OSCCAL_ADDR, parameters.osccalAddress); } void EdbgAvr8Interface::setPdiParameters() { - if (!this->targetParameters.appSectionPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: APPL_BASE_ADDR"); - } - - if (!this->targetParameters.bootSectionPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: BOOT_BASE_ADDR"); - } - - if (!this->targetParameters.appSectionSize.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: APPLICATION_BYTES"); - } - - if (!this->targetParameters.bootSectionSize.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: BOOT_BYTES"); - } - - if (!this->targetParameters.eepromPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: EEPROM_BASE_ADDR"); - } - - if (!this->targetParameters.fuseRegistersPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: FUSE_BASE_ADDR"); - } - - if (!this->targetParameters.lockRegistersPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: LOCKBIT_BASE_ADDR"); - } - - if (!this->targetParameters.userSignaturesPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: USER_SIGN_BASE_ADDR"); - } - - if (!this->targetParameters.productSignaturesPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: PROD_SIGN_BASE_ADDR"); - } - - if (!this->targetParameters.ramPdiOffset.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: DATA_BASE_ADDR"); - } - - if (!this->targetParameters.flashPageSize.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: FLASH_PAGE_BYTES"); - } - - if (!this->targetParameters.eepromSize.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: EEPROM_SIZE"); - } - - if (!this->targetParameters.eepromPageSize.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: EEPROM_PAGE_SIZE"); - } - - if (!this->targetParameters.nvmModuleBaseAddress.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: NVM_BASE"); - } - - if (!this->targetParameters.mcuModuleBaseAddress.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: SIGNATURE_OFFSET (MCU module base address)"); - } + const auto parameters = Parameters::Avr8Generic::PdiParameters(this->targetDescriptionFile); Logger::debug("Setting APPL_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_APPL_BASE_ADDR, - this->targetParameters.appSectionPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_APPL_BASE_ADDR, parameters.appSectionPdiOffset); Logger::debug("Setting BOOT_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BASE_ADDR, - this->targetParameters.bootSectionPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BASE_ADDR, parameters.bootSectionPdiOffset); Logger::debug("Setting EEPROM_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_BASE_ADDR, - this->targetParameters.eepromPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_BASE_ADDR, parameters.eepromPdiOffset); Logger::debug("Setting FUSE_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_FUSE_BASE_ADDR, - this->targetParameters.fuseRegistersPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_FUSE_BASE_ADDR, parameters.fuseRegistersPdiOffset); Logger::debug("Setting LOCKBIT_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_LOCKBIT_BASE_ADDR, - this->targetParameters.lockRegistersPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_LOCKBIT_BASE_ADDR, parameters.lockRegistersPdiOffset); Logger::debug("Setting USER_SIGN_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_USER_SIGN_BASE_ADDR, - this->targetParameters.userSignaturesPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_USER_SIGN_BASE_ADDR, parameters.userSignaturesPdiOffset); Logger::debug("Setting PROD_SIGN_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_PROD_SIGN_BASE_ADDR, - this->targetParameters.productSignaturesPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_PROD_SIGN_BASE_ADDR, parameters.prodSignaturesPdiOffset); Logger::debug("Setting DATA_BASE_ADDR AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_DATA_BASE_ADDR, - this->targetParameters.ramPdiOffset.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_DATA_BASE_ADDR, parameters.ramPdiOffset); Logger::debug("Setting APPLICATION_BYTES AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_APPLICATION_BYTES, - this->targetParameters.appSectionSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_APPLICATION_BYTES, parameters.appSectionSize); Logger::debug("Setting BOOT_BYTES AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BYTES, - this->targetParameters.bootSectionSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_BOOT_BYTES, parameters.bootSectionSize); Logger::debug("Setting FLASH_PAGE_BYTES AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_FLASH_PAGE_BYTES, - this->targetParameters.flashPageSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_FLASH_PAGE_BYTES, parameters.flashPageSize); Logger::debug("Setting EEPROM_SIZE AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_SIZE, - this->targetParameters.eepromSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_SIZE, parameters.eepromSize); Logger::debug("Setting EEPROM_PAGE_SIZE AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_PAGE_SIZE, - static_cast(this->targetParameters.eepromPageSize.value()) - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_EEPROM_PAGE_SIZE, parameters.eepromPageSize); Logger::debug("Setting NVM_BASE AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_NVM_BASE, - this->targetParameters.nvmModuleBaseAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_NVM_BASE, parameters.nvmModuleBaseAddress); Logger::debug("Setting SIGNATURE_OFFSET AVR8 parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_XMEGA_SIGNATURE_OFFSET, - this->targetParameters.mcuModuleBaseAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_XMEGA_SIGNATURE_OFFSET, parameters.signaturesPdiOffset); } void EdbgAvr8Interface::setUpdiParameters() { - if (!this->targetParameters.signatureSegmentStartAddress.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: SIGNATURE BASE ADDRESS"); - } + const auto parameters = Parameters::Avr8Generic::UpdiParameters(this->targetDescriptionFile); - if (!this->targetParameters.eepromPageSize.has_value()) { - throw DeviceInitializationFailure("Missing required parameter: UPDI_EEPROM_PAGE_SIZE"); - } + /* + * 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). + */ + Logger::debug("Setting UPDI_PROGMEM_BASE_ADDR AVR8 device parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR, + static_cast(parameters.programMemoryStartAddress) + ); - 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). - */ - const auto programMemBaseAddress = this->targetParameters.programMemoryUpdiStartAddress.value(); - Logger::debug("Setting UPDI_PROGMEM_BASE_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR, - static_cast(programMemBaseAddress) - ); + Logger::debug("Setting UPDI_PROGMEM_BASE_ADDR_MSB AVR8 device parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB, + static_cast(parameters.programMemoryStartAddress >> 16) + ); - Logger::debug("Setting UPDI_PROGMEM_BASE_ADDR_MSB AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB, - static_cast(programMemBaseAddress >> 16) - ); - } + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_24_BIT_ADDRESSING_ENABLE, + parameters.programMemoryStartAddress > 0xFFFF + ? static_cast(1) + : static_cast(0) + ); - 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 UPDI_FLASH_PAGE_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE, - static_cast(flashPageSize) - ); + /* + * 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). + */ + Logger::debug("Setting UPDI_FLASH_PAGE_SIZE AVR8 device parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE, + static_cast(parameters.flashPageSize) + ); - Logger::debug("Setting UPDI_FLASH_PAGE_SIZE_MSB AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE_MSB, - static_cast(flashPageSize >> 8) - ); - } + Logger::debug("Setting UPDI_FLASH_PAGE_SIZE_MSB AVR8 device parameter"); + this->setParameter( + Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE_MSB, + static_cast(parameters.flashPageSize >> 8) + ); if (this->targetParameters.eepromPageSize.has_value()) { Logger::debug("Setting UPDI_EEPROM_PAGE_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_EEPROM_PAGE_SIZE, - this->targetParameters.eepromPageSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_EEPROM_PAGE_SIZE, parameters.eepromPageSize); } if (this->targetParameters.nvmModuleBaseAddress.has_value()) { Logger::debug("Setting UPDI_NVMCTRL_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_NVMCTRL_ADDR, - this->targetParameters.nvmModuleBaseAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_NVMCTRL_ADDR, parameters.nvmModuleBaseAddress); } if (this->targetParameters.ocdModuleAddress.has_value()) { Logger::debug("Setting UPDI_OCD_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_OCD_ADDR, - this->targetParameters.ocdModuleAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_OCD_ADDR, parameters.ocdModuleAddress); } if (this->targetParameters.flashSize.has_value()) { Logger::debug("Setting UPDI_FLASH_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_FLASH_SIZE, - this->targetParameters.flashSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_FLASH_SIZE, parameters.flashSize); } if (this->targetParameters.eepromSize.has_value()) { Logger::debug("Setting UPDI_EEPROM_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_EEPROM_SIZE, - this->targetParameters.eepromSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_EEPROM_SIZE, parameters.eepromSize); } if (this->targetParameters.eepromStartAddress.has_value()) { Logger::debug("Setting UPDI_EEPROM_BASE_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_EEPROM_BASE_ADDR, - this->targetParameters.eepromStartAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_EEPROM_BASE_ADDR, parameters.eepromStartAddress); } if (this->targetParameters.signatureSegmentStartAddress.has_value()) { Logger::debug("Setting UPDI_SIG_BASE_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_SIG_BASE_ADDR, - this->targetParameters.signatureSegmentStartAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_SIG_BASE_ADDR, parameters.signatureSegmentStartAddress); } if (this->targetParameters.fuseSegmentStartAddress.has_value()) { Logger::debug("Setting UPDI_FUSE_BASE_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_FUSE_BASE_ADDR, - this->targetParameters.fuseSegmentStartAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_FUSE_BASE_ADDR, parameters.fuseSegmentStartAddress); } if (this->targetParameters.fuseSegmentSize.has_value()) { Logger::debug("Setting UPDI_FUSE_SIZE AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_FUSE_SIZE, - this->targetParameters.fuseSegmentSize.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_FUSE_SIZE, parameters.fuseSegmentSize); } if (this->targetParameters.lockbitsSegmentStartAddress.has_value()) { Logger::debug("Setting UPDI_LOCK_BASE_ADDR AVR8 device parameter"); - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_LOCK_BASE_ADDR, - this->targetParameters.lockbitsSegmentStartAddress.value() - ); + this->setParameter(Avr8EdbgParameters::DEVICE_UPDI_LOCK_BASE_ADDR, parameters.lockbitSegmentStartAddress); } - - this->setParameter( - Avr8EdbgParameters::DEVICE_UPDI_24_BIT_ADDRESSING_ENABLE, - this->targetParameters.programMemoryUpdiStartAddress.value_or(0) > 0xFFFF ? - static_cast(1) : static_cast(0) - ); } void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) { diff --git a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.cpp b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.cpp new file mode 100644 index 00000000..168d1da0 --- /dev/null +++ b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.cpp @@ -0,0 +1,130 @@ +#include "DebugWireJtagParameters.hpp" + +#include "src/Services/StringService.hpp" + +#include "src/Exceptions/InternalFatalErrorException.hpp" + +namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr::Parameters::Avr8Generic +{ + DebugWireJtagParameters::DebugWireJtagParameters( + const Targets::Microchip::Avr::Avr8Bit::TargetDescriptionFile& targetDescriptionFile + ) { + using Services::StringService; + + const auto& programMemorySegment = targetDescriptionFile.getProgramMemorySegment(); + const auto& ramMemorySegment = targetDescriptionFile.getRamMemorySegment(); + const auto& eepromMemorySegment = targetDescriptionFile.getEepromMemorySegment(); + + this->flashPageSize = static_cast(programMemorySegment.pageSize.value()); + this->flashSize = programMemorySegment.size; + this->flashStartWordAddress = static_cast(programMemorySegment.startAddress / 2); + + const auto firstBootSectionOptionGroup = targetDescriptionFile.tryGetPropertyGroup( + "boot_section_options.boot_section_1" + ); + if (firstBootSectionOptionGroup.has_value()) { + this->bootSectionStartWordAddress = static_cast( + StringService::toUint32(firstBootSectionOptionGroup->get().getProperty("start_address").value) / 2 + ); + } + + this->ramStartAddress = static_cast(ramMemorySegment.startAddress); + this->eepromSize = static_cast(eepromMemorySegment.size); + this->eepromPageSize = static_cast(eepromMemorySegment.pageSize.value()); + + const auto& ocdPropertyGroup = targetDescriptionFile.getPropertyGroup("ocd"); + this->ocdRevision = StringService::toUint8(ocdPropertyGroup.getProperty("ocd_revision").value); + this->ocdDataRegister = StringService::toUint8(ocdPropertyGroup.getProperty("ocd_datareg").value); + + const auto& eepromRegisterGroupDescriptor = targetDescriptionFile.getTargetPeripheralDescriptor("eeprom") + .getRegisterGroupDescriptor("eeprom"); + + const auto& eearDescriptor = eepromRegisterGroupDescriptor.tryGetRegisterDescriptor("eear"); + if (eearDescriptor.has_value()) { + const auto startAddress = eearDescriptor->get().startAddress; + this->eepromAddressRegisterLow = static_cast(startAddress); + this->eepromAddressRegisterHigh = static_cast( + eearDescriptor->get().size > 1 ? startAddress >> 2 : startAddress + ); + + } else { + const auto& eearlDescriptor = eepromRegisterGroupDescriptor.getRegisterDescriptor("eearl"); + this->eepromAddressRegisterLow = static_cast(eearlDescriptor.startAddress); + this->eepromAddressRegisterHigh = static_cast( + eearlDescriptor.size > 1 ? eearlDescriptor.startAddress >> 2 : eearlDescriptor.startAddress + ); + + const auto eearhDescriptor = eepromRegisterGroupDescriptor.tryGetRegisterDescriptor("eearh"); + if (eearhDescriptor.has_value()) { + this->eepromAddressRegisterHigh = static_cast(eearhDescriptor->get().startAddress); + } + } + + this->eepromDataRegisterAddress = static_cast( + eepromRegisterGroupDescriptor.getRegisterDescriptor("eedr").startAddress + ); + + this->eepromControlRegisterAddress = static_cast( + eepromRegisterGroupDescriptor.getRegisterDescriptor("eecr").startAddress + ); + + const auto& cpuRegisterGroupDescriptor = targetDescriptionFile.getTargetPeripheralDescriptor("cpu") + .getRegisterGroupDescriptor("cpu"); + + const auto spmcsrDescriptor = cpuRegisterGroupDescriptor.tryGetRegisterDescriptor("spmcsr") + ?: cpuRegisterGroupDescriptor.tryGetRegisterDescriptor("spmcr"); + + if (spmcsrDescriptor.has_value()) { + this->spmcRegisterStartAddress = static_cast(spmcsrDescriptor->get().startAddress); + + } else { + const auto& bootLoaderRegisterGroupDescriptor = targetDescriptionFile.getTargetPeripheralDescriptor( + "boot_load" + ).getRegisterGroupDescriptor("boot_load"); + + const auto spmcsrDescriptor = bootLoaderRegisterGroupDescriptor.tryGetRegisterDescriptor("spmcsr") + ?: bootLoaderRegisterGroupDescriptor.tryGetRegisterDescriptor("spmcr"); + + if (!spmcsrDescriptor.has_value()) { + throw Exceptions::InternalFatalErrorException("Could not extract SPMCS register from TDF"); + } + + this->spmcRegisterStartAddress = static_cast(spmcsrDescriptor->get().startAddress); + } + + const auto osccalDescriptor = cpuRegisterGroupDescriptor.tryGetRegisterDescriptor("osccal") + ?: cpuRegisterGroupDescriptor.tryGetRegisterDescriptor("osccal0") + ?: cpuRegisterGroupDescriptor.tryGetRegisterDescriptor("osccal1") + ?: cpuRegisterGroupDescriptor.tryGetRegisterDescriptor("fosccal") + ?: cpuRegisterGroupDescriptor.tryGetRegisterDescriptor("sosccala"); + + if (!osccalDescriptor.has_value()) { + throw Exceptions::InternalFatalErrorException("Could not extract OSCCAL register from TDF"); + } + + this->osccalAddress = static_cast(osccalDescriptor->get().startAddress); + + /* + * All addresses for registers that reside in the IO memory segment include the IO segment offset + * (start address). But the EDBG protocol requires *some* of these addresses to be stripped of this offset + * before sending them as target parameters. + * + * This applies to the following addresses: + * + * - OSCALL Address + * - EEARL Address + * - EEARH Address + * - EECR Address + * - EEDR Address + * + * It does *not* seem to apply to the SPMCR or OCDDR address. + */ + const auto& ioMemorySegment = targetDescriptionFile.getIoMemorySegment(); + + this->osccalAddress -= ioMemorySegment.startAddress; + this->eepromAddressRegisterLow -= ioMemorySegment.startAddress; + this->eepromAddressRegisterHigh -= ioMemorySegment.startAddress; + this->eepromControlRegisterAddress -= ioMemorySegment.startAddress; + this->eepromDataRegisterAddress -= ioMemorySegment.startAddress; + } +} diff --git a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.hpp b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.hpp new file mode 100644 index 00000000..16efa0b5 --- /dev/null +++ b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/DebugWireJtagParameters.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "src/Targets/Microchip/AVR/AVR8/TargetDescriptionFile.hpp" + +namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr::Parameters::Avr8Generic +{ + /** + * EDBG parameters for debugWire and JTAG AVR targets. + * + * See Microchip's "EDBG-based Tools Protocols" document for more on these parameters. + */ + struct DebugWireJtagParameters + { + std::uint16_t flashPageSize; + std::uint32_t flashSize; + std::uint32_t flashStartWordAddress; + std::optional bootSectionStartWordAddress; + std::uint16_t ramStartAddress; + std::uint16_t eepromSize; + std::uint8_t eepromPageSize; + std::uint8_t ocdRevision; + std::uint8_t ocdDataRegister; + std::uint8_t eepromAddressRegisterHigh; + std::uint8_t eepromAddressRegisterLow; + std::uint8_t eepromDataRegisterAddress; + std::uint8_t eepromControlRegisterAddress; + std::uint8_t spmcRegisterStartAddress; + std::uint8_t osccalAddress; + + DebugWireJtagParameters(const Targets::Microchip::Avr::Avr8Bit::TargetDescriptionFile& targetDescriptionFile); + }; +} diff --git a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.cpp b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.cpp new file mode 100644 index 00000000..ae6120ca --- /dev/null +++ b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.cpp @@ -0,0 +1,37 @@ +#include "PdiParameters.hpp" + +#include "src/Services/StringService.hpp" + +namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr::Parameters::Avr8Generic +{ + PdiParameters::PdiParameters( + const Targets::Microchip::Avr::Avr8Bit::TargetDescriptionFile& targetDescriptionFile + ) { + using Services::StringService; + + const auto& pdiGroup = targetDescriptionFile.getPropertyGroup("pdi_interface"); + + this->appSectionPdiOffset = StringService::toUint32(pdiGroup.getProperty("app_section_offset").value); + this->bootSectionPdiOffset = StringService::toUint32(pdiGroup.getProperty("boot_section_offset").value); + this->eepromPdiOffset = StringService::toUint32(pdiGroup.getProperty("eeprom_offset").value); + this->fuseRegistersPdiOffset = StringService::toUint32(pdiGroup.getProperty("fuse_registers_offset").value); + this->lockRegistersPdiOffset = StringService::toUint32(pdiGroup.getProperty("lock_registers_offset").value); + this->userSignaturesPdiOffset = StringService::toUint32(pdiGroup.getProperty("user_signatures_offset").value); + this->prodSignaturesPdiOffset = StringService::toUint32(pdiGroup.getProperty("prod_signatures_offset").value); + this->ramPdiOffset = StringService::toUint32(pdiGroup.getProperty("datamem_offset").value); + this->signaturesPdiOffset = StringService::toUint16(pdiGroup.getProperty("signature_offset").value); + + const auto& programMemorySegment = targetDescriptionFile.getProgramMemorySegment(); + const auto& eepromMemorySegment = targetDescriptionFile.getEepromMemorySegment(); + + this->appSectionSize = programMemorySegment.getSection("app_section").size; + this->bootSectionSize = static_cast(programMemorySegment.getSection("boot_section").size); + this->flashPageSize = static_cast(programMemorySegment.pageSize.value()); + this->eepromSize = static_cast(eepromMemorySegment.size); + this->eepromPageSize = static_cast(eepromMemorySegment.pageSize.value()); + + this->nvmModuleBaseAddress = static_cast( + targetDescriptionFile.getTargetPeripheralDescriptor("nvm").getRegisterGroupDescriptor("nvm").startAddress() + ); + } +} diff --git a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.hpp b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.hpp new file mode 100644 index 00000000..23379fd5 --- /dev/null +++ b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/PdiParameters.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "src/Targets/Microchip/AVR/AVR8/TargetDescriptionFile.hpp" + +namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr::Parameters::Avr8Generic +{ + /** + * EDBG parameters for PDI-enabled (XMega) AVR targets. + * + * See Microchip's "EDBG-based Tools Protocols" document for more on these parameters. + */ + struct PdiParameters + { + std::uint32_t appSectionPdiOffset; + std::uint32_t bootSectionPdiOffset; + std::uint32_t eepromPdiOffset; + std::uint32_t fuseRegistersPdiOffset; + std::uint32_t lockRegistersPdiOffset; + std::uint32_t userSignaturesPdiOffset; + std::uint32_t prodSignaturesPdiOffset; + std::uint32_t ramPdiOffset; + std::uint32_t appSectionSize; + std::uint16_t bootSectionSize; + std::uint16_t flashPageSize; + std::uint16_t eepromSize; + std::uint8_t eepromPageSize; + std::uint16_t nvmModuleBaseAddress; + std::uint16_t signaturesPdiOffset; + + PdiParameters(const Targets::Microchip::Avr::Avr8Bit::TargetDescriptionFile& targetDescriptionFile); + }; +} diff --git a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.cpp b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.cpp new file mode 100644 index 00000000..a41fb879 --- /dev/null +++ b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.cpp @@ -0,0 +1,39 @@ +#include "UpdiParameters.hpp" + +#include "src/Services/StringService.hpp" + +namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr::Parameters::Avr8Generic +{ + UpdiParameters::UpdiParameters( + const Targets::Microchip::Avr::Avr8Bit::TargetDescriptionFile& targetDescriptionFile + ) { + using Services::StringService; + + const auto& updiGroup = targetDescriptionFile.getPropertyGroup("updi_interface"); + + this->programMemoryStartAddress = StringService::toUint32(updiGroup.getProperty("progmem_offset").value); + this->ocdModuleAddress = StringService::toUint16(updiGroup.getProperty("ocd_base_addr").value); + + const auto& programMemorySegment = targetDescriptionFile.getProgramMemorySegment(); + const auto& eepromMemorySegment = targetDescriptionFile.getEepromMemorySegment(); + const auto& signatureMemorySegment = targetDescriptionFile.getSignatureMemorySegment(); + const auto& fuseMemorySegment = targetDescriptionFile.getFuseMemorySegment(); + const auto& lockbitMemorySegment = targetDescriptionFile.getLockbitMemorySegment(); + + this->flashSize = programMemorySegment.size; + this->flashPageSize = static_cast(programMemorySegment.pageSize.value()); + this->eepromStartAddress = static_cast(eepromMemorySegment.startAddress); + this->eepromSize = static_cast(eepromMemorySegment.size); + this->eepromPageSize = static_cast(eepromMemorySegment.pageSize.value()); + this->signatureSegmentStartAddress = static_cast(signatureMemorySegment.startAddress); + this->fuseSegmentSize = static_cast(fuseMemorySegment.size); + this->fuseSegmentStartAddress = static_cast(fuseMemorySegment.startAddress); + this->lockbitSegmentStartAddress = static_cast(lockbitMemorySegment.startAddress); + + this->nvmModuleBaseAddress = static_cast( + targetDescriptionFile.getTargetPeripheralDescriptor("nvmctrl").getRegisterGroupDescriptor( + "nvmctrl" + ).startAddress() + ); + } +} diff --git a/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.hpp b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.hpp new file mode 100644 index 00000000..bac99bce --- /dev/null +++ b/src/DebugToolDrivers/Microchip/Protocols/EDBG/AVR/Parameters/AVR8Generic/UpdiParameters.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "src/Targets/Microchip/AVR/AVR8/TargetDescriptionFile.hpp" + +namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr::Parameters::Avr8Generic +{ + /** + * EDBG parameters for UPDI-enabled AVR targets. + * + * See Microchip's "EDBG-based Tools Protocols" document for more on these parameters. + * BTW that document seems to be a little outdated. It doesn't list most of these parameters. I discovered the + * unlisted ones by looking at other open-source codebases and reverse engineering. + */ + struct UpdiParameters + { + std::uint32_t programMemoryStartAddress; + std::uint16_t flashPageSize; + std::uint8_t eepromPageSize; + std::uint16_t nvmModuleBaseAddress; + std::uint16_t ocdModuleAddress; + std::uint32_t flashSize; + std::uint16_t eepromSize; + std::uint16_t fuseSegmentSize; + std::uint16_t eepromStartAddress; + std::uint16_t signatureSegmentStartAddress; + std::uint16_t fuseSegmentStartAddress; + std::uint16_t lockbitSegmentStartAddress; + + UpdiParameters(const Targets::Microchip::Avr::Avr8Bit::TargetDescriptionFile& targetDescriptionFile); + }; +}