#pragma once #include #include #include #include "src/Targets/Microchip/AVR/Target.hpp" #include "src/DebugToolDrivers/DebugTool.hpp" #include "src/DebugToolDrivers/TargetInterfaces/Microchip/AVR/AVR8/Avr8DebugInterface.hpp" #include "src/DebugToolDrivers/TargetInterfaces/Microchip/AVR/AvrIspInterface.hpp" #include "Family.hpp" #include "TargetParameters.hpp" #include "PadDescriptor.hpp" #include "src/Targets/TargetRegister.hpp" #include "TargetDescription/TargetDescriptionFile.hpp" #include "src/ProjectConfig.hpp" namespace Bloom::Targets::Microchip::Avr::Avr8Bit { class Avr8: public Target { public: explicit Avr8() = default; Avr8(std::string name, const TargetSignature& signature): name(std::move(name)) { this->id = signature; this->loadTargetDescriptionFile(); this->initFromTargetDescriptionFile(); }; /* * The functions below implement the Target interface for AVR8 targets. * * See the Bloom::Targets::Target interface class for documentation on the expected behaviour of * each function. */ void preActivationConfigure(const TargetConfig& targetConfig) override; void postActivationConfigure() override; void postPromotionConfigure() override; void activate() override; void deactivate() override; /** * All AVR8 compatible debug tools must provide a valid Avr8Interface. * * @param debugTool * @return */ bool isDebugToolSupported(DebugTool* debugTool) override { return debugTool->getAvr8DebugInterface() != nullptr; } void setDebugTool(DebugTool* debugTool) override { this->avr8DebugInterface = debugTool->getAvr8DebugInterface(); this->avrIspInterface = debugTool->getAvrIspInterface(); } /** * Instances to this target class can be promoted. See Avr8::promote() method for more. * * @return */ bool supportsPromotion() override { return true; } /** * Instances of this generic Avr8 target class will be promoted to a family specific class (see the Mega, Xmega * and Tiny classes for more). * * @return */ std::unique_ptr promote() override; std::string getName() const override { return this->name; } TargetDescriptor getDescriptor() override; void run() override; void stop() override; void step() override; void reset() override; void setBreakpoint(std::uint32_t address) override; void removeBreakpoint(std::uint32_t address) override; void clearAllBreakpoints() override; void writeRegisters(TargetRegisters registers) override; TargetRegisters readRegisters(TargetRegisterDescriptors descriptors) override; TargetMemoryBuffer readMemory( TargetMemoryType memoryType, std::uint32_t startAddress, std::uint32_t bytes, const std::set& excludedAddressRanges = {} ) override; void writeMemory( TargetMemoryType memoryType, std::uint32_t startAddress, const TargetMemoryBuffer& buffer ) override; TargetState getState() override; std::uint32_t getProgramCounter() override; TargetRegister getProgramCounterRegister(); void setProgramCounter(std::uint32_t programCounter) override; std::uint32_t getStackPointer() override; std::map getPinStates(int variantId) override; void setPinState( const TargetPinDescriptor& pinDescriptor, const TargetPinState& state ) override; protected: DebugToolDrivers::TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* avr8DebugInterface = nullptr; DebugToolDrivers::TargetInterfaces::Microchip::Avr::AvrIspInterface* avrIspInterface = nullptr; std::string name; std::optional family; std::optional physicalInterface; std::optional targetDescriptionFile; std::optional targetParameters; std::map padDescriptorsByName; std::map targetVariantsById; std::map targetRegisterDescriptorsByType; std::map targetMemoryDescriptorsByType; bool updateDwenFuseBit = false; /** * Users are required to set their desired physical interface in their Bloom configuration. This would take * the form of a string, so we map the available options to the appropriate enums. */ static inline auto getPhysicalInterfacesByName() { using Targets::Microchip::Avr::Avr8Bit::PhysicalInterface; return std::map({ {"debugwire", PhysicalInterface::DEBUG_WIRE}, {"debug-wire", PhysicalInterface::DEBUG_WIRE}, {"pdi", PhysicalInterface::PDI}, {"jtag", PhysicalInterface::JTAG}, {"updi", PhysicalInterface::UPDI}, }); }; /** * Resolves the appropriate TDF for the AVR8 target and populates this->targetDescriptionFile. */ void loadTargetDescriptionFile(); /** * Initiates the AVR8 instance from data extracted from the TDF. */ void initFromTargetDescriptionFile(); /** * Populates this->targetRegisterDescriptorsByType with registers extracted from the TDF, as well as general * purpose and other CPU registers. */ void loadTargetRegisterDescriptors(); void loadTargetMemoryDescriptors(); /** * Extracts the ID from the target's memory. * * This function will cache the ID value and use the cached version for any subsequent calls. * * @return */ TargetSignature getId() override; /** * Updates the debugWire enable (DWEN) fuse bit on the AVR target. * * @param setFuse * True to set the fuse, false to clear it. */ void writeDwenFuseBit(bool setFuse); }; }