From 79b7457c89341c4cc8ef97531a0af37e4afd43b6 Mon Sep 17 00:00:00 2001 From: Nav Date: Sat, 21 Dec 2024 02:10:31 +0000 Subject: [PATCH] GPIO pad state access and manipulation for WCH RISC-V targets --- src/Targets/RiscV/RiscV.cpp | 8 - src/Targets/RiscV/RiscV.hpp | 3 - src/Targets/RiscV/Wch/GpioPadDescriptor.hpp | 41 +++ src/Targets/RiscV/Wch/WchRiscV.cpp | 285 ++++++++++++++++++ src/Targets/RiscV/Wch/WchRiscV.hpp | 21 ++ .../TargetDescriptionFile.cpp | 24 +- .../TargetDescriptionFile.hpp | 6 +- src/Targets/TargetPeripheralDescriptor.cpp | 12 + src/Targets/TargetPeripheralDescriptor.hpp | 4 + 9 files changed, 384 insertions(+), 20 deletions(-) create mode 100644 src/Targets/RiscV/Wch/GpioPadDescriptor.hpp diff --git a/src/Targets/RiscV/RiscV.cpp b/src/Targets/RiscV/RiscV.cpp index 5310faf5..345a4f12 100644 --- a/src/Targets/RiscV/RiscV.cpp +++ b/src/Targets/RiscV/RiscV.cpp @@ -287,14 +287,6 @@ namespace Targets::RiscV }); } - TargetGpioPadDescriptorAndStatePairs RiscV::getGpioPadStates(const TargetPadDescriptors& padDescriptors) { - return {}; - } - - void RiscV::setGpioPadState(const TargetPadDescriptor& padDescriptor, const TargetGpioPadState& state) { - - } - void RiscV::enableProgrammingMode() { this->riscVDebugInterface->enableProgrammingMode(); this->programmingMode = true; diff --git a/src/Targets/RiscV/RiscV.hpp b/src/Targets/RiscV/RiscV.hpp index 31259e9b..55ea72e8 100644 --- a/src/Targets/RiscV/RiscV.hpp +++ b/src/Targets/RiscV/RiscV.hpp @@ -77,9 +77,6 @@ namespace Targets::RiscV TargetStackPointer getStackPointer() override; void setStackPointer(TargetStackPointer stackPointer) override; - TargetGpioPadDescriptorAndStatePairs getGpioPadStates(const TargetPadDescriptors& padDescriptors) override; - void setGpioPadState(const TargetPadDescriptor& padDescriptor, const TargetGpioPadState& state) override; - void enableProgrammingMode() override; void disableProgrammingMode() override; bool programmingModeEnabled() override; diff --git a/src/Targets/RiscV/Wch/GpioPadDescriptor.hpp b/src/Targets/RiscV/Wch/GpioPadDescriptor.hpp new file mode 100644 index 00000000..7d8dbe6f --- /dev/null +++ b/src/Targets/RiscV/Wch/GpioPadDescriptor.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include "src/Targets/TargetPadDescriptor.hpp" +#include "src/Targets/TargetRegisterDescriptor.hpp" +#include "src/Targets/TargetBitFieldDescriptor.hpp" + +namespace Targets::RiscV::Wch +{ + enum class GpioPadDirection: std::uint8_t + { + INPUT = 0x00, + OUTPUT = 0x01, + }; + + enum class GpioPadInputMode: std::uint8_t + { + ANALOG = 0x00, + FLOATING = 0x01, + PULLED = 0x10, + }; + + enum class GpioPadOutputMode: std::uint8_t + { + GENERAL_PURPOSE = 0x00, + ALTERNATE_FUNCTION = 0x01, + }; + + struct GpioPadDescriptor + { + const TargetBitFieldDescriptor& peripheralClockEnableBitFieldDescriptor; + const TargetRegisterDescriptor& configRegisterDescriptor; + const TargetBitFieldDescriptor& configBitFieldDescriptor; + const TargetBitFieldDescriptor& modeBitFieldDescriptor; + const TargetRegisterDescriptor& inputDataRegisterDescriptor; + const TargetBitFieldDescriptor& inputDataBitFieldDescriptor; + const TargetRegisterDescriptor& outputDataRegisterDescriptor; + const TargetBitFieldDescriptor& outputDataBitFieldDescriptor; + }; +} diff --git a/src/Targets/RiscV/Wch/WchRiscV.cpp b/src/Targets/RiscV/Wch/WchRiscV.cpp index 6b949089..9170ebb1 100644 --- a/src/Targets/RiscV/Wch/WchRiscV.cpp +++ b/src/Targets/RiscV/Wch/WchRiscV.cpp @@ -38,6 +38,19 @@ namespace Targets::RiscV::Wch , flashStatusRegisterDescriptor(this->flashPeripheralDescriptor.getRegisterDescriptor("flash", "statr")) , flashStatusBootLockFieldDescriptor(this->flashStatusRegisterDescriptor.getBitFieldDescriptor("boot_lock")) , flashStatusBootModeFieldDescriptor(this->flashStatusRegisterDescriptor.getBitFieldDescriptor("boot_mode")) + , rccPeripheralDescriptor(this->targetDescriptionFile.getTargetPeripheralDescriptor("rcc")) + , portPeripheralClockEnableRegisterDescriptor( + this->rccPeripheralDescriptor.getRegisterDescriptor("rcc", "apb2pcenr") + ) + , padDescriptors(this->targetDescriptionFile.targetPadDescriptors()) + , gpioPortPeripheralDescriptors(this->targetDescriptionFile.gpioPortPeripheralDescriptors()) + , gpioPadDescriptorsByPadId( + WchRiscV::generateGpioPadDescriptorMapping( + this->portPeripheralClockEnableRegisterDescriptor, + this->gpioPortPeripheralDescriptors, + this->padDescriptors + ) + ) { if ( this->targetConfig.programSegmentKey.has_value() @@ -363,6 +376,112 @@ namespace Targets::RiscV::Wch return programCounter; } + TargetGpioPadDescriptorAndStatePairs WchRiscV::getGpioPadStates(const TargetPadDescriptors& padDescriptors) { + auto cachedRegsById = std::unordered_map{}; + const auto readGpioReg = [this, &cachedRegsById] (const TargetRegisterDescriptor& descriptor) + -> DynamicRegisterValue& { + auto cachedRegIt = cachedRegsById.find(descriptor.id); + if (cachedRegIt == cachedRegsById.end()) { + cachedRegIt = cachedRegsById.emplace( + descriptor.id, + this->readRegisterDynamicValue(descriptor) + ).first; + } + + return cachedRegIt->second; + }; + + auto output = TargetGpioPadDescriptorAndStatePairs{}; + + for (const auto* padDescriptor : padDescriptors) { + const auto gpioPadDescriptorIt = this->gpioPadDescriptorsByPadId.find(padDescriptor->id); + if (gpioPadDescriptorIt == this->gpioPadDescriptorsByPadId.end()) { + continue; + } + + const auto& gpioPadDescriptor = gpioPadDescriptorIt->second; + + const auto& portClockEnableRegisterValue = readGpioReg(this->portPeripheralClockEnableRegisterDescriptor); + if (!portClockEnableRegisterValue.bitFieldAs(gpioPadDescriptor.peripheralClockEnableBitFieldDescriptor)) { + // The port peripheral is currently disabled. We cannot obtain any meaningful state for this pad + continue; + } + + const auto& configRegisterValue = readGpioReg(gpioPadDescriptor.configRegisterDescriptor); + const auto padMode = configRegisterValue.bitField(gpioPadDescriptor.modeBitFieldDescriptor); + + if (padMode == static_cast(GpioPadDirection::INPUT)) { + output.emplace_back( + TargetGpioPadDescriptorAndStatePair{ + *padDescriptor, + TargetGpioPadState{ + readGpioReg(gpioPadDescriptor.inputDataRegisterDescriptor).bitFieldAs( + gpioPadDescriptor.inputDataBitFieldDescriptor + ) ? TargetGpioPadState::State::HIGH : TargetGpioPadState::State::LOW, + TargetGpioPadState::DataDirection::INPUT + } + } + ); + + continue; + } + + output.emplace_back( + TargetGpioPadDescriptorAndStatePair{ + *padDescriptor, + TargetGpioPadState{ + readGpioReg(gpioPadDescriptor.outputDataRegisterDescriptor).bitFieldAs( + gpioPadDescriptor.outputDataBitFieldDescriptor + ) ? TargetGpioPadState::State::HIGH : TargetGpioPadState::State::LOW, + TargetGpioPadState::DataDirection::OUTPUT + } + } + ); + } + + return output; + } + + void WchRiscV::setGpioPadState(const TargetPadDescriptor& padDescriptor, const TargetGpioPadState& state) { + const auto gpioPadDescriptorIt = this->gpioPadDescriptorsByPadId.find(padDescriptor.id); + if (gpioPadDescriptorIt == this->gpioPadDescriptorsByPadId.end()) { + throw Exceptions::Exception{"Unknown pad"}; + } + + const auto& gpioPadDescriptor = gpioPadDescriptorIt->second; + + auto configRegisterValue = this->readRegisterDynamicValue(gpioPadDescriptor.configRegisterDescriptor); + const auto currentDir = configRegisterValue.bitField( + gpioPadDescriptor.modeBitFieldDescriptor + ) == static_cast(GpioPadDirection::INPUT) + ? TargetGpioPadState::DataDirection::INPUT + : TargetGpioPadState::DataDirection::OUTPUT; + + if (currentDir != state.direction) { + configRegisterValue.setBitField( + gpioPadDescriptor.modeBitFieldDescriptor, + static_cast( + state.direction == TargetGpioPadState::DataDirection::INPUT + ? GpioPadDirection::INPUT + : GpioPadDirection::OUTPUT + ) + ); + + this->writeRegister(gpioPadDescriptor.configRegisterDescriptor, configRegisterValue.data()); + } + + if (state.direction == TargetGpioPadState::DataDirection::OUTPUT) { + auto outDataRegisterValue = this->readRegisterDynamicValue(gpioPadDescriptor.outputDataRegisterDescriptor); + outDataRegisterValue.setBitField( + gpioPadDescriptor.outputDataBitFieldDescriptor, + state.value == TargetGpioPadState::State::HIGH + ? 0x01 + : 0x00 + ); + this->writeRegister(gpioPadDescriptor.outputDataRegisterDescriptor, outDataRegisterValue.data()); + } + } + std::string WchRiscV::passthroughCommandHelpText() { using Services::StringService; @@ -574,4 +693,170 @@ namespace Targets::RiscV::Wch this->reset(); } + + std::map WchRiscV::generateGpioPadDescriptorMapping( + const TargetRegisterDescriptor& portPeripheralClockEnableRegisterDescriptor, + const std::vector& portPeripheralDescriptors, + const std::vector& padDescriptors + ) { + static const auto findConfigBitField = [] ( + const TargetPadDescriptor& padDescriptor, + const TargetRegisterDescriptor& configRegisterDescriptor + ) -> std::optional> { + return padDescriptor.key.size() >= 3 + ? configRegisterDescriptor.tryGetBitFieldDescriptor("cnf" + padDescriptor.key.substr(2)) + : std::nullopt; + }; + + static const auto findModeBitField = [] ( + const TargetPadDescriptor& padDescriptor, + const TargetRegisterDescriptor& configRegisterDescriptor + ) -> std::optional> { + return padDescriptor.key.size() >= 3 + ? configRegisterDescriptor.tryGetBitFieldDescriptor("mode" + padDescriptor.key.substr(2)) + : std::nullopt; + }; + + static const auto findInputDataBitField = [] ( + const TargetPadDescriptor& padDescriptor, + const TargetRegisterDescriptor& inputDataRegisterDescriptor + ) -> std::optional> { + return padDescriptor.key.size() >= 3 + ? inputDataRegisterDescriptor.tryGetBitFieldDescriptor("indr" + padDescriptor.key.substr(2)) + : std::nullopt; + }; + + static const auto findOutputDataBitField = [] ( + const TargetPadDescriptor& padDescriptor, + const TargetRegisterDescriptor& outputDataRegisterDescriptor + ) -> std::optional> { + return padDescriptor.key.size() >= 3 + ? outputDataRegisterDescriptor.tryGetBitFieldDescriptor("odr" + padDescriptor.key.substr(2)) + : std::nullopt; + }; + + auto output = std::map{}; + + for (const auto& padDesc : padDescriptors) { + if (padDesc.type != TargetPadType::GPIO) { + continue; + } + + for (const auto& peripheralDesc : portPeripheralDescriptors) { + if ( + !peripheralDesc.tryGetFirstSignalDescriptor(padDesc.key).has_value() + || peripheralDesc.key.size() < 5 + || peripheralDesc.key.find("port") != 0 + ) { + continue; + } + + const auto portLetter = peripheralDesc.key.substr(4, 1); + const auto peripheralClockEnableBitFieldDescOpt = portPeripheralClockEnableRegisterDescriptor.tryGetBitFieldDescriptor( + "iop" + portLetter + "en" + ); + + if (!peripheralClockEnableBitFieldDescOpt.has_value()) { + continue; + } + + auto configRegisterDescOpt = std::optional>{}; + auto configBitFieldDescOpt = std::optional>{}; + auto modeBitFieldDescOpt = std::optional>{}; + + const auto portGroupDescOpt = peripheralDesc.tryGetRegisterGroupDescriptor("port"); + if (!portGroupDescOpt.has_value()) { + continue; + } + + const auto& portGroupDescriptor = portGroupDescOpt->get(); + + const auto configLowRegisterDescOpt = portGroupDescriptor.tryGetRegisterDescriptor("cfglr"); + const auto configHighRegisterDescOpt = portGroupDescriptor.tryGetRegisterDescriptor("cfghr"); + const auto configExtendedRegisterDescOpt = portGroupDescriptor.tryGetRegisterDescriptor("cfgxr"); + + if (configLowRegisterDescOpt.has_value()) { + const auto& configLowRegisterDescriptor = configLowRegisterDescOpt->get(); + + configBitFieldDescOpt = findConfigBitField(padDesc, configLowRegisterDescriptor); + modeBitFieldDescOpt = findModeBitField(padDesc, configLowRegisterDescriptor); + + if (configBitFieldDescOpt.has_value()) { + configRegisterDescOpt = configLowRegisterDescOpt; + } + } + + if ( + (!configBitFieldDescOpt.has_value() || !modeBitFieldDescOpt.has_value()) + && configHighRegisterDescOpt.has_value() + ) { + const auto& configHighRegisterDescriptor = configHighRegisterDescOpt->get(); + + configBitFieldDescOpt = findConfigBitField(padDesc, configHighRegisterDescriptor); + modeBitFieldDescOpt = findModeBitField(padDesc, configHighRegisterDescriptor); + + if (configBitFieldDescOpt.has_value()) { + configRegisterDescOpt = configHighRegisterDescOpt; + } + } + + if ( + (!configBitFieldDescOpt.has_value() || !modeBitFieldDescOpt.has_value()) + && configExtendedRegisterDescOpt.has_value() + ) { + const auto& configExtendedRegisterDescriptor = configExtendedRegisterDescOpt->get(); + + configBitFieldDescOpt = findConfigBitField(padDesc, configExtendedRegisterDescriptor); + modeBitFieldDescOpt = findModeBitField(padDesc, configExtendedRegisterDescriptor); + + if (configBitFieldDescOpt.has_value()) { + configRegisterDescOpt = configExtendedRegisterDescOpt; + } + } + + if ( + !configRegisterDescOpt.has_value() + || !configBitFieldDescOpt.has_value() + || !modeBitFieldDescOpt.has_value() + ) { + continue; + } + + const auto inputDataRegisterDescOpt = portGroupDescriptor.tryGetRegisterDescriptor("indr"); + const auto outputDataRegisterDescOpt = portGroupDescriptor.tryGetRegisterDescriptor("outdr"); + + if (!inputDataRegisterDescOpt.has_value() || !outputDataRegisterDescOpt.has_value()) { + continue; + } + + const auto& inputDataRegisterDescriptor = inputDataRegisterDescOpt->get(); + const auto& outputDataRegisterDescriptor = outputDataRegisterDescOpt->get(); + + const auto inputBitFieldDescOpt = findInputDataBitField(padDesc, inputDataRegisterDescriptor); + const auto outputBitFieldDescOpt = findOutputDataBitField(padDesc, outputDataRegisterDescriptor); + + if (!inputBitFieldDescOpt.has_value() || !outputBitFieldDescOpt.has_value()) { + continue; + } + + output.emplace( + padDesc.id, + GpioPadDescriptor{ + .peripheralClockEnableBitFieldDescriptor = peripheralClockEnableBitFieldDescOpt->get(), + .configRegisterDescriptor = configRegisterDescOpt->get(), + .configBitFieldDescriptor = configBitFieldDescOpt->get(), + .modeBitFieldDescriptor = modeBitFieldDescOpt->get(), + .inputDataRegisterDescriptor = inputDataRegisterDescriptor, + .inputDataBitFieldDescriptor = inputBitFieldDescOpt->get(), + .outputDataRegisterDescriptor = outputDataRegisterDescriptor, + .outputDataBitFieldDescriptor = outputBitFieldDescOpt->get(), + } + ); + + break; + } + } + + return output; + } } diff --git a/src/Targets/RiscV/Wch/WchRiscV.hpp b/src/Targets/RiscV/Wch/WchRiscV.hpp index f5f2e80d..a1868cf5 100644 --- a/src/Targets/RiscV/Wch/WchRiscV.hpp +++ b/src/Targets/RiscV/Wch/WchRiscV.hpp @@ -3,11 +3,16 @@ #include #include #include +#include +#include #include "src/Targets/RiscV/RiscV.hpp" +#include "src/Targets/TargetPeripheralDescriptor.hpp" +#include "src/Targets/TargetPadDescriptor.hpp" #include "WchRiscVTargetConfig.hpp" #include "TargetDescriptionFile.hpp" +#include "GpioPadDescriptor.hpp" namespace Targets::RiscV::Wch { @@ -43,6 +48,9 @@ namespace Targets::RiscV::Wch TargetMemoryAddress getProgramCounter() override; + TargetGpioPadDescriptorAndStatePairs getGpioPadStates(const TargetPadDescriptors& padDescriptors) override; + void setGpioPadState(const TargetPadDescriptor& padDescriptor, const TargetGpioPadState& state) override; + std::string passthroughCommandHelpText() override; std::optional invokePassthroughCommand(const PassthroughCommand& command) override; @@ -84,6 +92,13 @@ namespace Targets::RiscV::Wch const TargetBitFieldDescriptor& flashStatusBootLockFieldDescriptor; const TargetBitFieldDescriptor& flashStatusBootModeFieldDescriptor; + const TargetPeripheralDescriptor rccPeripheralDescriptor; + const TargetRegisterDescriptor& portPeripheralClockEnableRegisterDescriptor; + + std::vector padDescriptors; + std::vector gpioPortPeripheralDescriptors; + std::map gpioPadDescriptorsByPadId; + const TargetMemorySegmentDescriptor& resolveAliasedMemorySegment(); TargetMemoryAddress transformMappedAddress( TargetMemoryAddress address, @@ -94,5 +109,11 @@ namespace Targets::RiscV::Wch void unlockBootModeBitField(); void enableBootMode(); void enableUserMode(); + + static std::map generateGpioPadDescriptorMapping( + const TargetRegisterDescriptor& portPeripheralClockEnableRegisterDescriptor, + const std::vector& portPeripheralDescriptors, + const std::vector& padDescriptors + ); }; } diff --git a/src/Targets/TargetDescription/TargetDescriptionFile.cpp b/src/Targets/TargetDescription/TargetDescriptionFile.cpp index e25d2561..fba030ca 100644 --- a/src/Targets/TargetDescription/TargetDescriptionFile.cpp +++ b/src/Targets/TargetDescription/TargetDescriptionFile.cpp @@ -325,11 +325,11 @@ namespace Targets::TargetDescription std::map TargetDescriptionFile::targetPadDescriptorsByKey() const { auto output = std::map{}; - const auto gpioPadKeys = this->getGpioPadKeys(); + const auto gpioPeripheralSignalPadKeys = this->getGpioPeripheralSignalPadKeys(); for (const auto& [key, pad] : this->padsByKey) { output.emplace( key, - TargetDescriptionFile::targetPadDescriptorFromPad(pad, gpioPadKeys) + TargetDescriptionFile::targetPadDescriptorFromPad(pad, gpioPeripheralSignalPadKeys) ); } @@ -362,6 +362,17 @@ namespace Targets::TargetDescription return output; } + std::vector TargetDescriptionFile::targetPadDescriptors() const { + auto output = std::vector{}; + + const auto gpioPeripheralSignalPadKeys = this->getGpioPeripheralSignalPadKeys(); + for (const auto& [key, pad] : this->padsByKey) { + output.emplace_back(TargetDescriptionFile::targetPadDescriptorFromPad(pad, gpioPeripheralSignalPadKeys)); + } + + return output; + } + std::vector TargetDescriptionFile::gpioPortPeripheralDescriptors() const { auto output = std::vector{}; @@ -505,7 +516,7 @@ namespace Targets::TargetDescription return attribute->get(); } - std::set TargetDescriptionFile::getGpioPadKeys() const { + std::set TargetDescriptionFile::getGpioPeripheralSignalPadKeys() const { auto output = std::set{}; for (const auto* peripheral : this->getGpioPeripherals()) { for (const auto& signal : peripheral->sigs) { @@ -984,6 +995,7 @@ namespace Targets::TargetDescription memorySegment.executable, memorySegment.access, memorySegment.access, + false, memorySegment.pageSize }; } @@ -1153,10 +1165,10 @@ namespace Targets::TargetDescription TargetPadDescriptor TargetDescriptionFile::targetPadDescriptorFromPad( const Pad& pad, - const std::set& gpioPadKeys + const std::set& gpioPeripheralSignalPadKeys ) { - static const auto resolvePadType = [&gpioPadKeys] (const Pad& pad) -> TargetPadType { - if (gpioPadKeys.contains(pad.key)) { + const auto resolvePadType = [&gpioPeripheralSignalPadKeys] (const Pad& pad) -> TargetPadType { + if (gpioPeripheralSignalPadKeys.contains(pad.key)) { return TargetPadType::GPIO; } diff --git a/src/Targets/TargetDescription/TargetDescriptionFile.hpp b/src/Targets/TargetDescription/TargetDescriptionFile.hpp index 6f763154..40f0fae8 100644 --- a/src/Targets/TargetDescription/TargetDescriptionFile.hpp +++ b/src/Targets/TargetDescription/TargetDescriptionFile.hpp @@ -130,7 +130,6 @@ namespace Targets::TargetDescription [[nodiscard]] std::set getModulePeripherals(const std::string& moduleKey) const; [[nodiscard]] std::set getGpioPeripherals() const; - [[nodiscard]] std::optional tryGetTargetMemorySegmentDescriptor( std::string_view addressSpaceKey, std::string_view segmentKey @@ -150,6 +149,7 @@ namespace Targets::TargetDescription [[nodiscard]] std::map targetPadDescriptorsByKey() const; [[nodiscard]] std::map targetPinoutDescriptorsByKey() const; [[nodiscard]] std::map targetVariantDescriptorsByKey() const; + [[nodiscard]] std::vector targetPadDescriptors() const; [[nodiscard]] std::vector gpioPortPeripheralDescriptors() const; protected: @@ -180,7 +180,7 @@ namespace Targets::TargetDescription ) const; [[nodiscard]] const std::string& getDeviceAttribute(const std::string& attributeName) const; - [[nodiscard]] std::set getGpioPadKeys() const; + [[nodiscard]] std::set getGpioPeripheralSignalPadKeys() const; static std::optional tryGetAttribute(const QDomElement& element, const QString& attributeName); static std::string getAttribute(const QDomElement& element, const QString& attributeName); @@ -244,7 +244,7 @@ namespace Targets::TargetDescription static TargetPadDescriptor targetPadDescriptorFromPad( const Pad& pad, - const std::set& gpioPadKeys + const std::set& gpioPeripheralSignalPadKeys ); static TargetPinoutDescriptor targetPinoutDescriptorFromPinout(const Pinout& pinout); diff --git a/src/Targets/TargetPeripheralDescriptor.cpp b/src/Targets/TargetPeripheralDescriptor.cpp index 557bb3bd..d6ae7a12 100644 --- a/src/Targets/TargetPeripheralDescriptor.cpp +++ b/src/Targets/TargetPeripheralDescriptor.cpp @@ -66,6 +66,18 @@ namespace Targets return this->getRegisterGroupDescriptor(groupKey).getRegisterDescriptor(registerKey); } + std::optional< + std::reference_wrapper + > TargetPeripheralDescriptor::tryGetFirstSignalDescriptor(std::string_view padKey) const { + for (const auto& signalDescriptor : this->signalDescriptors) { + if (signalDescriptor.padKey == padKey) { + return std::cref(signalDescriptor); + } + } + + return std::nullopt; + } + TargetPeripheralDescriptor TargetPeripheralDescriptor::clone() const { auto output = TargetPeripheralDescriptor{ this->key, diff --git a/src/Targets/TargetPeripheralDescriptor.hpp b/src/Targets/TargetPeripheralDescriptor.hpp index a98b5759..97afbb67 100644 --- a/src/Targets/TargetPeripheralDescriptor.hpp +++ b/src/Targets/TargetPeripheralDescriptor.hpp @@ -53,6 +53,10 @@ namespace Targets const std::string& registerKey ) const; + [[nodiscard]] std::optional< + std::reference_wrapper + > tryGetFirstSignalDescriptor(std::string_view padKey) const; + [[nodiscard]] TargetPeripheralDescriptor clone() const; }; }