diff --git a/src/TargetController/TargetControllerComponent.cpp b/src/TargetController/TargetControllerComponent.cpp index 94a3e034..124ef2b4 100644 --- a/src/TargetController/TargetControllerComponent.cpp +++ b/src/TargetController/TargetControllerComponent.cpp @@ -510,12 +510,23 @@ namespace TargetController if (!this->environmentConfig.targetConfig.hardwareBreakpoints) { Logger::warning("Hardware breakpoints have been disabled"); - } else if (targetDescriptor.breakpointResources.maximumHardwareBreakpoints.has_value()) { - Logger::info( - "Available hardware breakpoints: " + std::to_string( - *(targetDescriptor.breakpointResources.maximumHardwareBreakpoints) - ) - ); + } else { + const auto& breakpointResources = targetDescriptor.breakpointResources; + if (breakpointResources.maximumHardwareBreakpoints.has_value()) { + Logger::info( + "Available hardware breakpoints: " + std::to_string( + *(breakpointResources.maximumHardwareBreakpoints) + ) + ); + } + + if (breakpointResources.reservedHardwareBreakpoints > 0) { + Logger::info( + "Reserved hardware breakpoints: " + std::to_string( + breakpointResources.reservedHardwareBreakpoints + ) + ); + } } this->programMemoryCache = std::make_unique( @@ -971,7 +982,8 @@ namespace TargetController if ( !targetBreakpointResources.maximumHardwareBreakpoints.has_value() - || this->hardwareBreakpointsByAddress.size() < *(targetBreakpointResources.maximumHardwareBreakpoints) + || this->hardwareBreakpointsByAddress.size() < (*(targetBreakpointResources.maximumHardwareBreakpoints) + - targetBreakpointResources.reservedHardwareBreakpoints) ) { exhaustedResourcesWarning = true; diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp index 5d5c21d5..688ecac9 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8.cpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8.cpp @@ -697,7 +697,7 @@ namespace Targets::Microchip::Avr::Avr8Bit } BreakpointResources Avr8::getBreakpointResources() { - auto maxHardwareBreakpoints = 0; + auto maxHardwareBreakpoints = static_cast(0); switch (this->targetConfig.physicalInterface) { case PhysicalInterface::JTAG: { @@ -719,7 +719,11 @@ namespace Targets::Microchip::Avr::Avr8Bit return BreakpointResources( maxHardwareBreakpoints, - std::nullopt + std::nullopt, + std::min( + static_cast(this->targetConfig.reserveSteppingBreakpoint ? 1 : 0), + maxHardwareBreakpoints + ) ); } diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp index f88d5e95..746c33e5 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp @@ -35,31 +35,51 @@ namespace Targets::Microchip::Avr::Avr8Bit // The 'manageDwenFuseBit' param used to be 'updateDwenFuseBit' - we still support the old, for now. if (targetNode["updateDwenFuseBit"]) { - this->manageDwenFuseBit = targetNode["updateDwenFuseBit"].as(); + this->manageDwenFuseBit = targetNode["updateDwenFuseBit"].as( + this->manageDwenFuseBit + ); } if (targetNode["manageDwenFuseBit"]) { - this->manageDwenFuseBit = targetNode["manageDwenFuseBit"].as(); + this->manageDwenFuseBit = targetNode["manageDwenFuseBit"].as( + this->manageDwenFuseBit + ); } if (targetNode["cycleTargetPowerPostDwenUpdate"]) { - this->cycleTargetPowerPostDwenUpdate = targetNode["cycleTargetPowerPostDwenUpdate"].as(); + this->cycleTargetPowerPostDwenUpdate = targetNode["cycleTargetPowerPostDwenUpdate"].as( + this->cycleTargetPowerPostDwenUpdate + ); } if (targetNode["disableDebugWirePreDisconnect"]) { - this->disableDebugWireOnDeactivate = targetNode["disableDebugWirePreDisconnect"].as(); + this->disableDebugWireOnDeactivate = targetNode["disableDebugWirePreDisconnect"].as( + this->disableDebugWireOnDeactivate + ); } if (targetNode["targetPowerCycleDelay"]) { - this->targetPowerCycleDelay = std::chrono::milliseconds(targetNode["targetPowerCycleDelay"].as()); + this->targetPowerCycleDelay = std::chrono::milliseconds(targetNode["targetPowerCycleDelay"].as( + this->targetPowerCycleDelay.count() + )); } if (targetNode["manageOcdenFuseBit"]) { - this->manageOcdenFuseBit = targetNode["manageOcdenFuseBit"].as(); + this->manageOcdenFuseBit = targetNode["manageOcdenFuseBit"].as( + this->manageOcdenFuseBit + ); } if (targetNode["preserveEeprom"]) { - this->preserveEeprom = targetNode["preserveEeprom"].as(); + this->preserveEeprom = targetNode["preserveEeprom"].as( + this->preserveEeprom + ); + } + + if (targetNode["reserveSteppingBreakpoint"]) { + this->reserveSteppingBreakpoint = targetNode["reserveSteppingBreakpoint"].as( + this->reserveSteppingBreakpoint + ); } } } diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp index 4bf9781f..2c11d73d 100644 --- a/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp +++ b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp @@ -93,6 +93,11 @@ namespace Targets::Microchip::Avr::Avr8Bit */ bool preserveEeprom = true; + /** + * Determines if Bloom will reserve a single hardware breakpoint for stepping operations. + */ + bool reserveSteppingBreakpoint = true; + explicit Avr8TargetConfig(const TargetConfig& targetConfig); private: diff --git a/src/Targets/TargetBreakpoint.hpp b/src/Targets/TargetBreakpoint.hpp index ee9da87d..c6543ed8 100644 --- a/src/Targets/TargetBreakpoint.hpp +++ b/src/Targets/TargetBreakpoint.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "TargetMemory.hpp" @@ -40,13 +41,21 @@ namespace Targets { std::optional maximumHardwareBreakpoints; std::optional maximumSoftwareBreakpoints; + std::uint16_t reservedHardwareBreakpoints; BreakpointResources( std::optional maximumHardwareBreakpoints, - std::optional maximumSoftwareBreakpoints + std::optional maximumSoftwareBreakpoints, + std::uint16_t reservedHardwareBreakpoints ) : maximumHardwareBreakpoints(maximumHardwareBreakpoints) , maximumSoftwareBreakpoints(maximumSoftwareBreakpoints) - {} + , reservedHardwareBreakpoints(reservedHardwareBreakpoints) + { + assert( + !this->maximumHardwareBreakpoints.has_value() + || this->maximumHardwareBreakpoints >= this->reservedHardwareBreakpoints + ); + } }; }