Massive refactor to accommodate RISC-V targets
- Refactored entire codebase (excluding the Insight component) to accommodate multiple target architectures (no longer specific to AVR) - Deleted 'generate SVD' GDB monitor command - I will eventually move this functionality to the Bloom website - Added unit size property to address spaces - Many other changes which I couldn't be bothered to describe here
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,220 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/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 "ProgramMemorySection.hpp"
|
||||
#include "ProgrammingSession.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR/Fuse.hpp"
|
||||
#include "src/Targets/TargetPhysicalInterface.hpp"
|
||||
#include "src/Targets/TargetRegisterDescriptor.hpp"
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
|
||||
#include "TargetDescription/TargetDescriptionFile.hpp"
|
||||
|
||||
#include "Avr8TargetConfig.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
{
|
||||
class Avr8: public Target
|
||||
{
|
||||
public:
|
||||
explicit Avr8(
|
||||
const TargetConfig& targetConfig,
|
||||
TargetDescription::TargetDescriptionFile&& targetDescriptionFile
|
||||
);
|
||||
|
||||
/*
|
||||
* The functions below implement the Target interface for AVR8 targets.
|
||||
*
|
||||
* See the Targets::Target abstract class for documentation on the expected behaviour of
|
||||
* each function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* All AVR8 compatible debug tools must provide a valid Avr8Interface.
|
||||
*
|
||||
* @param debugTool
|
||||
* @return
|
||||
*/
|
||||
bool supportsDebugTool(DebugTool* debugTool) override;
|
||||
|
||||
void setDebugTool(DebugTool* debugTool) override;
|
||||
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
TargetDescriptor getDescriptor() override;
|
||||
|
||||
void run(std::optional<TargetMemoryAddress> toAddress = std::nullopt) override;
|
||||
void stop() override;
|
||||
void step() override;
|
||||
void reset() override;
|
||||
|
||||
void setSoftwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void removeSoftwareBreakpoint(TargetMemoryAddress address) override;
|
||||
|
||||
void setHardwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void removeHardwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void clearAllBreakpoints() override;
|
||||
|
||||
void writeRegisters(const TargetRegisters& registers) override;
|
||||
TargetRegisters readRegisters(const Targets::TargetRegisterDescriptorIds& descriptorIds) override;
|
||||
|
||||
TargetMemoryBuffer readMemory(
|
||||
TargetMemoryType memoryType,
|
||||
TargetMemoryAddress startAddress,
|
||||
TargetMemorySize bytes,
|
||||
const std::set<Targets::TargetMemoryAddressRange>& excludedAddressRanges = {}
|
||||
) override;
|
||||
void writeMemory(
|
||||
TargetMemoryType memoryType,
|
||||
TargetMemoryAddress startAddress,
|
||||
const TargetMemoryBuffer& buffer
|
||||
) override;
|
||||
void eraseMemory(TargetMemoryType memoryType) override;
|
||||
|
||||
TargetState getState() override;
|
||||
|
||||
TargetMemoryAddress getProgramCounter() override;
|
||||
void setProgramCounter(TargetMemoryAddress programCounter) override;
|
||||
|
||||
TargetStackPointer getStackPointer() override;
|
||||
|
||||
std::map<int, TargetPinState> getPinStates(int variantId) override;
|
||||
void setPinState(
|
||||
const TargetPinDescriptor& pinDescriptor,
|
||||
const TargetPinState& state
|
||||
) override;
|
||||
|
||||
void enableProgrammingMode() override;
|
||||
|
||||
void disableProgrammingMode() override;
|
||||
|
||||
bool programmingModeEnabled() override;
|
||||
|
||||
protected:
|
||||
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* targetPowerManagementInterface = nullptr;
|
||||
DebugToolDrivers::TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* avr8DebugInterface = nullptr;
|
||||
DebugToolDrivers::TargetInterfaces::Microchip::Avr::AvrIspInterface* avrIspInterface = nullptr;
|
||||
|
||||
Avr8TargetConfig targetConfig;
|
||||
|
||||
TargetDescription::TargetDescriptionFile targetDescriptionFile;
|
||||
|
||||
TargetSignature signature;
|
||||
std::string name;
|
||||
Family family;
|
||||
|
||||
TargetParameters targetParameters;
|
||||
|
||||
std::set<Targets::TargetPhysicalInterface> physicalInterfaces;
|
||||
std::map<std::string, PadDescriptor> padDescriptorsByName;
|
||||
std::map<int, TargetVariant> targetVariantsById;
|
||||
|
||||
TargetRegisterDescriptor stackPointerRegisterDescriptor;
|
||||
TargetRegisterDescriptor statusRegisterDescriptor;
|
||||
|
||||
/**
|
||||
* On some AVR8 targets, like the ATmega328P, a cleared fuse bit means the fuse is "programmed" (enabled).
|
||||
* And a set bit means the fuse is "un-programmed" (disabled). But on others, like the ATmega4809, it's the
|
||||
* other way around (set bit == enabled, cleared bit == disabled).
|
||||
*
|
||||
* The FuseEnableStrategy specifies the strategy of enabling a fuse. It's extracted from the TDF.
|
||||
* See TargetDescription::getFuseEnableStrategy() for more.
|
||||
*/
|
||||
FuseEnableStrategy fuseEnableStrategy;
|
||||
|
||||
std::map<TargetRegisterDescriptorId, TargetRegisterDescriptor> targetRegisterDescriptorsById;
|
||||
|
||||
std::map<TargetMemoryType, TargetMemoryDescriptor> targetMemoryDescriptorsByType;
|
||||
|
||||
std::optional<ProgrammingSession> activeProgrammingSession = std::nullopt;
|
||||
|
||||
/**
|
||||
* Populates this->targetRegisterDescriptorsById with registers extracted from the TDF, as well as general
|
||||
* purpose and other CPU registers.
|
||||
*/
|
||||
void loadTargetRegisterDescriptors();
|
||||
|
||||
void loadTargetMemoryDescriptors();
|
||||
|
||||
BreakpointResources getBreakpointResources();
|
||||
|
||||
/**
|
||||
* Checks if a particular fuse is enabled in the given fuse byte value. Takes the target's fuse enable strategy
|
||||
* into account.
|
||||
*
|
||||
* @param descriptor
|
||||
* @param fuseByteValue
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
bool isFuseEnabled(const FuseBitsDescriptor& descriptor, unsigned char fuseByteValue) const;
|
||||
|
||||
/**
|
||||
* Enables/disables a fuse within the given fuse byte, using the target's fuse enable strategy.
|
||||
*
|
||||
* @param descriptor
|
||||
* @param fuseByteValue
|
||||
* @param enabled
|
||||
*
|
||||
* @return
|
||||
* The updated fuse byte value.
|
||||
*/
|
||||
unsigned char setFuseEnabled(
|
||||
const FuseBitsDescriptor& descriptor,
|
||||
unsigned char fuseByteValue,
|
||||
bool enabled
|
||||
) const;
|
||||
|
||||
/**
|
||||
* Updates the debugWire enable (DWEN) fuse bit on the AVR target.
|
||||
*
|
||||
* @param enable
|
||||
* True to enable the fuse, false to disable it.
|
||||
*/
|
||||
void updateDwenFuseBit(bool enable);
|
||||
|
||||
/**
|
||||
* Updates the On-chip debug enable (OCDEN) fuse bit on the AVR target.
|
||||
*
|
||||
* @param enable
|
||||
* True to enable the fuse, false to disable it.
|
||||
*/
|
||||
void updateOcdenFuseBit(bool enable);
|
||||
|
||||
/**
|
||||
* Updates the "Preserve EEPROM" (EESAVE) fuse bit on the AVR target.
|
||||
*
|
||||
* @param enable
|
||||
* True to enable the fuse, false to disable it.
|
||||
*
|
||||
* @return
|
||||
* True if the fuse bit was updated. False if the fuse bit was already set to the desired value.
|
||||
*/
|
||||
bool updateEesaveFuseBit(bool enable);
|
||||
|
||||
/**
|
||||
* Resolves the program memory section from a program memory address.
|
||||
*
|
||||
* Currently unused, but will be needed soon.
|
||||
*
|
||||
* @param address
|
||||
* @return
|
||||
*/
|
||||
ProgramMemorySection getProgramMemorySectionFromAddress(TargetMemoryAddress address);
|
||||
};
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
{
|
||||
/**
|
||||
* Pin configurations for AVR8 targets may vary across target variants. This is why we must differentiate a pin
|
||||
* to a pad. A pin is mapped to a pad, but this mapping is variant specific. For example, pin 4 on
|
||||
* the ATmega328P-PN (DIP variant) is mapped to a GPIO pad (PORTD/PIN2), but on the QFN variant (ATmega328P-MN),
|
||||
* pin 4 is mapped to a GND pad.
|
||||
*
|
||||
* PadDescriptor describes a single pad on an AVR8 target. On target configuration, PadDescriptors are
|
||||
* generated from the AVR8 target description file. These descriptors are mapped to pad names.
|
||||
* See Avr8::loadPadDescriptors() for more.
|
||||
*/
|
||||
struct PadDescriptor
|
||||
{
|
||||
std::string name;
|
||||
|
||||
std::optional<std::uint8_t> gpioPinNumber;
|
||||
std::optional<std::uint16_t> gpioPortAddress;
|
||||
std::optional<std::uint16_t> gpioPortInputAddress;
|
||||
std::optional<std::uint16_t> gpioDdrAddress;
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,282 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/TargetDescription/TargetDescriptionFile.hpp"
|
||||
|
||||
#include "src/Targets/TargetVariant.hpp"
|
||||
#include "src/Targets/TargetRegisterDescriptor.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
|
||||
#include "src/Targets/Microchip/AVR/IspParameters.hpp"
|
||||
#include "src/Targets/Microchip/AVR/Fuse.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR/AVR8/Family.hpp"
|
||||
#include "src/Targets/Microchip/AVR/AVR8/TargetParameters.hpp"
|
||||
#include "src/Targets/Microchip/AVR/AVR8/PadDescriptor.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
{
|
||||
/**
|
||||
* Represents an AVR8 TDF. See the Targets::TargetDescription::TargetDescriptionFile close for more on TDFs.
|
||||
*
|
||||
* During the build process, we generate a JSON file containing a mapping of AVR8 target signatures to target
|
||||
* description file paths. Bloom uses this mapping to find a particular target description file, for AVR8 targets,
|
||||
* given a target signature. See directory "build/resources/TargetDescriptionFiles".
|
||||
* The generation of the JSON mapping, is done by a PHP script:
|
||||
* "build/scripts/CopyAvrPartFilesAndCreateMapping.php". This script is invoked via a custom command, at build time.
|
||||
*
|
||||
* For more information of TDFs, see src/Targets/TargetDescription/README.md
|
||||
*/
|
||||
class TargetDescriptionFile: public Targets::TargetDescription::TargetDescriptionFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among
|
||||
* other things.
|
||||
*
|
||||
* @param xml
|
||||
*/
|
||||
explicit TargetDescriptionFile(const std::string& xmlFilePath);
|
||||
|
||||
/**
|
||||
* Extracts the AVR8 target signature from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] TargetSignature getTargetSignature() const;
|
||||
|
||||
/**
|
||||
* Extracts the AVR8 target family from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] Family getAvrFamily() const;
|
||||
|
||||
[[nodiscard]] const Targets::TargetDescription::AddressSpace& getProgramAddressSpace() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::AddressSpace& getRamAddressSpace() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::AddressSpace& getEepromAddressSpace() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::AddressSpace& getIoAddressSpace() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::AddressSpace& getSignatureAddressSpace() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::AddressSpace& getFuseAddressSpace() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::AddressSpace& getLockbitAddressSpace() const;
|
||||
|
||||
[[nodiscard]] const Targets::TargetDescription::MemorySegment& getProgramMemorySegment() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::MemorySegment& getRamMemorySegment() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::MemorySegment& getEepromMemorySegment() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::MemorySegment& getIoMemorySegment() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::MemorySegment& getSignatureMemorySegment() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::MemorySegment& getFuseMemorySegment() const;
|
||||
[[nodiscard]] const Targets::TargetDescription::MemorySegment& getLockbitMemorySegment() const;
|
||||
|
||||
/**
|
||||
* Constructs an instance of TargetParameters, for the AVR8 target, with data from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] TargetParameters getTargetParameters() const;
|
||||
|
||||
/**
|
||||
* Extracts the target's ISP parameters from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] IspParameters getIspParameters() const;
|
||||
|
||||
/**
|
||||
* Extracts the target's fuse enable strategy.
|
||||
*
|
||||
* @return
|
||||
* std::nullopt if the TDF doesn't contain a fuse enable strategy.
|
||||
*/
|
||||
[[nodiscard]] std::optional<FuseEnableStrategy> getFuseEnableStrategy() const;
|
||||
|
||||
/**
|
||||
* Constructs a FuseBitDescriptor for the debugWire enable (DWEN) fuse bit, with information extracted from
|
||||
* the TDF.
|
||||
*
|
||||
* @return
|
||||
* std::nullopt if the DWEN bit field could not be found in the TDF.
|
||||
*/
|
||||
[[nodiscard]] std::optional<FuseBitsDescriptor> getDwenFuseBitsDescriptor() const;
|
||||
|
||||
/**
|
||||
* Constructs a FuseBitDescriptor for the SPI enable (SPIEN) fuse bit, with information extracted from
|
||||
* the TDF.
|
||||
*
|
||||
* @return
|
||||
* std::nullopt if the SPIEN bit field could not be found in the TDF.
|
||||
*/
|
||||
[[nodiscard]] std::optional<FuseBitsDescriptor> getSpienFuseBitsDescriptor() const;
|
||||
|
||||
/**
|
||||
* Constructs a FuseBitDescriptor for the OCD enable (OCDEN) fuse bit, with information extracted from
|
||||
* the TDF.
|
||||
*
|
||||
* @return
|
||||
* std::nullopt if the OCDEN bit field could not be found in the TDF.
|
||||
*/
|
||||
[[nodiscard]] std::optional<FuseBitsDescriptor> getOcdenFuseBitsDescriptor() const;
|
||||
|
||||
/**
|
||||
* Constructs a FuseBitDescriptor for the JTAG enable (JTAGEN) fuse bit, with information extracted from
|
||||
* the TDF.
|
||||
*
|
||||
* @return
|
||||
* std::nullopt if the JTAGEN bit field could not be found in the TDF.
|
||||
*/
|
||||
[[nodiscard]] std::optional<FuseBitsDescriptor> getJtagenFuseBitsDescriptor() const;
|
||||
|
||||
/**
|
||||
* Constructs a FuseBitDescriptor for the "Preserve EEPROM" (EESAVE) fuse bit, with information extracted from
|
||||
* the TDF.
|
||||
*
|
||||
* @return
|
||||
* std::nullopt if the EESAVE bit field could not be found in the TDF.
|
||||
*/
|
||||
[[nodiscard]] std::optional<FuseBitsDescriptor> getEesaveFuseBitsDescriptor() const;
|
||||
|
||||
/**
|
||||
* Returns a mapping of all pad descriptors extracted from TDF, mapped by name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] const auto& getPadDescriptorsMappedByName() const {
|
||||
return this->padDescriptorsByName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mapping of all target variants extracted from the TDF, mapped by ID.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] const auto& getVariantsMappedById() const {
|
||||
return this->targetVariantsById;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mapping of all target register descriptors extracted from the TDF, by ID.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] const auto& getRegisterDescriptorsMappedById() const {
|
||||
return this->targetRegisterDescriptorsById;
|
||||
}
|
||||
|
||||
private:
|
||||
/**`
|
||||
* AVR8 target description files include the target family name. This method returns a mapping of part
|
||||
* description family name strings to Family enum values.
|
||||
*
|
||||
* TODO: the difference in AVR8 family variations, like "tinyAVR" and "tinyAVR 2" may require attention.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static inline auto getFamilyNameToEnumMapping() {
|
||||
// All keys should be lower-case.
|
||||
return std::map<std::string, Family> {
|
||||
{"megaavr", Family::MEGA},
|
||||
{"avr mega", Family::MEGA},
|
||||
{"avr xmega", Family::XMEGA},
|
||||
{"avr tiny", Family::TINY},
|
||||
{"tinyavr", Family::TINY},
|
||||
{"tinyavr 2", Family::TINY},
|
||||
{"avr da", Family::DA},
|
||||
{"avr db", Family::DB},
|
||||
{"avr dd", Family::DD},
|
||||
{"avr ea", Family::EA},
|
||||
};
|
||||
};
|
||||
|
||||
std::string avrFamilyName;
|
||||
|
||||
std::map<std::string, PadDescriptor> padDescriptorsByName;
|
||||
std::map<int, TargetVariant> targetVariantsById;
|
||||
|
||||
std::map<TargetRegisterDescriptorId, TargetRegisterDescriptor> targetRegisterDescriptorsById;
|
||||
|
||||
/**
|
||||
* Populates this->supportedPhysicalInterfaces with physical interfaces defined in the TDF.
|
||||
*/
|
||||
void loadSupportedPhysicalInterfaces();
|
||||
|
||||
/**
|
||||
* Generates a collection of PadDescriptor objects from data in the TDF and populates this->padDescriptorsByName.
|
||||
*/
|
||||
void loadPadDescriptors();
|
||||
|
||||
/**
|
||||
* Loads all variants for the AVR8 target, from the TDF, and populates this->targetVariantsById.
|
||||
*/
|
||||
void loadTargetVariants();
|
||||
|
||||
/**
|
||||
* Loads all register descriptors from the TDF, and populates this->targetRegisterDescriptorsById.
|
||||
*/
|
||||
void loadTargetRegisterDescriptors();
|
||||
|
||||
/**
|
||||
* Gets the register address offset for a specific peripheral module.
|
||||
*
|
||||
* @param moduleName
|
||||
* @param instanceName
|
||||
* @param registerGroupName
|
||||
* @return
|
||||
*/
|
||||
Targets::TargetMemoryAddress getPeripheralModuleRegisterAddressOffset(
|
||||
const std::string& moduleName,
|
||||
const std::string& instanceName,
|
||||
const std::string& registerGroupName
|
||||
) const;
|
||||
|
||||
[[nodiscard]] std::optional<FuseBitsDescriptor> getFuseBitsDescriptorByName(
|
||||
const std::string& fuseBitName
|
||||
) const;
|
||||
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::AddressSpace> getProgramMemoryAddressSpace() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getFlashApplicationMemorySegment(
|
||||
const Targets::TargetDescription::AddressSpace& programAddressSpace
|
||||
) const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getRegisterMemorySegment() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getFirstBootSectionMemorySegment() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::MemorySegment> getLockbitsMemorySegment() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::RegisterGroup> getCpuRegisterGroup() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::RegisterGroup> getBootLoadRegisterGroup() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::RegisterGroup> getEepromRegisterGroup() const;
|
||||
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getStatusRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getStackPointerRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getStackPointerHighRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getStackPointerLowRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getOscillatorCalibrationRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getSpmcsRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getSpmcRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromAddressRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromAddressLowRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromAddressHighRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromDataRegister() const;
|
||||
[[nodiscard]] std::optional<Targets::TargetDescription::Register> getEepromControlRegister() const;
|
||||
|
||||
/**
|
||||
* Loads target parameters that are specific to debugWire and mega JTAG sessions.
|
||||
*
|
||||
* @param targetParameters
|
||||
*/
|
||||
virtual void loadDebugWireAndJtagTargetParameters(TargetParameters& targetParameters) const;
|
||||
|
||||
/**
|
||||
* Loads target parameters that are specific to PDI sessions.
|
||||
*
|
||||
* @param targetParameters
|
||||
*/
|
||||
virtual void loadPdiTargetParameters(TargetParameters& targetParameters) const;
|
||||
|
||||
/**
|
||||
* Loads target parameters that are specific to UPDI sessions.
|
||||
*
|
||||
* @param targetParameters
|
||||
*/
|
||||
virtual void loadUpdiTargetParameters(TargetParameters& targetParameters) const;
|
||||
};
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include "../TargetSignature.hpp"
|
||||
#include "Family.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
{
|
||||
/**
|
||||
* Holds all parameters that would be required for configuring a debug tool, for an AVR8 target.
|
||||
*
|
||||
* This can usually be extracted from the AVR8 TDF.
|
||||
* See Targets::Microchip::Avr::Avr8Bit::TargetDescription::TargetDescriptionFile::getTargetParameters();
|
||||
*/
|
||||
struct TargetParameters
|
||||
{
|
||||
std::optional<std::uint32_t> mappedIoSegmentStartAddress;
|
||||
std::optional<std::uint16_t> mappedIoSegmentSize;
|
||||
std::optional<std::uint32_t> bootSectionStartAddress;
|
||||
std::optional<std::uint32_t> gpRegisterStartAddress;
|
||||
std::optional<std::uint32_t> gpRegisterSize;
|
||||
std::optional<std::uint16_t> flashPageSize;
|
||||
std::optional<std::uint32_t> flashSize;
|
||||
std::optional<std::uint32_t> flashStartAddress;
|
||||
std::optional<std::uint16_t> ramStartAddress;
|
||||
std::optional<std::uint32_t> ramSize;
|
||||
std::optional<std::uint16_t> eepromStartAddress;
|
||||
std::optional<std::uint16_t> eepromSize;
|
||||
std::optional<std::uint8_t> eepromPageSize;
|
||||
std::optional<std::uint8_t> eepromAddressRegisterHigh;
|
||||
std::optional<std::uint8_t> eepromAddressRegisterLow;
|
||||
std::optional<std::uint8_t> eepromDataRegisterAddress;
|
||||
std::optional<std::uint8_t> eepromControlRegisterAddress;
|
||||
std::optional<std::uint8_t> ocdRevision;
|
||||
std::optional<std::uint8_t> ocdDataRegister;
|
||||
std::optional<std::uint16_t> statusRegisterStartAddress;
|
||||
std::optional<std::uint16_t> statusRegisterSize;
|
||||
std::optional<std::uint16_t> stackPointerRegisterLowAddress;
|
||||
std::optional<std::uint16_t> stackPointerRegisterSize;
|
||||
std::optional<std::uint8_t> spmcRegisterStartAddress;
|
||||
std::optional<std::uint8_t> osccalAddress;
|
||||
|
||||
// XMega/PDI/UPDI specific target params
|
||||
std::optional<std::uint32_t> appSectionPdiOffset;
|
||||
std::optional<std::uint32_t> appSectionStartAddress;
|
||||
std::optional<std::uint32_t> appSectionSize;
|
||||
std::optional<std::uint16_t> bootSectionSize;
|
||||
std::optional<std::uint32_t> bootSectionPdiOffset;
|
||||
std::optional<std::uint32_t> eepromPdiOffset;
|
||||
std::optional<std::uint32_t> ramPdiOffset;
|
||||
std::optional<std::uint32_t> fuseRegistersPdiOffset;
|
||||
std::optional<std::uint32_t> lockRegistersPdiOffset;
|
||||
std::optional<std::uint32_t> userSignaturesPdiOffset;
|
||||
std::optional<std::uint32_t> productSignaturesPdiOffset;
|
||||
std::optional<std::uint16_t> nvmModuleBaseAddress;
|
||||
std::optional<std::uint16_t> mcuModuleBaseAddress;
|
||||
|
||||
// UPDI specific target params
|
||||
std::optional<std::uint16_t> ocdModuleAddress;
|
||||
std::optional<std::uint32_t> programMemoryUpdiStartAddress;
|
||||
std::optional<std::uint16_t> signatureSegmentStartAddress;
|
||||
std::optional<std::uint16_t> signatureSegmentSize;
|
||||
std::optional<std::uint16_t> fuseSegmentStartAddress;
|
||||
std::optional<std::uint16_t> fuseSegmentSize;
|
||||
std::optional<std::uint16_t> lockbitsSegmentStartAddress;
|
||||
};
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr
|
||||
{
|
||||
enum class FuseType: std::uint8_t
|
||||
{
|
||||
LOW,
|
||||
HIGH,
|
||||
EXTENDED,
|
||||
OTHER,
|
||||
};
|
||||
|
||||
enum class FuseEnableStrategy: std::uint8_t
|
||||
{
|
||||
CLEAR,
|
||||
SET,
|
||||
};
|
||||
|
||||
struct Fuse
|
||||
{
|
||||
FuseType type;
|
||||
std::uint8_t value;
|
||||
|
||||
Fuse(FuseType type, std::uint8_t value)
|
||||
: type(type)
|
||||
, value(value)
|
||||
{}
|
||||
};
|
||||
|
||||
struct FuseBitsDescriptor
|
||||
{
|
||||
TargetMemoryAddress byteAddress;
|
||||
|
||||
/**
|
||||
* The type of the fuse byte in which the fuse bits resides.
|
||||
*/
|
||||
FuseType fuseType;
|
||||
|
||||
/**
|
||||
* Fuse bits mask
|
||||
*/
|
||||
std::uint8_t bitMask;
|
||||
|
||||
FuseBitsDescriptor(TargetMemoryAddress byteAddress, FuseType fuseType, std::uint8_t bitMask)
|
||||
: byteAddress(byteAddress)
|
||||
, fuseType(fuseType)
|
||||
, bitMask(bitMask)
|
||||
{}
|
||||
};
|
||||
}
|
||||
1154
src/Targets/Microchip/AVR8/Avr8.cpp
Normal file
1154
src/Targets/Microchip/AVR8/Avr8.cpp
Normal file
File diff suppressed because it is too large
Load Diff
232
src/Targets/Microchip/AVR8/Avr8.hpp
Normal file
232
src/Targets/Microchip/AVR8/Avr8.hpp
Normal file
@@ -0,0 +1,232 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/Target.hpp"
|
||||
#include "src/DebugToolDrivers/DebugTool.hpp"
|
||||
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/Microchip/AVR8/Avr8DebugInterface.hpp"
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/Microchip/AVR8/AvrIspInterface.hpp"
|
||||
|
||||
#include "Family.hpp"
|
||||
#include "GpioPadDescriptor.hpp"
|
||||
#include "ProgramMemorySection.hpp"
|
||||
#include "ProgrammingSession.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR8/Fuse.hpp"
|
||||
#include "src/Targets/TargetPhysicalInterface.hpp"
|
||||
#include "src/Targets/TargetRegisterDescriptor.hpp"
|
||||
#include "src/Targets/TargetBitFieldDescriptor.hpp"
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
|
||||
#include "TargetDescriptionFile.hpp"
|
||||
|
||||
#include "Avr8TargetConfig.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
class Avr8: public Target
|
||||
{
|
||||
public:
|
||||
explicit Avr8(const TargetConfig& targetConfig, TargetDescriptionFile&& targetDescriptionFile);
|
||||
|
||||
/*
|
||||
* The functions below implement the Target interface for AVR8 targets.
|
||||
*
|
||||
* See the Targets::Target abstract class for documentation on the expected behaviour of
|
||||
* each function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* All AVR8 compatible debug tools must provide a valid Avr8Interface.
|
||||
*
|
||||
* @param debugTool
|
||||
* @return
|
||||
*/
|
||||
bool supportsDebugTool(DebugTool* debugTool) override;
|
||||
|
||||
void setDebugTool(DebugTool* debugTool) override;
|
||||
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
TargetDescriptor targetDescriptor() override;
|
||||
|
||||
void run(std::optional<TargetMemoryAddress> toAddress) override;
|
||||
void stop() override;
|
||||
void step() override;
|
||||
void reset() override;
|
||||
|
||||
void setSoftwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void removeSoftwareBreakpoint(TargetMemoryAddress address) override;
|
||||
|
||||
void setHardwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void removeHardwareBreakpoint(TargetMemoryAddress address) override;
|
||||
void clearAllBreakpoints() override;
|
||||
|
||||
TargetRegisterDescriptorAndValuePairs readRegisters(const TargetRegisterDescriptors& descriptors) override;
|
||||
void writeRegisters(const TargetRegisterDescriptorAndValuePairs& registers) override;
|
||||
|
||||
TargetMemoryBuffer readMemory(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
TargetMemoryAddress startAddress,
|
||||
TargetMemorySize bytes,
|
||||
const std::set<TargetMemoryAddressRange>& excludedAddressRanges
|
||||
) override;
|
||||
void writeMemory(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
TargetMemoryAddress startAddress,
|
||||
const TargetMemoryBuffer& buffer
|
||||
) override;
|
||||
bool isProgramMemory(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
TargetMemoryAddress startAddress,
|
||||
TargetMemorySize size
|
||||
) override;
|
||||
void eraseMemory(
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const TargetMemorySegmentDescriptor& memorySegmentDescriptor
|
||||
) override;
|
||||
|
||||
TargetExecutionState getExecutionState() override;
|
||||
|
||||
TargetMemoryAddress getProgramCounter() override;
|
||||
void setProgramCounter(TargetMemoryAddress programCounter) override;
|
||||
|
||||
TargetStackPointer getStackPointer() override;
|
||||
void setStackPointer(TargetStackPointer stackPointer) override;
|
||||
|
||||
TargetGpioPinDescriptorAndStatePairs getGpioPinStates(const TargetPinoutDescriptor& pinoutDescriptor) override;
|
||||
void setGpioPinState(const TargetPinDescriptor& pinDescriptor, const TargetGpioPinState& state) override;
|
||||
|
||||
void enableProgrammingMode() override;
|
||||
|
||||
void disableProgrammingMode() override;
|
||||
|
||||
bool programmingModeEnabled() override;
|
||||
|
||||
protected:
|
||||
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* targetPowerManagementInterface = nullptr;
|
||||
DebugToolDrivers::TargetInterfaces::Microchip::Avr8::Avr8DebugInterface* avr8DebugInterface = nullptr;
|
||||
DebugToolDrivers::TargetInterfaces::Microchip::Avr8::AvrIspInterface* avrIspInterface = nullptr;
|
||||
|
||||
Avr8TargetConfig targetConfig;
|
||||
TargetDescriptionFile targetDescriptionFile;
|
||||
|
||||
TargetAddressSpaceDescriptor dataAddressSpaceDescriptor;
|
||||
TargetAddressSpaceDescriptor fuseAddressSpaceDescriptor;
|
||||
|
||||
TargetMemorySegmentDescriptor ramMemorySegmentDescriptor;
|
||||
TargetMemorySegmentDescriptor ioMemorySegmentDescriptor;
|
||||
TargetMemorySegmentDescriptor fuseMemorySegmentDescriptor;
|
||||
|
||||
TargetSignature signature;
|
||||
Family family;
|
||||
|
||||
bool activated = false;
|
||||
|
||||
std::set<TargetPhysicalInterface> physicalInterfaces;
|
||||
|
||||
std::vector<TargetPeripheralDescriptor> gpioPortPeripheralDescriptors;
|
||||
std::map<std::string, GpioPadDescriptor> gpioPadDescriptorsByPadName;
|
||||
|
||||
/**
|
||||
* The stack pointer register on AVR8 targets can take several forms:
|
||||
*
|
||||
* 1. A single 8 or 16-bit register in the CPU peripheral, with key "sp"
|
||||
* 2. Two 8-bit registers for high and low bytes in a 16-bit stack pointer, in the CPU peripheral, with keys
|
||||
* "spl" and "sph"
|
||||
* 3. A single 8-bit low byte register for an 8-bit stack pointer, in the CPU peripheral. This is similar
|
||||
* to 1, but with key "spl"
|
||||
*/
|
||||
std::optional<TargetRegisterDescriptor> spRegisterDescriptor;
|
||||
std::optional<TargetRegisterDescriptor> spLowRegisterDescriptor;
|
||||
std::optional<TargetRegisterDescriptor> spHighRegisterDescriptor;
|
||||
|
||||
/**
|
||||
* On some AVR8 targets, like the ATmega328P, a cleared fuse bit means the fuse is "programmed" (enabled).
|
||||
* And a set bit means the fuse is "un-programmed" (disabled). But on others, like the ATmega4809, it's the
|
||||
* other way around (set bit == enabled, cleared bit == disabled).
|
||||
*
|
||||
* The FuseEnableStrategy specifies the strategy of enabling a fuse. It's extracted from the TDF.
|
||||
* See TargetDescription::getFuseEnableStrategy() for more.
|
||||
*/
|
||||
FuseEnableStrategy fuseEnableStrategy;
|
||||
|
||||
std::optional<ProgrammingSession> activeProgrammingSession = std::nullopt;
|
||||
|
||||
static std::map<std::string, GpioPadDescriptor> generateGpioPadDescriptorMapping(
|
||||
const std::vector<TargetPeripheralDescriptor>& portPeripheralDescriptors
|
||||
);
|
||||
|
||||
TargetMemoryBuffer readRegister(const TargetRegisterDescriptor& descriptor);
|
||||
void writeRegister(const TargetRegisterDescriptor& descriptor, const TargetMemoryBuffer& value) ;
|
||||
|
||||
void applyDebugInterfaceRegisterAccessRestrictions(
|
||||
TargetRegisterGroupDescriptor& groupDescriptor,
|
||||
const TargetAddressSpaceDescriptor& addressSpaceDescriptor
|
||||
);
|
||||
|
||||
BreakpointResources getBreakpointResources();
|
||||
|
||||
/**
|
||||
* Checks if a particular fuse is enabled in the given fuse byte value. Takes the target's fuse enable strategy
|
||||
* into account.
|
||||
*
|
||||
* @param bitFieldDescriptor
|
||||
* @param value
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
bool isFuseEnabled(const TargetBitFieldDescriptor& bitFieldDescriptor, FuseValue value) const;
|
||||
|
||||
/**
|
||||
* Enables/disables a fuse within the given fuse byte, using the target's fuse enable strategy.
|
||||
*
|
||||
* @param bitFieldDescriptor
|
||||
* @param value
|
||||
* @param enabled
|
||||
*
|
||||
* @return
|
||||
* The updated fuse byte value.
|
||||
*/
|
||||
FuseValue setFuseEnabled(
|
||||
const TargetBitFieldDescriptor& bitFieldDescriptor,
|
||||
FuseValue value,
|
||||
bool enabled
|
||||
) const;
|
||||
|
||||
/**
|
||||
* Updates the debugWIRE enable (DWEN) fuse bit on the AVR target.
|
||||
*
|
||||
* @param enable
|
||||
* True to enable the fuse, false to disable it.
|
||||
*/
|
||||
void updateDwenFuseBit(bool enable);
|
||||
|
||||
/**
|
||||
* Updates the On-chip debug enable (OCDEN) fuse bit on the AVR target.
|
||||
*
|
||||
* @param enable
|
||||
* True to enable the fuse, false to disable it.
|
||||
*/
|
||||
void updateOcdenFuseBit(bool enable);
|
||||
|
||||
/**
|
||||
* Updates the "Preserve EEPROM" (EESAVE) fuse bit on the AVR target.
|
||||
*
|
||||
* @param enable
|
||||
* True to enable the fuse, false to disable it.
|
||||
*
|
||||
* @return
|
||||
* True if the fuse bit was updated. False if the fuse bit was already set to the desired value.
|
||||
*/
|
||||
bool updateEesaveFuseBit(bool enable);
|
||||
};
|
||||
}
|
||||
@@ -1,17 +1,10 @@
|
||||
#include "Avr8TargetConfig.hpp"
|
||||
|
||||
#include "src/Services/PathService.hpp"
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
#include "src/Exceptions/InvalidConfig.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
Avr8TargetConfig::Avr8TargetConfig(const TargetConfig& targetConfig)
|
||||
: TargetConfig(targetConfig)
|
||||
{
|
||||
using Exceptions::InvalidConfig;
|
||||
|
||||
const auto& targetNode = targetConfig.targetNode;
|
||||
|
||||
// The 'manageDwenFuseBit' param used to be 'updateDwenFuseBit' - we still support the old, for now.
|
||||
@@ -40,9 +33,9 @@ namespace Targets::Microchip::Avr::Avr8Bit
|
||||
}
|
||||
|
||||
if (targetNode["targetPowerCycleDelay"]) {
|
||||
this->targetPowerCycleDelay = std::chrono::milliseconds(targetNode["targetPowerCycleDelay"].as<int>(
|
||||
this->targetPowerCycleDelay = std::chrono::milliseconds{targetNode["targetPowerCycleDelay"].as<int>(
|
||||
this->targetPowerCycleDelay.count()
|
||||
));
|
||||
)};
|
||||
}
|
||||
|
||||
if (targetNode["manageOcdenFuseBit"]) {
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "src/ProjectConfig.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
/**
|
||||
* Extending the generic TargetConfig struct to accommodate AVR8 target configuration parameters.
|
||||
@@ -15,15 +15,15 @@ namespace Targets::Microchip::Avr::Avr8Bit
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Because the debugWire module requires control of the reset pin on the target, enabling this module will
|
||||
* 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.
|
||||
* 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
|
||||
* 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
|
||||
* 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.
|
||||
@@ -35,7 +35,7 @@ namespace Targets::Microchip::Avr::Avr8Bit
|
||||
bool disableDebugWireOnDeactivate = false;
|
||||
|
||||
/**
|
||||
* The manageDwenFuseBit flag determines if Bloom should manage the DWEN fuse bit, for debugWire sessions.
|
||||
* The manageDwenFuseBit 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.
|
||||
@@ -44,7 +44,7 @@ namespace Targets::Microchip::Avr::Avr8Bit
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
@@ -57,7 +57,7 @@ namespace Targets::Microchip::Avr::Avr8Bit
|
||||
*
|
||||
* This parameter determines how long we wait.
|
||||
*/
|
||||
std::chrono::milliseconds targetPowerCycleDelay = std::chrono::milliseconds(250);
|
||||
std::chrono::milliseconds targetPowerCycleDelay = std::chrono::milliseconds{250};
|
||||
|
||||
/**
|
||||
* The manageOcdenFuseBit flag determines if Bloom should manage the OCDEN fuse but on JTAG-enabled AVR
|
||||
@@ -10,9 +10,5 @@ namespace Exceptions
|
||||
explicit DebugWirePhysicalInterfaceError(const std::string& message)
|
||||
: TargetOperationFailure(message)
|
||||
{}
|
||||
|
||||
explicit DebugWirePhysicalInterfaceError(const char* message)
|
||||
: TargetOperationFailure(message)
|
||||
{}
|
||||
};
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
enum class Family: int
|
||||
{
|
||||
MEGA,
|
||||
XMEGA,
|
||||
TINY,
|
||||
DB,
|
||||
DA,
|
||||
DB,
|
||||
DD,
|
||||
EA,
|
||||
};
|
||||
24
src/Targets/Microchip/AVR8/Fuse.hpp
Normal file
24
src/Targets/Microchip/AVR8/Fuse.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
using FuseValue = std::uint8_t;
|
||||
|
||||
enum class FuseType: std::uint8_t
|
||||
{
|
||||
LOW,
|
||||
HIGH,
|
||||
EXTENDED,
|
||||
OTHER,
|
||||
};
|
||||
|
||||
enum class FuseEnableStrategy: std::uint8_t
|
||||
{
|
||||
CLEAR,
|
||||
SET,
|
||||
};
|
||||
}
|
||||
34
src/Targets/Microchip/AVR8/GpioPadDescriptor.hpp
Normal file
34
src/Targets/Microchip/AVR8/GpioPadDescriptor.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/Targets/TargetRegisterDescriptor.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
/**
|
||||
* This struct contains all of the relevant GPIO register descriptors for a particular pad, on an AVR8 target.
|
||||
*
|
||||
* We use this to read and manipulate the state of GPIO pins.
|
||||
*/
|
||||
struct GpioPadDescriptor
|
||||
{
|
||||
std::uint8_t registerMask;
|
||||
|
||||
const TargetRegisterDescriptor& dataDirectionRegisterDescriptor;
|
||||
const TargetRegisterDescriptor& inputRegisterDescriptor;
|
||||
const TargetRegisterDescriptor& outputRegisterDescriptor;
|
||||
|
||||
GpioPadDescriptor(
|
||||
std::uint8_t registerMask,
|
||||
const TargetRegisterDescriptor& dataDirectionRegisterDescriptor,
|
||||
const TargetRegisterDescriptor& inputRegisterDescriptor,
|
||||
const TargetRegisterDescriptor& outputRegisterDescriptor
|
||||
)
|
||||
: registerMask(registerMask)
|
||||
, dataDirectionRegisterDescriptor(dataDirectionRegisterDescriptor)
|
||||
, inputRegisterDescriptor(inputRegisterDescriptor)
|
||||
, outputRegisterDescriptor(outputRegisterDescriptor)
|
||||
{}
|
||||
};
|
||||
}
|
||||
29
src/Targets/Microchip/AVR8/IspParameters.cpp
Normal file
29
src/Targets/Microchip/AVR8/IspParameters.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "IspParameters.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
IspParameters::IspParameters(const TargetDescriptionFile& targetDescriptionFile) {
|
||||
using Services::StringService;
|
||||
|
||||
const auto& ispGroup = targetDescriptionFile.getPropertyGroup("isp_interface");
|
||||
|
||||
this->programModeTimeout = StringService::toUint8(ispGroup.getProperty("ispenterprogmode_timeout").value);
|
||||
this->programModeStabilizationDelay = StringService::toUint8(
|
||||
ispGroup.getProperty("ispenterprogmode_stabdelay").value
|
||||
);
|
||||
this->programModeCommandExecutionDelay = StringService::toUint8(
|
||||
ispGroup.getProperty("ispenterprogmode_cmdexedelay").value
|
||||
);
|
||||
this->programModeSyncLoops = StringService::toUint8(ispGroup.getProperty("ispenterprogmode_synchloops").value);
|
||||
this->programModeByteDelay = StringService::toUint8(ispGroup.getProperty("ispenterprogmode_bytedelay").value);
|
||||
this->programModePollValue = StringService::toUint8(ispGroup.getProperty("ispenterprogmode_pollvalue").value);
|
||||
this->programModePollIndex = StringService::toUint8(ispGroup.getProperty("ispenterprogmode_pollindex").value);
|
||||
this->programModePreDelay = StringService::toUint8(ispGroup.getProperty("ispleaveprogmode_predelay").value);
|
||||
this->programModePostDelay = StringService::toUint8(ispGroup.getProperty("ispleaveprogmode_postdelay").value);
|
||||
this->readSignaturePollIndex = StringService::toUint8(ispGroup.getProperty("ispreadsign_pollindex").value);
|
||||
this->readFusePollIndex = StringService::toUint8(ispGroup.getProperty("ispreadfuse_pollindex").value);
|
||||
this->readLockPollIndex = StringService::toUint8(ispGroup.getProperty("ispreadlock_pollindex").value);
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Targets::Microchip::Avr
|
||||
#include "TargetDescriptionFile.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
/**
|
||||
* These parameters are required by the ISP interface. They can be extracted from the target's TDF.
|
||||
* These parameters are required by ISP interfaces, to enter programming mode.
|
||||
*
|
||||
* These parameters are not specific to the EDBG protocol, which is why they do not reside in the EDBG protocol
|
||||
* directory.
|
||||
*/
|
||||
struct IspParameters
|
||||
{
|
||||
@@ -18,9 +23,10 @@ namespace Targets::Microchip::Avr
|
||||
std::uint8_t programModePollIndex;
|
||||
std::uint8_t programModePreDelay;
|
||||
std::uint8_t programModePostDelay;
|
||||
|
||||
std::uint8_t readSignaturePollIndex;
|
||||
std::uint8_t readFusePollIndex;
|
||||
std::uint8_t readLockPollIndex;
|
||||
|
||||
explicit IspParameters(const TargetDescriptionFile& targetDescriptionFile);
|
||||
};
|
||||
}
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
#include "Exceptions/DecodeFailure.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
namespace Targets::Microchip::Avr8::OpcodeDecoder
|
||||
{
|
||||
Decoder::InstructionMapping Decoder::decode(
|
||||
Targets::TargetMemoryAddress startByteAddress,
|
||||
const TargetMemoryBuffer& data,
|
||||
bool throwOnFailure
|
||||
) {
|
||||
auto output = Decoder::InstructionMapping();
|
||||
auto output = Decoder::InstructionMapping{};
|
||||
|
||||
static const auto decoders = Decoder::opcodeDecoders();
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
|
||||
if (instruction.has_value()) {
|
||||
const auto instructionSize = instruction->byteSize;
|
||||
output.insert(std::pair(instructionByteAddress, std::move(*instruction)));
|
||||
output.emplace(instructionByteAddress, std::move(*instruction));
|
||||
|
||||
dataIt += instructionSize;
|
||||
instructionByteAddress += instructionSize;
|
||||
@@ -40,13 +40,13 @@ namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
|
||||
if (!opcodeMatched) {
|
||||
if (throwOnFailure) {
|
||||
throw Exceptions::DecodeFailure(
|
||||
throw Exceptions::DecodeFailure{
|
||||
instructionByteAddress,
|
||||
static_cast<std::uint32_t>(*(dataIt + 1) << 8) | *dataIt
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
output.insert(std::pair(instructionByteAddress, std::nullopt));
|
||||
output.emplace(instructionByteAddress, std::nullopt);
|
||||
|
||||
dataIt += 2;
|
||||
instructionByteAddress += 2;
|
||||
@@ -62,7 +62,7 @@ namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
*
|
||||
* I've used the same order that is used in the AVR implementation of GDB.
|
||||
*/
|
||||
return Decoder::OpcodeDecoders({
|
||||
return Decoder::OpcodeDecoders{
|
||||
std::bind(&Opcodes::UndefinedOrErased::decode, std::placeholders::_1, std::placeholders::_2),
|
||||
std::bind(&Opcodes::Clc::decode, std::placeholders::_1, std::placeholders::_2),
|
||||
std::bind(&Opcodes::Clh::decode, std::placeholders::_1, std::placeholders::_2),
|
||||
@@ -208,6 +208,6 @@ namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
std::bind(&Opcodes::Eicall::decode, std::placeholders::_1, std::placeholders::_2),
|
||||
std::bind(&Opcodes::Eijmp::decode, std::placeholders::_1, std::placeholders::_2),
|
||||
std::bind(&Opcodes::Des::decode, std::placeholders::_1, std::placeholders::_2),
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
#include "src/Services/BitsetService.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
namespace Targets::Microchip::Avr8::OpcodeDecoder
|
||||
{
|
||||
class Decoder
|
||||
{
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder::Exceptions
|
||||
namespace Targets::Microchip::Avr8::OpcodeDecoder::Exceptions
|
||||
{
|
||||
class DecodeFailure: public ::Exceptions::Exception
|
||||
{
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
namespace Targets::Microchip::Avr8::OpcodeDecoder
|
||||
{
|
||||
struct Instruction
|
||||
{
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
#include "src/Services/BitsetService.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
namespace Targets::Microchip::Avr8::OpcodeDecoder
|
||||
{
|
||||
struct InstructionParameterBase
|
||||
{};
|
||||
@@ -520,13 +520,13 @@ namespace Targets::Microchip::Avr::Avr8Bit::OpcodeDecoder
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto output = Instruction(
|
||||
auto output = Instruction{
|
||||
SelfType::name,
|
||||
opcode,
|
||||
byteSize,
|
||||
mnemonic,
|
||||
canChangeProgramFlow
|
||||
);
|
||||
};
|
||||
|
||||
if constexpr (decltype(sourceRegisterParameter)::hasValue()) {
|
||||
constexpr auto param = sourceRegisterParameter.value;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
enum class ProgramMemorySection: std::uint8_t
|
||||
{
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Targets::Microchip::Avr::Avr8Bit
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
/**
|
||||
* Information relating to a specific AVR8 programming session.
|
||||
195
src/Targets/Microchip/AVR8/TargetDescriptionFile.cpp
Normal file
195
src/Targets/Microchip/AVR8/TargetDescriptionFile.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "TargetDescriptionFile.hpp"
|
||||
|
||||
#include "src/Services/PathService.hpp"
|
||||
#include "src/Services/StringService.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
#include "src/Targets/TargetDescription/Exceptions/TargetDescriptionParsingFailureException.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
using Targets::TargetDescription::RegisterGroup;
|
||||
using Targets::TargetDescription::AddressSpace;
|
||||
using Targets::TargetDescription::MemorySegment;
|
||||
using Targets::TargetDescription::Register;
|
||||
using Targets::TargetDescription::Exceptions::InvalidTargetDescriptionDataException;
|
||||
using Targets::TargetRegisterDescriptor;
|
||||
using Services::StringService;
|
||||
|
||||
TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath)
|
||||
: Targets::TargetDescription::TargetDescriptionFile(xmlFilePath)
|
||||
{}
|
||||
|
||||
TargetSignature TargetDescriptionFile::getTargetSignature() const {
|
||||
const auto& signatureGroup = this->getPropertyGroup("signatures");
|
||||
|
||||
return {
|
||||
StringService::toUint8(signatureGroup.getProperty("signature0").value, 16),
|
||||
StringService::toUint8(signatureGroup.getProperty("signature1").value, 16),
|
||||
StringService::toUint8(signatureGroup.getProperty("signature2").value, 16)
|
||||
};
|
||||
}
|
||||
|
||||
Family TargetDescriptionFile::getAvrFamily() const {
|
||||
static const auto targetFamiliesByName = std::map<std::string, Family>{
|
||||
{"MEGA", Family::MEGA},
|
||||
{"XMEGA", Family::XMEGA},
|
||||
{"TINY", Family::TINY},
|
||||
{"DA", Family::DA},
|
||||
{"DB", Family::DB},
|
||||
{"DD", Family::DD},
|
||||
{"EA", Family::EA},
|
||||
};
|
||||
|
||||
const auto familyIt = targetFamiliesByName.find(this->getDeviceAttribute("avr-family"));
|
||||
if (familyIt == targetFamiliesByName.end()) {
|
||||
throw InvalidTargetDescriptionDataException{"Unknown AVR family name in target description file"};
|
||||
}
|
||||
|
||||
return familyIt->second;
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getRegisterFileAddressSpace() const {
|
||||
/*
|
||||
* On some AVRs, the register file is accessible via the data address space. On the newer UPDI and PDI AVRs,
|
||||
* it has a dedicated address space.
|
||||
*/
|
||||
const auto addressSpace = this->tryGetAddressSpace("register_file");
|
||||
return addressSpace.has_value()
|
||||
? addressSpace->get()
|
||||
: this->getAddressSpace("data");
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getProgramAddressSpace() const {
|
||||
return this->getAddressSpace("prog");
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getDataAddressSpace() const {
|
||||
return this->getAddressSpace("data");
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getEepromAddressSpace() const {
|
||||
const auto addressSpace = this->tryGetAddressSpace("eeprom");
|
||||
return addressSpace.has_value()
|
||||
? addressSpace->get()
|
||||
: this->getAddressSpace("data");
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getIoAddressSpace() const {
|
||||
return this->getAddressSpace("data");
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getSignatureAddressSpace() const {
|
||||
const auto addressSpace = this->tryGetAddressSpace("signatures");
|
||||
return addressSpace.has_value()
|
||||
? addressSpace->get()
|
||||
: this->getAddressSpace("data");
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getFuseAddressSpace() const {
|
||||
const auto addressSpace = this->tryGetAddressSpace("fuses");
|
||||
return addressSpace.has_value()
|
||||
? addressSpace->get()
|
||||
: this->getAddressSpace("data");
|
||||
}
|
||||
|
||||
const TargetDescription::AddressSpace& TargetDescriptionFile::getLockbitAddressSpace() const {
|
||||
const auto addressSpace = this->tryGetAddressSpace("lockbits");
|
||||
return addressSpace.has_value()
|
||||
? addressSpace->get()
|
||||
: this->getAddressSpace("data");
|
||||
}
|
||||
|
||||
const TargetDescription::MemorySegment& TargetDescriptionFile::getProgramMemorySegment() const {
|
||||
return this->getProgramAddressSpace().getMemorySegment("internal_program_memory");
|
||||
}
|
||||
|
||||
const TargetDescription::MemorySegment& TargetDescriptionFile::getRamMemorySegment() const {
|
||||
return this->getDataAddressSpace().getMemorySegment("internal_ram");
|
||||
}
|
||||
|
||||
const TargetDescription::MemorySegment& TargetDescriptionFile::getEepromMemorySegment() const {
|
||||
return this->getEepromAddressSpace().getMemorySegment("internal_eeprom");
|
||||
}
|
||||
|
||||
const TargetDescription::MemorySegment& TargetDescriptionFile::getIoMemorySegment() const {
|
||||
const auto addressSpace = this->getIoAddressSpace();
|
||||
const auto segment = addressSpace.tryGetMemorySegment("io");
|
||||
return segment.has_value()
|
||||
? segment->get()
|
||||
: addressSpace.getMemorySegment("mapped_io");
|
||||
}
|
||||
|
||||
const TargetDescription::MemorySegment& TargetDescriptionFile::getSignatureMemorySegment() const {
|
||||
return this->getSignatureAddressSpace().getMemorySegment("signatures");
|
||||
}
|
||||
|
||||
const TargetDescription::MemorySegment& TargetDescriptionFile::getFuseMemorySegment() const {
|
||||
return this->getFuseAddressSpace().getMemorySegment("fuses");
|
||||
}
|
||||
|
||||
const TargetDescription::MemorySegment& TargetDescriptionFile::getLockbitMemorySegment() const {
|
||||
return this->getLockbitAddressSpace().getMemorySegment("lockbits");
|
||||
}
|
||||
|
||||
TargetAddressSpaceDescriptor TargetDescriptionFile::getDataAddressSpaceDescriptor() const {
|
||||
return this->targetAddressSpaceDescriptorFromAddressSpace(this->getDataAddressSpace());
|
||||
}
|
||||
|
||||
TargetAddressSpaceDescriptor TargetDescriptionFile::getFuseAddressSpaceDescriptor() const {
|
||||
return this->targetAddressSpaceDescriptorFromAddressSpace(this->getFuseAddressSpace());
|
||||
}
|
||||
|
||||
TargetMemorySegmentDescriptor TargetDescriptionFile::getRamMemorySegmentDescriptor() const {
|
||||
return this->targetMemorySegmentDescriptorFromMemorySegment(
|
||||
this->getRamMemorySegment(),
|
||||
this->getDataAddressSpace()
|
||||
);
|
||||
}
|
||||
|
||||
TargetMemorySegmentDescriptor TargetDescriptionFile::getFuseMemorySegmentDescriptor() const {
|
||||
return this->targetMemorySegmentDescriptorFromMemorySegment(
|
||||
this->getFuseMemorySegment(),
|
||||
this->getFuseAddressSpace()
|
||||
);
|
||||
}
|
||||
|
||||
TargetMemorySegmentDescriptor TargetDescriptionFile::getIoMemorySegmentDescriptor() const {
|
||||
return this->targetMemorySegmentDescriptorFromMemorySegment(
|
||||
this->getIoMemorySegment(),
|
||||
this->getIoAddressSpace()
|
||||
);
|
||||
}
|
||||
|
||||
TargetPeripheralDescriptor TargetDescriptionFile::getFuseTargetPeripheralDescriptor() const {
|
||||
return this->getTargetPeripheralDescriptor("fuse");
|
||||
}
|
||||
|
||||
Pair<
|
||||
TargetRegisterDescriptor,
|
||||
TargetBitFieldDescriptor
|
||||
> TargetDescriptionFile::getFuseRegisterBitFieldDescriptorPair(const std::string& fuseBitFieldKey) const {
|
||||
const auto peripheralDescriptor = this->getFuseTargetPeripheralDescriptor();
|
||||
const auto pair = peripheralDescriptor.getRegisterGroupDescriptor("fuse").getRegisterBitFieldDescriptorPair(
|
||||
fuseBitFieldKey
|
||||
);
|
||||
|
||||
return {pair.first.clone(), pair.second.clone()};
|
||||
}
|
||||
|
||||
std::optional<FuseEnableStrategy> TargetDescriptionFile::getFuseEnableStrategy() const {
|
||||
const auto fuseEnabledValueProperty = this->tryGetProperty("programming_info", "fuse_enabled_value");
|
||||
if (fuseEnabledValueProperty.has_value()) {
|
||||
if (fuseEnabledValueProperty->get().value == "0") {
|
||||
return FuseEnableStrategy::CLEAR;
|
||||
}
|
||||
|
||||
if (fuseEnabledValueProperty->get().value == "1") {
|
||||
return FuseEnableStrategy::SET;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
85
src/Targets/Microchip/AVR8/TargetDescriptionFile.hpp
Normal file
85
src/Targets/Microchip/AVR8/TargetDescriptionFile.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/TargetDescription/TargetDescriptionFile.hpp"
|
||||
|
||||
#include "src/Targets/TargetRegisterDescriptor.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR8/TargetSignature.hpp"
|
||||
#include "src/Targets/Microchip/AVR8/Fuse.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR8/Family.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
/**
|
||||
* AVR8 TDF
|
||||
*
|
||||
* For more information of TDFs, see src/Targets/TargetDescription/README.md
|
||||
*/
|
||||
class TargetDescriptionFile: public TargetDescription::TargetDescriptionFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among
|
||||
* other things.
|
||||
*
|
||||
* @param xml
|
||||
*/
|
||||
explicit TargetDescriptionFile(const std::string& xmlFilePath);
|
||||
|
||||
/**
|
||||
* Extracts the AVR8 target signature from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] TargetSignature getTargetSignature() const;
|
||||
|
||||
/**
|
||||
* Extracts the AVR8 target family from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] Family getAvrFamily() const;
|
||||
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getRegisterFileAddressSpace() const;
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getProgramAddressSpace() const;
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getDataAddressSpace() const;
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getEepromAddressSpace() const;
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getIoAddressSpace() const;
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getSignatureAddressSpace() const;
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getFuseAddressSpace() const;
|
||||
[[nodiscard]] const TargetDescription::AddressSpace& getLockbitAddressSpace() const;
|
||||
|
||||
[[nodiscard]] const TargetDescription::MemorySegment& getProgramMemorySegment() const;
|
||||
[[nodiscard]] const TargetDescription::MemorySegment& getRamMemorySegment() const;
|
||||
[[nodiscard]] const TargetDescription::MemorySegment& getEepromMemorySegment() const;
|
||||
[[nodiscard]] const TargetDescription::MemorySegment& getIoMemorySegment() const;
|
||||
[[nodiscard]] const TargetDescription::MemorySegment& getSignatureMemorySegment() const;
|
||||
[[nodiscard]] const TargetDescription::MemorySegment& getFuseMemorySegment() const;
|
||||
[[nodiscard]] const TargetDescription::MemorySegment& getLockbitMemorySegment() const;
|
||||
|
||||
[[nodiscard]] TargetAddressSpaceDescriptor getDataAddressSpaceDescriptor() const;
|
||||
[[nodiscard]] TargetAddressSpaceDescriptor getFuseAddressSpaceDescriptor() const;
|
||||
|
||||
[[nodiscard]] TargetMemorySegmentDescriptor getRamMemorySegmentDescriptor() const;
|
||||
[[nodiscard]] TargetMemorySegmentDescriptor getFuseMemorySegmentDescriptor() const;
|
||||
[[nodiscard]] TargetMemorySegmentDescriptor getIoMemorySegmentDescriptor() const;
|
||||
|
||||
[[nodiscard]] TargetPeripheralDescriptor getFuseTargetPeripheralDescriptor() const;
|
||||
[[nodiscard]] Pair<
|
||||
TargetRegisterDescriptor,
|
||||
TargetBitFieldDescriptor
|
||||
> getFuseRegisterBitFieldDescriptorPair(const std::string& fuseBitFieldKey) const;
|
||||
|
||||
/**
|
||||
* Extracts the target's fuse enable strategy.
|
||||
*
|
||||
* @return
|
||||
* std::nullopt if the TDF doesn't contain a fuse enable strategy.
|
||||
*/
|
||||
[[nodiscard]] std::optional<FuseEnableStrategy> getFuseEnableStrategy() const;
|
||||
};
|
||||
}
|
||||
@@ -4,10 +4,12 @@
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Targets::Microchip::Avr
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
namespace Targets::Microchip::Avr8
|
||||
{
|
||||
/**
|
||||
* All AVR targets carry a three-byte signature that is *usually* unique to the target.
|
||||
* All AVR8 targets carry a three-byte signature that is *usually* unique to the target.
|
||||
*
|
||||
* The AVR target signature consists of three bytes: 0xAABBCC
|
||||
* Byte AA (byteZero) identifies the manufacture of the target (usually 1E for Atmel/Microchip)
|
||||
@@ -15,11 +17,7 @@ namespace Targets::Microchip::Avr
|
||||
* Byte CC (byteTwo) identifies the target
|
||||
*
|
||||
* Some AVR targets have been found to carry identical signatures. For example, the AT90PWM1, AT90PWM2B
|
||||
* and the AT90PWM3B all carry a signature of 0x1E9383. Although these devices may not differ in
|
||||
* significant ways, Bloom does still take duplicate signatures into account, to ensure that the correct
|
||||
* target description file is used.
|
||||
*
|
||||
* This class represents an AVR target signature.
|
||||
* and the AT90PWM3B all carry a signature of 0x1E9383.
|
||||
*/
|
||||
struct TargetSignature
|
||||
{
|
||||
@@ -35,7 +33,7 @@ namespace Targets::Microchip::Avr
|
||||
{};
|
||||
|
||||
explicit TargetSignature(const std::string& hex) {
|
||||
const auto signature = static_cast<std::uint32_t>(std::stoul(hex, nullptr, 16));
|
||||
const auto signature = Services::StringService::toUint32(hex, 16);
|
||||
|
||||
this->byteZero = static_cast<unsigned char>(signature >> 16);
|
||||
this->byteOne = static_cast<unsigned char>(signature >> 8);
|
||||
@@ -43,7 +41,7 @@ namespace Targets::Microchip::Avr
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string toHex() const {
|
||||
std::stringstream stream;
|
||||
auto stream = std::stringstream{};
|
||||
stream << std::hex << std::setfill('0');
|
||||
stream << std::setw(2) << static_cast<unsigned int>(this->byteZero);
|
||||
stream << std::setw(2) << static_cast<unsigned int>(this->byteOne);
|
||||
Reference in New Issue
Block a user