diff --git a/CMakeLists.txt b/CMakeLists.txt index cf3f7415..f0cbf341 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ add_executable(Bloom src/Application.cpp src/DebugToolDrivers/USB/UsbDevice.cpp src/TargetController/TargetController.cpp + src/TargetController/TargetControllerConsole.cpp src/EventManager/EventListener.cpp src/EventManager/EventManager.cpp src/DebugServers/DebugServer.cpp diff --git a/src/DebugServers/DebugServer.cpp b/src/DebugServers/DebugServer.cpp index c0cb7d2e..e4744cdc 100644 --- a/src/DebugServers/DebugServer.cpp +++ b/src/DebugServers/DebugServer.cpp @@ -57,177 +57,4 @@ void DebugServer::shutdown() { void DebugServer::onShutdownDebugServerEvent(EventPointer event) { this->shutdown(); -} - -void DebugServer::stopTargetExecution() { - auto stopTargetEvent = std::make_shared(); - this->eventManager.triggerEvent(stopTargetEvent); - - auto responseEvent = this->eventListener->waitForEvent< - Events::TargetExecutionStopped, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), stopTargetEvent->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } -} - -void DebugServer::continueTargetExecution(std::optional fromAddress) { - auto resumeExecutionEvent = std::make_shared(); - - if (fromAddress.has_value()) { - resumeExecutionEvent->fromProgramCounter = fromAddress.value(); - } - - this->eventManager.triggerEvent(resumeExecutionEvent); - auto responseEvent = this->eventListener->waitForEvent< - Events::TargetExecutionResumed, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), resumeExecutionEvent->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } -} - -void DebugServer::stepTargetExecution(std::optional fromAddress) { - auto stepExecutionEvent = std::make_shared(); - - if (fromAddress.has_value()) { - stepExecutionEvent->fromProgramCounter = fromAddress.value(); - } - - this->eventManager.triggerEvent(stepExecutionEvent); - auto responseEvent = this->eventListener->waitForEvent< - Events::TargetExecutionResumed, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), stepExecutionEvent->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } -} - -TargetRegisters DebugServer::readGeneralRegistersFromTarget(TargetRegisterDescriptors descriptors) { - auto readRegistersEvent = std::make_shared(); - readRegistersEvent->descriptors = descriptors; - - this->eventManager.triggerEvent(readRegistersEvent); - auto responseEvent = this->eventListener->waitForEvent< - Events::RegistersRetrievedFromTarget, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), readRegistersEvent->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } - - auto retrievedRegistersEvent = std::get>(responseEvent.value()); - return retrievedRegistersEvent->registers; -} - -void DebugServer::writeGeneralRegistersToTarget(TargetRegisters registers) { - auto event = std::make_shared(); - event->registers = registers; - - this->eventManager.triggerEvent(event); - auto responseEvent = this->eventListener->waitForEvent< - Events::RegistersWrittenToTarget, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), event->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } -} - -TargetMemoryBuffer DebugServer::readMemoryFromTarget(TargetMemoryType memoryType, std::uint32_t startAddress, std::uint32_t bytes) { - auto readMemoryEvent = std::make_shared(); - readMemoryEvent->memoryType = memoryType; - readMemoryEvent->startAddress = startAddress; - readMemoryEvent->bytes = bytes; - - this->eventManager.triggerEvent(readMemoryEvent); - auto responseEvent = this->eventListener->waitForEvent< - Events::MemoryRetrievedFromTarget, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), readMemoryEvent->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } - - auto retrievedRegistersEvent = std::get>(responseEvent.value()); - return retrievedRegistersEvent->data; -} - -void DebugServer::writeMemoryToTarget( - TargetMemoryType memoryType, - std::uint32_t startAddress, - const TargetMemoryBuffer& buffer -) { - auto writeMemoryEvent = std::make_shared(); - writeMemoryEvent->memoryType = memoryType; - writeMemoryEvent->startAddress = startAddress; - writeMemoryEvent->buffer = buffer; - - this->eventManager.triggerEvent(writeMemoryEvent); - auto responseEvent = this->eventListener->waitForEvent< - Events::MemoryWrittenToTarget, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), writeMemoryEvent->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } -} - -void DebugServer::setBreakpointOnTarget(TargetBreakpoint breakpoint) { - auto event = std::make_shared(); - event->breakpoint = breakpoint; - - this->eventManager.triggerEvent(event); - auto responseEvent = this->eventListener->waitForEvent< - Events::BreakpointSetOnTarget, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), event->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } -} - -void DebugServer::removeBreakpointOnTarget(TargetBreakpoint breakpoint) { - auto event = std::make_shared(); - event->breakpoint = breakpoint; - - this->eventManager.triggerEvent(event); - auto responseEvent = this->eventListener->waitForEvent< - Events::BreakpointRemovedOnTarget, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), event->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } -} - +} \ No newline at end of file diff --git a/src/DebugServers/DebugServer.hpp b/src/DebugServers/DebugServer.hpp index f2bfbbd0..d70ecfb6 100644 --- a/src/DebugServers/DebugServer.hpp +++ b/src/DebugServers/DebugServer.hpp @@ -4,6 +4,7 @@ #include #include +#include "src/TargetController/TargetControllerConsole.hpp" #include "src/EventManager/Events/Events.hpp" #include "src/EventManager/EventManager.hpp" #include "src/Exceptions/DebugServerInterrupted.hpp" @@ -75,6 +76,11 @@ namespace Bloom::DebugServers EventManager& eventManager; EventListenerPointer eventListener = std::make_shared("DebugServerEventListener"); + TargetControllerConsole targetControllerConsole = TargetControllerConsole( + this->eventManager, + *(this->eventListener) + ); + /** * Enables the interruption of any blocking file IO. */ @@ -99,75 +105,6 @@ namespace Bloom::DebugServers */ virtual void close() = 0; - /** - * Requests the TargetController to halt execution on the target. - */ - void stopTargetExecution(); - - /** - * Requests the TargetController to continue execution on the target. - * - * @param fromAddress - */ - void continueTargetExecution(std::optional fromAddress); - - /** - * Requests the TargetController to step execution on the target. - * - * @param fromAddress - */ - void stepTargetExecution(std::optional fromAddress); - - /** - * Requests the TargetController to read register values from the target. - * - * @param descriptors - * Descriptors of the registers to read. - * - * @return - */ - TargetRegisters readGeneralRegistersFromTarget(TargetRegisterDescriptors descriptors); - - /** - * Requests the TargetController to write register values to the target. - * - * @param registers - */ - void writeGeneralRegistersToTarget(TargetRegisters registers); - - /** - * Requests the TargetController to read memory from the target. - * - * @param memoryType - * @param startAddress - * @param bytes - * @return - */ - TargetMemoryBuffer readMemoryFromTarget(TargetMemoryType memoryType, std::uint32_t startAddress, std::uint32_t bytes); - - /** - * Requests the TargetController to write memory to the target. - * - * @param memoryType - * @param startAddress - * @param buffer - */ - void writeMemoryToTarget(TargetMemoryType memoryType, std::uint32_t startAddress, const TargetMemoryBuffer& buffer); - - /** - * Requests the TargetController to set a breakpoint on the target. - * - * @param breakpoint - */ - void setBreakpointOnTarget(TargetBreakpoint breakpoint); - - /** - * Requests the TargetController to remove a breakpoint from the target. - * - * @param breakpoint - */ - void removeBreakpointOnTarget(TargetBreakpoint breakpoint); - public: DebugServer(EventManager& eventManager): eventManager(eventManager) {}; diff --git a/src/DebugServers/GdbRsp/GdbRspDebugServer.cpp b/src/DebugServers/GdbRsp/GdbRspDebugServer.cpp index e0d5e155..44cbd7c1 100644 --- a/src/DebugServers/GdbRsp/GdbRspDebugServer.cpp +++ b/src/DebugServers/GdbRsp/GdbRspDebugServer.cpp @@ -238,7 +238,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadGeneralRegisters& pa } } - auto registerSet = this->readGeneralRegistersFromTarget(descriptors); + auto registerSet = this->targetControllerConsole.readGeneralRegisters(descriptors); auto registerNumberToDescriptorMapping = this->getRegisterNumberToDescriptorMapping(); /* @@ -297,7 +297,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteGeneralRegisters& p try { auto registerDescriptor = this->getRegisterDescriptorFromNumber(packet.registerNumber); - this->writeGeneralRegistersToTarget({TargetRegister(registerDescriptor, packet.registerValue)}); + this->targetControllerConsole.writeGeneralRegisters({ + TargetRegister(registerDescriptor, packet.registerValue) + }); this->clientConnection->writePacket(ResponsePacket({'O', 'K'})); } catch (const Exception& exception) { @@ -310,7 +312,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ContinueExecution& packe Logger::debug("Handling ContinueExecution packet"); try { - this->continueTargetExecution(packet.fromProgramCounter); + this->targetControllerConsole.continueTargetExecution(packet.fromProgramCounter); this->clientConnection->waitingForBreak = true; } catch (const Exception& exception) { @@ -323,7 +325,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::StepExecution& packet) { Logger::debug("Handling StepExecution packet"); try { - this->stepTargetExecution(packet.fromProgramCounter); + this->targetControllerConsole.stepTargetExecution(packet.fromProgramCounter); this->clientConnection->waitingForBreak = true; } catch (const Exception& exception) { @@ -338,7 +340,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadMemory& packet) { try { auto memoryType = this->getMemoryTypeFromGdbAddress(packet.startAddress); auto startAddress = this->removeMemoryTypeIndicatorFromGdbAddress(packet.startAddress); - auto memoryBuffer = this->readMemoryFromTarget(memoryType, startAddress, packet.bytes); + auto memoryBuffer = this->targetControllerConsole.readMemory(memoryType, startAddress, packet.bytes); auto hexMemoryBuffer = Packet::dataToHex(memoryBuffer); this->clientConnection->writePacket( @@ -357,7 +359,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteMemory& packet) { try { auto memoryType = this->getMemoryTypeFromGdbAddress(packet.startAddress); auto startAddress = this->removeMemoryTypeIndicatorFromGdbAddress(packet.startAddress); - this->writeMemoryToTarget(memoryType, startAddress, packet.buffer); + this->targetControllerConsole.writeMemory(memoryType, startAddress, packet.buffer); this->clientConnection->writePacket(ResponsePacket({'O', 'K'})); @@ -373,7 +375,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::SetBreakpoint& packet) { try { auto breakpoint = TargetBreakpoint(); breakpoint.address = packet.address; - this->setBreakpointOnTarget(breakpoint); + this->targetControllerConsole.setBreakpoint(breakpoint); this->clientConnection->writePacket(ResponsePacket({'O', 'K'})); @@ -389,7 +391,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::RemoveBreakpoint& packet try { auto breakpoint = TargetBreakpoint(); breakpoint.address = packet.address; - this->removeBreakpointOnTarget(breakpoint); + this->targetControllerConsole.removeBreakpoint(breakpoint); this->clientConnection->writePacket(ResponsePacket({'O', 'K'})); @@ -403,7 +405,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::InterruptExecution& pack Logger::debug("Handling InterruptExecution packet"); try { - this->stopTargetExecution(); + this->targetControllerConsole.stopTargetExecution(); this->clientConnection->writePacket(TargetStopped(Signal::INTERRUPTED)); } catch (const Exception& exception) { diff --git a/src/Insight/Insight.cpp b/src/Insight/Insight.cpp index 6a020917..120dc856 100644 --- a/src/Insight/Insight.cpp +++ b/src/Insight/Insight.cpp @@ -46,7 +46,7 @@ void Insight::startup() { std::bind(&Insight::onTargetControllerStateChangedEvent, this, std::placeholders::_1) ); - auto targetDescriptor = this->getTargetDescriptor(); + auto targetDescriptor = this->targetControllerConsole.getTargetDescriptor(); std::string qtAppName = "Bloom"; char* appArguments[] = {qtAppName.data()}; @@ -91,24 +91,6 @@ void Insight::startup() { connect(&(this->mainWindow), &InsightWindow::setTargetPinState, worker, &InsightWorker::requestPinStateUpdate); } -Targets::TargetDescriptor Insight::getTargetDescriptor() { - auto extractEvent = std::make_shared(); - this->eventManager.triggerEvent(extractEvent); - auto responseEvent = this->eventListener->waitForEvent< - Events::TargetDescriptorExtracted, - Events::TargetControllerErrorOccurred - >(std::chrono::milliseconds(5000), extractEvent->id); - - if (!responseEvent.has_value() - || !std::holds_alternative>(responseEvent.value()) - ) { - throw Exception("Unexpected response from TargetController"); - } - - auto descriptorExtracted = std::get>(responseEvent.value()); - return descriptorExtracted->targetDescriptor; -} - void Insight::shutdown() { if (this->getState() == ThreadState::STOPPED) { return; diff --git a/src/Insight/Insight.hpp b/src/Insight/Insight.hpp index 8f8793c7..926953e9 100644 --- a/src/Insight/Insight.hpp +++ b/src/Insight/Insight.hpp @@ -2,13 +2,13 @@ #include #include - #include "UserInterfaces/InsightWindow/InsightWindow.hpp" + #include "src/Helpers/Thread.hpp" #include "src/ApplicationConfig.hpp" #include "src/EventManager/EventManager.hpp" #include "src/EventManager/EventListener.hpp" -#include "src/Targets/TargetDescriptor.hpp" +#include "src/TargetController/TargetControllerConsole.hpp" namespace Bloom { @@ -34,6 +34,11 @@ namespace Bloom QApplication* application = nullptr; InsightWindow mainWindow; + TargetControllerConsole targetControllerConsole = TargetControllerConsole( + this->eventManager, + *(this->eventListener) + ); + /** * Insight consists of two threads - the main thread where the main Qt event loop runs (for the GUI), and * a single worker thread to handle any blocking/time-expensive operations. @@ -42,8 +47,6 @@ namespace Bloom void startup(); - Targets::TargetDescriptor getTargetDescriptor(); - public: Insight(EventManager& eventManager): eventManager(eventManager) {}; diff --git a/src/Insight/InsightWorker.cpp b/src/Insight/InsightWorker.cpp index 1377c388..77a0d5ef 100644 --- a/src/Insight/InsightWorker.cpp +++ b/src/Insight/InsightWorker.cpp @@ -43,10 +43,7 @@ void InsightWorker::startup() { } void InsightWorker::requestPinStates(int variantId) { - auto requestEvent = std::make_shared(); - requestEvent->variantId = variantId; - - this->eventManager.triggerEvent(requestEvent); + this->targetControllerConsole.requestPinStates(variantId); } void InsightWorker::requestPinStateUpdate( @@ -54,12 +51,7 @@ void InsightWorker::requestPinStateUpdate( Bloom::Targets::TargetPinDescriptor pinDescriptor, Bloom::Targets::TargetPinState pinState ) { - auto updateEvent = std::make_shared(); - updateEvent->variantId = variantId; - updateEvent->pinDescriptor = pinDescriptor; - updateEvent->pinState = pinState; - - this->eventManager.triggerEvent(updateEvent); + this->targetControllerConsole.setPinState(variantId, pinDescriptor, pinState); } void InsightWorker::onTargetStoppedEvent(EventPointer event) { diff --git a/src/Insight/InsightWorker.hpp b/src/Insight/InsightWorker.hpp index 3ffa5998..1677a4d3 100644 --- a/src/Insight/InsightWorker.hpp +++ b/src/Insight/InsightWorker.hpp @@ -8,6 +8,7 @@ #include "src/ApplicationConfig.hpp" #include "src/EventManager/EventManager.hpp" #include "src/EventManager/EventListener.hpp" +#include "src/TargetController/TargetControllerConsole.hpp" namespace Bloom { @@ -25,6 +26,11 @@ namespace Bloom EventManager& eventManager; EventListenerPointer eventListener = std::make_shared("InsightWorkerEventListener"); + TargetControllerConsole targetControllerConsole = TargetControllerConsole( + this->eventManager, + *(this->eventListener) + ); + QTimer* eventDispatchTimer = nullptr; void onTargetStoppedEvent(EventPointer event); diff --git a/src/TargetController/TargetControllerConsole.cpp b/src/TargetController/TargetControllerConsole.cpp new file mode 100644 index 00000000..ddd52ec9 --- /dev/null +++ b/src/TargetController/TargetControllerConsole.cpp @@ -0,0 +1,217 @@ +#include + +#include "TargetControllerConsole.hpp" +#include "src/EventManager/Events/Events.hpp" +#include "src/Logger/Logger.hpp" + +using namespace Bloom; + +Targets::TargetDescriptor TargetControllerConsole::getTargetDescriptor() { + auto extractEvent = std::make_shared(); + this->eventManager.triggerEvent(extractEvent); + auto responseEvent = this->eventListener.waitForEvent< + Events::TargetDescriptorExtracted, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), extractEvent->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } + + auto descriptorExtracted = std::get>(responseEvent.value()); + return descriptorExtracted->targetDescriptor; +} + +void TargetControllerConsole::stopTargetExecution() { + auto stopTargetEvent = std::make_shared(); + this->eventManager.triggerEvent(stopTargetEvent); + + auto responseEvent = this->eventListener.waitForEvent< + Events::TargetExecutionStopped, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), stopTargetEvent->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } +} + +void TargetControllerConsole::continueTargetExecution(std::optional fromAddress) { + auto resumeExecutionEvent = std::make_shared(); + + if (fromAddress.has_value()) { + resumeExecutionEvent->fromProgramCounter = fromAddress.value(); + } + + this->eventManager.triggerEvent(resumeExecutionEvent); + auto responseEvent = this->eventListener.waitForEvent< + Events::TargetExecutionResumed, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), resumeExecutionEvent->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } +} + +void TargetControllerConsole::stepTargetExecution(std::optional fromAddress) { + auto stepExecutionEvent = std::make_shared(); + + if (fromAddress.has_value()) { + stepExecutionEvent->fromProgramCounter = fromAddress.value(); + } + + this->eventManager.triggerEvent(stepExecutionEvent); + auto responseEvent = this->eventListener.waitForEvent< + Events::TargetExecutionResumed, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), stepExecutionEvent->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } +} + +TargetRegisters TargetControllerConsole::readGeneralRegisters(TargetRegisterDescriptors descriptors) { + auto readRegistersEvent = std::make_shared(); + readRegistersEvent->descriptors = descriptors; + + this->eventManager.triggerEvent(readRegistersEvent); + auto responseEvent = this->eventListener.waitForEvent< + Events::RegistersRetrievedFromTarget, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), readRegistersEvent->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } + + auto retrievedRegistersEvent = std::get>(responseEvent.value()); + return retrievedRegistersEvent->registers; +} + +void TargetControllerConsole::writeGeneralRegisters(TargetRegisters registers) { + auto event = std::make_shared(); + event->registers = registers; + + this->eventManager.triggerEvent(event); + auto responseEvent = this->eventListener.waitForEvent< + Events::RegistersWrittenToTarget, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), event->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } +} + +TargetMemoryBuffer TargetControllerConsole::readMemory( + TargetMemoryType memoryType, + std::uint32_t startAddress, + std::uint32_t bytes +) { + auto readMemoryEvent = std::make_shared(); + readMemoryEvent->memoryType = memoryType; + readMemoryEvent->startAddress = startAddress; + readMemoryEvent->bytes = bytes; + + this->eventManager.triggerEvent(readMemoryEvent); + auto responseEvent = this->eventListener.waitForEvent< + Events::MemoryRetrievedFromTarget, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), readMemoryEvent->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } + + auto retrievedRegistersEvent = std::get>(responseEvent.value()); + return retrievedRegistersEvent->data; +} + +void TargetControllerConsole::writeMemory( + TargetMemoryType memoryType, + std::uint32_t startAddress, + const TargetMemoryBuffer& buffer +) { + auto writeMemoryEvent = std::make_shared(); + writeMemoryEvent->memoryType = memoryType; + writeMemoryEvent->startAddress = startAddress; + writeMemoryEvent->buffer = buffer; + + this->eventManager.triggerEvent(writeMemoryEvent); + auto responseEvent = this->eventListener.waitForEvent< + Events::MemoryWrittenToTarget, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), writeMemoryEvent->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } +} + +void TargetControllerConsole::setBreakpoint(TargetBreakpoint breakpoint) { + auto event = std::make_shared(); + event->breakpoint = breakpoint; + + this->eventManager.triggerEvent(event); + auto responseEvent = this->eventListener.waitForEvent< + Events::BreakpointSetOnTarget, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), event->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } +} + +void TargetControllerConsole::removeBreakpoint(TargetBreakpoint breakpoint) { + auto event = std::make_shared(); + event->breakpoint = breakpoint; + + this->eventManager.triggerEvent(event); + auto responseEvent = this->eventListener.waitForEvent< + Events::BreakpointRemovedOnTarget, + Events::TargetControllerErrorOccurred + >(std::chrono::milliseconds(5000), event->id); + + if (!responseEvent.has_value() + || !std::holds_alternative>(responseEvent.value()) + ) { + throw Exception("Unexpected response from TargetController"); + } +} + +void TargetControllerConsole::requestPinStates(int variantId) { + auto requestEvent = std::make_shared(); + requestEvent->variantId = variantId; + + this->eventManager.triggerEvent(requestEvent); +} + +void TargetControllerConsole::setPinState(int variantId, TargetPinDescriptor pinDescriptor, TargetPinState pinState) { + auto updateEvent = std::make_shared(); + updateEvent->variantId = variantId; + updateEvent->pinDescriptor = pinDescriptor; + updateEvent->pinState = pinState; + + this->eventManager.triggerEvent(updateEvent); +} \ No newline at end of file diff --git a/src/TargetController/TargetControllerConsole.hpp b/src/TargetController/TargetControllerConsole.hpp new file mode 100644 index 00000000..3ee2ec0c --- /dev/null +++ b/src/TargetController/TargetControllerConsole.hpp @@ -0,0 +1,126 @@ +#pragma once + +#include +#include + +#include "src/EventManager/EventListener.hpp" +#include "src/EventManager/EventManager.hpp" + +#include "src/Targets/TargetRegister.hpp" +#include "src/Targets/TargetMemory.hpp" +#include "src/Targets/TargetBreakpoint.hpp" +#include "src/Targets/TargetVariant.hpp" +#include "src/Targets/TargetState.hpp" +#include "src/Targets/TargetPinDescriptor.hpp" + +namespace Bloom +{ + using namespace Targets; + + /** + * The TargetControllerConsole provides an interface to the TargetController, for components within Bloom that + * require access to common functionality from the TargetController. + */ + class TargetControllerConsole + { + private: + EventManager& eventManager; + EventListener& eventListener; + + public: + TargetControllerConsole(EventManager& eventManager, EventListener& eventListener): + eventManager(eventManager), eventListener(eventListener) {}; + + /** + * Requests the TargetDescriptor from the TargetController + * + * @return + */ + TargetDescriptor getTargetDescriptor(); + + /** + * Requests the TargetController to halt execution on the target. + */ + void stopTargetExecution(); + + /** + * Requests the TargetController to continue execution on the target. + * + * @param fromAddress + */ + void continueTargetExecution(std::optional fromAddress); + + /** + * Requests the TargetController to step execution on the target. + * + * @param fromAddress + */ + void stepTargetExecution(std::optional fromAddress); + + /** + * Requests the TargetController to read register values from the target. + * + * @param descriptors + * Descriptors of the registers to read. + * + * @return + */ + TargetRegisters readGeneralRegisters(TargetRegisterDescriptors descriptors); + + /** + * Requests the TargetController to write register values to the target. + * + * @param registers + */ + void writeGeneralRegisters(TargetRegisters registers); + + /** + * Requests the TargetController to read memory from the target. + * + * @param memoryType + * @param startAddress + * @param bytes + * @return + */ + TargetMemoryBuffer readMemory(TargetMemoryType memoryType, std::uint32_t startAddress, std::uint32_t bytes); + + /** + * Requests the TargetController to write memory to the target. + * + * @param memoryType + * @param startAddress + * @param buffer + */ + void writeMemory(TargetMemoryType memoryType, std::uint32_t startAddress, const TargetMemoryBuffer& buffer); + + /** + * Requests the TargetController to set a breakpoint on the target. + * + * @param breakpoint + */ + void setBreakpoint(TargetBreakpoint breakpoint); + + /** + * Requests the TargetController to remove a breakpoint from the target. + * + * @param breakpoint + */ + void removeBreakpoint(TargetBreakpoint breakpoint); + + /** + * Requests a pin state update on the target, for a specific pin. + * + * @param variantId + * @param pinDescriptor + * @param pinState + */ + void setPinState(int variantId, TargetPinDescriptor pinDescriptor, TargetPinState pinState); + + /** + * Requests a pin state refresh from the TargetController, for a specific target variant. + * + * @param variantId + */ + void requestPinStates(int variantId); + }; +}