Added eraseProgramMemorySection() function to Avr8 debug interface - to erase XMEGA program memory sections when necessary
This commit is contained in:
@@ -720,6 +720,24 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
return this->writeMemory(avr8MemoryType, startAddress, buffer);
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
|
EraseMemory(
|
||||||
|
section == ProgramMemorySection::BOOT
|
||||||
|
? Avr8EraseMemoryMode::BOOT_SECTION
|
||||||
|
: Avr8EraseMemoryMode::APPLICATION_SECTION
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||||
|
throw Avr8CommandFailure("AVR8 erase memory command failed", response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TargetState EdbgAvr8Interface::getTargetState() {
|
TargetState EdbgAvr8Interface::getTargetState() {
|
||||||
/*
|
/*
|
||||||
* We are not informed when a target goes from a stopped state to a running state, so there is no need
|
* We are not informed when a target goes from a stopped state to a running state, so there is no need
|
||||||
@@ -745,13 +763,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->programmingModeEnabled = true;
|
this->programmingModeEnabled = true;
|
||||||
|
|
||||||
if (this->configVariant == Avr8ConfigVariant::XMEGA) {
|
|
||||||
Logger::warning(
|
|
||||||
"The entire application section of program memory will be erased, in preparation for programming"
|
|
||||||
);
|
|
||||||
this->eraseMemory(Avr8EraseMemoryMode::APPLICATION_SECTION);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::disableProgrammingMode() {
|
void EdbgAvr8Interface::disableProgrammingMode() {
|
||||||
@@ -1755,15 +1766,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::eraseMemory(Avr8EraseMemoryMode mode) {
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
|
||||||
EraseMemory(mode)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
|
||||||
throw Avr8CommandFailure("AVR8 erase memory command failed", response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::refreshTargetState() {
|
void EdbgAvr8Interface::refreshTargetState() {
|
||||||
|
|||||||
@@ -242,6 +242,13 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
const Targets::TargetMemoryBuffer& buffer
|
const Targets::TargetMemoryBuffer& buffer
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issues the "Erase" command to erase a particular section of program memory.
|
||||||
|
*
|
||||||
|
* @param section
|
||||||
|
*/
|
||||||
|
void eraseProgramMemorySection(Targets::Microchip::Avr::Avr8Bit::ProgramMemorySection section) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current state of the target.
|
* Returns the current state of the target.
|
||||||
*
|
*
|
||||||
@@ -536,13 +543,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
*/
|
*/
|
||||||
void writeMemory(Avr8MemoryType type, std::uint32_t address, const Targets::TargetMemoryBuffer& buffer);
|
void writeMemory(Avr8MemoryType type, std::uint32_t address, const Targets::TargetMemoryBuffer& buffer);
|
||||||
|
|
||||||
/**
|
|
||||||
* Erases a particular region of memory, depending on the value of mode.
|
|
||||||
*
|
|
||||||
* @param mode
|
|
||||||
*/
|
|
||||||
void eraseMemory(Avr8EraseMemoryMode mode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the current target state.
|
* Fetches the current target state.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
|
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
|
||||||
#include "src/Targets/Microchip/AVR/AVR8/Family.hpp"
|
#include "src/Targets/Microchip/AVR/AVR8/Family.hpp"
|
||||||
#include "src/Targets/Microchip/AVR/AVR8/PhysicalInterface.hpp"
|
#include "src/Targets/Microchip/AVR/AVR8/PhysicalInterface.hpp"
|
||||||
|
#include "src/Targets/Microchip/AVR/AVR8/ProgramMemorySection.hpp"
|
||||||
#include "src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp"
|
#include "src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp"
|
||||||
|
|
||||||
#include "src/Targets/TargetState.hpp"
|
#include "src/Targets/TargetState.hpp"
|
||||||
@@ -194,6 +195,13 @@ namespace Bloom::DebugToolDrivers::TargetInterfaces::Microchip::Avr::Avr8
|
|||||||
const Targets::TargetMemoryBuffer& buffer
|
const Targets::TargetMemoryBuffer& buffer
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should erase a particular program memory section.
|
||||||
|
*
|
||||||
|
* @param section
|
||||||
|
*/
|
||||||
|
virtual void eraseProgramMemorySection(Targets::Microchip::Avr::Avr8Bit::ProgramMemorySection section) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should obtain the current target state.
|
* Should obtain the current target state.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -323,6 +323,47 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Avr8::writeMemory(TargetMemoryType memoryType, std::uint32_t startAddress, const TargetMemoryBuffer& buffer) {
|
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
|
||||||
|
) {
|
||||||
|
// 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<std::uint32_t>(startAddress + buffer.size() - 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (startSection != endSection) {
|
||||||
|
throw Exception(
|
||||||
|
"Requested program memory write spans more than one section (APPLICATION and BOOT) - aborting."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
!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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this->avr8DebugInterface->writeMemory(memoryType, startAddress, buffer);
|
this->avr8DebugInterface->writeMemory(memoryType, startAddress, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -919,4 +960,10 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProgramMemorySection Avr8::getProgramMemorySectionFromAddress(std::uint32_t address) {
|
||||||
|
return address >= this->targetParameters->bootSectionStartAddress.value()
|
||||||
|
? ProgramMemorySection::BOOT
|
||||||
|
: ProgramMemorySection::APPLICATION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "TargetParameters.hpp"
|
#include "TargetParameters.hpp"
|
||||||
#include "PadDescriptor.hpp"
|
#include "PadDescriptor.hpp"
|
||||||
#include "ProgrammingSession.hpp"
|
#include "ProgrammingSession.hpp"
|
||||||
|
#include "ProgramMemorySection.hpp"
|
||||||
#include "src/Targets/TargetRegister.hpp"
|
#include "src/Targets/TargetRegister.hpp"
|
||||||
|
|
||||||
#include "TargetDescription/TargetDescriptionFile.hpp"
|
#include "TargetDescription/TargetDescriptionFile.hpp"
|
||||||
@@ -182,5 +183,13 @@ namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
|||||||
* True to set the fuse, false to clear it.
|
* True to set the fuse, false to clear it.
|
||||||
*/
|
*/
|
||||||
void writeDwenFuseBit(bool setFuse);
|
void writeDwenFuseBit(bool setFuse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the program memory section from a program memory address.
|
||||||
|
*
|
||||||
|
* @param address
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ProgramMemorySection getProgramMemorySectionFromAddress(std::uint32_t address);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/Targets/Microchip/AVR/AVR8/ProgramMemorySection.hpp
Normal file
12
src/Targets/Microchip/AVR/AVR8/ProgramMemorySection.hpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Bloom::Targets::Microchip::Avr::Avr8Bit
|
||||||
|
{
|
||||||
|
enum class ProgramMemorySection: std::uint8_t
|
||||||
|
{
|
||||||
|
APPLICATION,
|
||||||
|
BOOT,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user