Added EDBG parameter structs with TDF-based initialisation

This commit is contained in:
Nav
2024-03-25 18:59:15 +00:00
parent dd0b4dd7e1
commit 3c8efa60a6
8 changed files with 421 additions and 348 deletions

View File

@@ -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

View File

@@ -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<std::uint8_t>(
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<std::uint8_t>(
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<std::uint8_t>(
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<std::uint8_t>(
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<std::uint8_t>(
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<std::uint8_t>(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<std::uint16_t>(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<std::uint16_t>(programMemBaseAddress)
);
Logger::debug("Setting UPDI_PROGMEM_BASE_ADDR_MSB AVR8 device parameter");
this->setParameter(
Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB,
static_cast<std::uint8_t>(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<std::uint8_t>(programMemBaseAddress >> 16)
);
}
this->setParameter(
Avr8EdbgParameters::DEVICE_UPDI_24_BIT_ADDRESSING_ENABLE,
parameters.programMemoryStartAddress > 0xFFFF
? static_cast<std::uint8_t>(1)
: static_cast<std::uint8_t>(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<std::uint8_t>(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<std::uint8_t>(parameters.flashPageSize)
);
Logger::debug("Setting UPDI_FLASH_PAGE_SIZE_MSB AVR8 device parameter");
this->setParameter(
Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE_MSB,
static_cast<std::uint8_t>(flashPageSize >> 8)
);
}
Logger::debug("Setting UPDI_FLASH_PAGE_SIZE_MSB AVR8 device parameter");
this->setParameter(
Avr8EdbgParameters::DEVICE_UPDI_FLASH_PAGE_SIZE_MSB,
static_cast<std::uint8_t>(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<std::uint8_t>(1) : static_cast<std::uint8_t>(0)
);
}
void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) {

View File

@@ -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<std::uint16_t>(programMemorySegment.pageSize.value());
this->flashSize = programMemorySegment.size;
this->flashStartWordAddress = static_cast<std::uint32_t>(programMemorySegment.startAddress / 2);
const auto firstBootSectionOptionGroup = targetDescriptionFile.tryGetPropertyGroup(
"boot_section_options.boot_section_1"
);
if (firstBootSectionOptionGroup.has_value()) {
this->bootSectionStartWordAddress = static_cast<std::uint32_t>(
StringService::toUint32(firstBootSectionOptionGroup->get().getProperty("start_address").value) / 2
);
}
this->ramStartAddress = static_cast<std::uint16_t>(ramMemorySegment.startAddress);
this->eepromSize = static_cast<std::uint16_t>(eepromMemorySegment.size);
this->eepromPageSize = static_cast<std::uint8_t>(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<std::uint8_t>(startAddress);
this->eepromAddressRegisterHigh = static_cast<std::uint8_t>(
eearDescriptor->get().size > 1 ? startAddress >> 2 : startAddress
);
} else {
const auto& eearlDescriptor = eepromRegisterGroupDescriptor.getRegisterDescriptor("eearl");
this->eepromAddressRegisterLow = static_cast<std::uint8_t>(eearlDescriptor.startAddress);
this->eepromAddressRegisterHigh = static_cast<std::uint8_t>(
eearlDescriptor.size > 1 ? eearlDescriptor.startAddress >> 2 : eearlDescriptor.startAddress
);
const auto eearhDescriptor = eepromRegisterGroupDescriptor.tryGetRegisterDescriptor("eearh");
if (eearhDescriptor.has_value()) {
this->eepromAddressRegisterHigh = static_cast<std::uint8_t>(eearhDescriptor->get().startAddress);
}
}
this->eepromDataRegisterAddress = static_cast<std::uint8_t>(
eepromRegisterGroupDescriptor.getRegisterDescriptor("eedr").startAddress
);
this->eepromControlRegisterAddress = static_cast<std::uint8_t>(
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<std::uint8_t>(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<std::uint8_t>(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<std::uint8_t>(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;
}
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <cstdint>
#include <optional>
#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<std::uint32_t> 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);
};
}

View File

@@ -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<std::uint16_t>(programMemorySegment.getSection("boot_section").size);
this->flashPageSize = static_cast<std::uint16_t>(programMemorySegment.pageSize.value());
this->eepromSize = static_cast<std::uint16_t>(eepromMemorySegment.size);
this->eepromPageSize = static_cast<std::uint8_t>(eepromMemorySegment.pageSize.value());
this->nvmModuleBaseAddress = static_cast<std::uint16_t>(
targetDescriptionFile.getTargetPeripheralDescriptor("nvm").getRegisterGroupDescriptor("nvm").startAddress()
);
}
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include <cstdint>
#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);
};
}

View File

@@ -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<std::uint16_t>(programMemorySegment.pageSize.value());
this->eepromStartAddress = static_cast<std::uint16_t>(eepromMemorySegment.startAddress);
this->eepromSize = static_cast<std::uint16_t>(eepromMemorySegment.size);
this->eepromPageSize = static_cast<std::uint8_t>(eepromMemorySegment.pageSize.value());
this->signatureSegmentStartAddress = static_cast<std::uint16_t>(signatureMemorySegment.startAddress);
this->fuseSegmentSize = static_cast<std::uint16_t>(fuseMemorySegment.size);
this->fuseSegmentStartAddress = static_cast<std::uint16_t>(fuseMemorySegment.startAddress);
this->lockbitSegmentStartAddress = static_cast<std::uint16_t>(lockbitMemorySegment.startAddress);
this->nvmModuleBaseAddress = static_cast<std::uint16_t>(
targetDescriptionFile.getTargetPeripheralDescriptor("nvmctrl").getRegisterGroupDescriptor(
"nvmctrl"
).startAddress()
);
}
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include <cstdint>
#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);
};
}