diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ac0e2fa..35d79314 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,7 @@ add_executable(Bloom src/Targets/TargetDescription/TargetDescriptionFile.cpp src/Targets/TargetRegister.cpp src/Targets/Microchip/AVR/AVR8/Avr8.cpp + src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp build/resources/TargetDescriptionFiles/AVR/Mapping.json diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp new file mode 100644 index 00000000..763439b4 --- /dev/null +++ b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.cpp @@ -0,0 +1,42 @@ +#include "Avr8TargetConfig.hpp" + +#include "src/Logger/Logger.hpp" +#include "src/Exceptions/InvalidConfig.hpp" + +namespace Bloom::Targets::Microchip::Avr::Avr8Bit +{ + Avr8TargetConfig::Avr8TargetConfig(const TargetConfig& targetConfig): TargetConfig(targetConfig) { + using Bloom::Exceptions::InvalidConfig; + + if (!targetConfig.jsonObject.contains("physicalInterface")) { + throw InvalidConfig("Missing physical interface config parameter for AVR8 target."); + } + + const auto physicalInterfaceName = targetConfig.jsonObject.value("physicalInterface").toString().toLower() + .toStdString(); + + static const auto physicalInterfacesByName = Avr8TargetConfig::getPhysicalInterfacesByName(); + + if (!physicalInterfacesByName.contains(physicalInterfaceName)) { + throw InvalidConfig("Invalid physical interface config parameter for AVR8 target."); + } + + this->physicalInterface = physicalInterfacesByName.at(physicalInterfaceName); + + if (targetConfig.jsonObject.contains("updateDwenFuseBit")) { + this->updateDwenFuseBit = targetConfig.jsonObject.value("updateDwenFuseBit").toBool(); + } + + if (targetConfig.jsonObject.contains("cycleTargetPowerPostDwenUpdate")) { + this->cycleTargetPowerPostDwenUpdate = targetConfig.jsonObject.value( + "cycleTargetPowerPostDwenUpdate" + ).toBool(); + } + + if (targetConfig.jsonObject.contains("disableDebugWirePreDisconnect")) { + this->disableDebugWireOnDeactivate = targetConfig.jsonObject.value( + "disableDebugWirePreDisconnect" + ).toBool(); + } + } +} diff --git a/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp new file mode 100644 index 00000000..d7a68e7e --- /dev/null +++ b/src/Targets/Microchip/AVR/AVR8/Avr8TargetConfig.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "src/ProjectConfig.hpp" + +#include "PhysicalInterface.hpp" + +namespace Bloom::Targets::Microchip::Avr::Avr8Bit +{ + /** + * Extending the generic TargetConfig struct to accommodate AVR8 target configuration parameters. + */ + class Avr8TargetConfig: public TargetConfig + { + public: + /** + * The physical interface is the interface used for communication between the debug tool and the connected + * target. + */ + PhysicalInterface physicalInterface = PhysicalInterface::DEBUG_WIRE; + + /** + * Because the debugWire module requires control of the reset pin on the target, enabling this module will + * effectively mean losing control of the reset pin. This means users won't be able to use other + * interfaces that require access to the reset pin, such as ISP, until the debugWire module is disabled. + * + * The EdbgAvr8Interface provides a function for temporarily disabling the debugWire module on the target. + * This doesn't change the DWEN fuse and its affect is only temporary - the debugWire module will be + * reactivated upon the user cycling the power to the target. + * + * Bloom is able to temporarily disable the debugWire module, automatically, upon deactivating of the + * target (which usually occurs after a debug session has ended). This allows users to program the target via + * ISP, after they've finished a debug session. After programming the target, the user will need to cycle the + * target power before Bloom can gain access for another debug session. This flag control this function. + * + * NOTE: Currently, this flag is only honoured by the EdbgAvr8Interface. + * + * See the EdbgAvr8Interface::disableDebugWire() function for more. + */ + bool disableDebugWireOnDeactivate = false; + + /** + * The updateDwenFuseBit flag determines if Bloom should manage the DWEN fuse bit, for debugWire sessions. + * + * This parameter is optional, and the function is disabled by default. Users must explicitly enable it in + * their target configuration. + */ + bool updateDwenFuseBit = false; + + /** + * For debug tools that provide target power management functions (such as some evaluation boards), Bloom can + * automatically cycle the target power after updating the DWEN fuse bit, for debugWire sessions. This parameter + * controls this function. + * + * This parameter is optional. The function is enabled by default. + */ + bool cycleTargetPowerPostDwenUpdate = true; + + explicit Avr8TargetConfig(const TargetConfig& targetConfig); + + private: + static inline auto getPhysicalInterfacesByName() { + return std::map({ + {"debugwire", PhysicalInterface::DEBUG_WIRE}, // Deprecated - left here for backwards compatibility + {"debug-wire", PhysicalInterface::DEBUG_WIRE}, + {"pdi", PhysicalInterface::PDI}, + {"jtag", PhysicalInterface::JTAG}, + {"updi", PhysicalInterface::UPDI}, + }); + }; + }; +}