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 c8415947..b98740d3 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp @@ -720,16 +720,18 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr return this->writeMemory(avr8MemoryType, startAddress, buffer); } - void EdbgAvr8Interface::eraseProgramMemorySection(ProgramMemorySection section) { - if (this->configVariant != Avr8ConfigVariant::XMEGA) { - throw Exception("AVR8 erase command not supported for non-XMEGA config variants."); + void EdbgAvr8Interface::eraseProgramMemory(std::optional section) { + if (this->configVariant == Avr8ConfigVariant::DEBUG_WIRE) { + throw Exception("AVR8 erase command not supported for debugWire config variant."); } auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( EraseMemory( - section == ProgramMemorySection::BOOT - ? Avr8EraseMemoryMode::BOOT_SECTION - : Avr8EraseMemoryMode::APPLICATION_SECTION + section.has_value() + ? section == ProgramMemorySection::BOOT + ? Avr8EraseMemoryMode::BOOT_SECTION + : Avr8EraseMemoryMode::APPLICATION_SECTION + : Avr8EraseMemoryMode::CHIP ) ); 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 92e5fc52..d411bc53 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp @@ -243,11 +243,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr ) override; /** - * Issues the "Erase" command to erase a particular section of program memory. + * Issues the "Erase" command to erase a particular section of program memory, or the entire chip. * * @param section */ - void eraseProgramMemorySection(Targets::Microchip::Avr::Avr8Bit::ProgramMemorySection section) override; + void eraseProgramMemory( + std::optional section = std::nullopt + ) override; /** * Returns the current state of the target. diff --git a/src/DebugToolDrivers/TargetInterfaces/Microchip/AVR/AVR8/Avr8DebugInterface.hpp b/src/DebugToolDrivers/TargetInterfaces/Microchip/AVR/AVR8/Avr8DebugInterface.hpp index 37ced9d2..7f78f704 100644 --- a/src/DebugToolDrivers/TargetInterfaces/Microchip/AVR/AVR8/Avr8DebugInterface.hpp +++ b/src/DebugToolDrivers/TargetInterfaces/Microchip/AVR/AVR8/Avr8DebugInterface.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp" @@ -196,11 +197,14 @@ namespace Bloom::DebugToolDrivers::TargetInterfaces::Microchip::Avr::Avr8 ) = 0; /** - * Should erase a particular program memory section. + * Should erase the target's entire program memory, or a specific section where applicable. * * @param section + * The section to erase, or std::nullopt to erase the entire program memory. */ - virtual void eraseProgramMemorySection(Targets::Microchip::Avr::Avr8Bit::ProgramMemorySection section) = 0; + virtual void eraseProgramMemory( + std::optional section = std::nullopt + ) = 0; /** * Should obtain the current target state. diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp index 0aaaf2d5..83536926 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp @@ -325,42 +325,48 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit void Avr8::writeMemory(TargetMemoryType memoryType, std::uint32_t startAddress, const TargetMemoryBuffer& buffer) { if ( memoryType == TargetMemoryType::FLASH && this->programmingSession.has_value() - && this->targetConfig->physicalInterface == PhysicalInterface::PDI + && this->targetConfig->physicalInterface != PhysicalInterface::DEBUG_WIRE ) { - // For PDI targets, we must erase the appropriate section before the first write. - const auto startSection = this->getProgramMemorySectionFromAddress(startAddress); - const auto endSection = this->getProgramMemorySectionFromAddress( - static_cast(startAddress + buffer.size() - 1) - ); - - if (startSection != endSection) { - throw Exception( - "Requested program memory write spans more than one section (APPLICATION and BOOT) - aborting." + if (this->targetConfig->physicalInterface == PhysicalInterface::PDI) { + const auto startSection = this->getProgramMemorySectionFromAddress(startAddress); + const auto endSection = this->getProgramMemorySectionFromAddress( + static_cast(startAddress + buffer.size() - 1) ); - } - if ( - !this->programmingSession->applicationSectionErased - && ( - startSection == ProgramMemorySection::APPLICATION - || endSection == ProgramMemorySection::APPLICATION - ) - ) { - Logger::warning("Erasing program memory APPLICATION section, in preparation for writing."); - this->avr8DebugInterface->eraseProgramMemorySection(ProgramMemorySection::APPLICATION); - this->programmingSession->applicationSectionErased = true; - } + if (startSection != endSection) { + throw Exception( + "Requested program memory write spans more than one section (APPLICATION and BOOT) - aborting." + ); + } - if ( - !this->programmingSession->bootSectionErased + if ( + !this->programmingSession->applicationSectionErased + && ( + startSection == ProgramMemorySection::APPLICATION + || endSection == ProgramMemorySection::APPLICATION + ) + ) { + Logger::warning("Erasing program memory APPLICATION section, in preparation for programming."); + this->avr8DebugInterface->eraseProgramMemory(ProgramMemorySection::APPLICATION); + this->programmingSession->applicationSectionErased = true; + } + + if ( + !this->programmingSession->bootSectionErased && ( startSection == ProgramMemorySection::BOOT || endSection == ProgramMemorySection::BOOT ) - ) { - Logger::warning("Erasing program memory BOOT section, in preparation for writing."); - this->avr8DebugInterface->eraseProgramMemorySection(ProgramMemorySection::BOOT); - this->programmingSession->bootSectionErased = true; + ) { + Logger::warning("Erasing program memory BOOT section, in preparation for programming."); + this->avr8DebugInterface->eraseProgramMemory(ProgramMemorySection::BOOT); + this->programmingSession->bootSectionErased = true; + } + + } else if (!this->programmingSession->chipErased) { + Logger::warning("Erasing entire chip, in preparation for programming."); + this->avr8DebugInterface->eraseProgramMemory(); + this->programmingSession->chipErased = true; } } @@ -962,7 +968,8 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit } ProgramMemorySection Avr8::getProgramMemorySectionFromAddress(std::uint32_t address) { - return address >= this->targetParameters->bootSectionStartAddress.value() + return this->targetParameters->bootSectionStartAddress.has_value() + && address >= this->targetParameters->bootSectionStartAddress.value() ? ProgramMemorySection::BOOT : ProgramMemorySection::APPLICATION; } diff --git a/src/Targets/Microchip/AVR/AVR8/ProgrammingSession.hpp b/src/Targets/Microchip/AVR/AVR8/ProgrammingSession.hpp index ad81c5ad..3e76ee51 100644 --- a/src/Targets/Microchip/AVR/AVR8/ProgrammingSession.hpp +++ b/src/Targets/Microchip/AVR/AVR8/ProgrammingSession.hpp @@ -4,6 +4,7 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit { struct ProgrammingSession { + bool chipErased = false; bool applicationSectionErased = false; bool bootSectionErased = false; };