From cfe533e5db2e3c4e0965062b6bf9db5c495a1e0d Mon Sep 17 00:00:00 2001 From: Nav Date: Sun, 5 Jun 2022 16:13:43 +0100 Subject: [PATCH] Introduced concept of programming mode --- src/TargetController/Commands/Command.hpp | 4 ++ .../Commands/CommandTypes.hpp | 2 + .../Commands/DisableProgrammingMode.hpp | 27 ++++++++++ .../Commands/EnableProgrammingMode.hpp | 27 ++++++++++ .../Commands/GetTargetDescriptor.hpp | 4 ++ .../Commands/ReadTargetMemory.hpp | 4 ++ .../Commands/WriteTargetMemory.hpp | 4 ++ .../TargetControllerComponent.cpp | 53 +++++++++++++++++++ .../TargetControllerComponent.hpp | 15 ++++++ .../TargetControllerConsole.cpp | 18 +++++++ .../TargetControllerConsole.hpp | 14 +++++ 11 files changed, 172 insertions(+) create mode 100644 src/TargetController/Commands/DisableProgrammingMode.hpp create mode 100644 src/TargetController/Commands/EnableProgrammingMode.hpp diff --git a/src/TargetController/Commands/Command.hpp b/src/TargetController/Commands/Command.hpp index b4ced02c..bf5beedc 100644 --- a/src/TargetController/Commands/Command.hpp +++ b/src/TargetController/Commands/Command.hpp @@ -40,6 +40,10 @@ namespace Bloom::TargetController::Commands return false; } + [[nodiscard]] virtual bool requiresDebugMode() const { + return true; + } + private: static inline std::atomic lastCommandId = 0; }; diff --git a/src/TargetController/Commands/CommandTypes.hpp b/src/TargetController/Commands/CommandTypes.hpp index 6fb7ad65..69b9f14f 100644 --- a/src/TargetController/Commands/CommandTypes.hpp +++ b/src/TargetController/Commands/CommandTypes.hpp @@ -24,5 +24,7 @@ namespace Bloom::TargetController::Commands SET_TARGET_PIN_STATE, GET_TARGET_STACK_POINTER, GET_TARGET_PROGRAM_COUNTER, + ENABLE_PROGRAMMING_MODE, + DISABLE_PROGRAMMING_MODE, }; } diff --git a/src/TargetController/Commands/DisableProgrammingMode.hpp b/src/TargetController/Commands/DisableProgrammingMode.hpp new file mode 100644 index 00000000..51dd4eae --- /dev/null +++ b/src/TargetController/Commands/DisableProgrammingMode.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "Command.hpp" + +namespace Bloom::TargetController::Commands +{ + class DisableProgrammingMode: public Command + { + public: + static constexpr CommandType type = CommandType::DISABLE_PROGRAMMING_MODE; + static inline const std::string name = "DisableProgrammingMode"; + + DisableProgrammingMode() = default; + + [[nodiscard]] CommandType getType() const override { + return DisableProgrammingMode::type; + } + + [[nodiscard]] bool requiresStoppedTargetState() const override { + return true; + } + + [[nodiscard]] bool requiresDebugMode() const override { + return false; + } + }; +} diff --git a/src/TargetController/Commands/EnableProgrammingMode.hpp b/src/TargetController/Commands/EnableProgrammingMode.hpp new file mode 100644 index 00000000..7584b530 --- /dev/null +++ b/src/TargetController/Commands/EnableProgrammingMode.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "Command.hpp" + +namespace Bloom::TargetController::Commands +{ + class EnableProgrammingMode: public Command + { + public: + static constexpr CommandType type = CommandType::ENABLE_PROGRAMMING_MODE; + static inline const std::string name = "EnableProgrammingMode"; + + EnableProgrammingMode() = default; + + [[nodiscard]] CommandType getType() const override { + return EnableProgrammingMode::type; + } + + [[nodiscard]] bool requiresStoppedTargetState() const override { + return true; + } + + [[nodiscard]] bool requiresDebugMode() const override { + return false; + } + }; +} diff --git a/src/TargetController/Commands/GetTargetDescriptor.hpp b/src/TargetController/Commands/GetTargetDescriptor.hpp index 411a54c2..d31a134d 100644 --- a/src/TargetController/Commands/GetTargetDescriptor.hpp +++ b/src/TargetController/Commands/GetTargetDescriptor.hpp @@ -17,5 +17,9 @@ namespace Bloom::TargetController::Commands [[nodiscard]] CommandType getType() const override { return GetTargetDescriptor::type; } + + [[nodiscard]] bool requiresDebugMode() const override { + return false; + } }; } diff --git a/src/TargetController/Commands/ReadTargetMemory.hpp b/src/TargetController/Commands/ReadTargetMemory.hpp index 76e276e4..1d9689a4 100644 --- a/src/TargetController/Commands/ReadTargetMemory.hpp +++ b/src/TargetController/Commands/ReadTargetMemory.hpp @@ -42,5 +42,9 @@ namespace Bloom::TargetController::Commands [[nodiscard]] bool requiresStoppedTargetState() const override { return true; } + + [[nodiscard]] bool requiresDebugMode() const override { + return this->memoryType == Targets::TargetMemoryType::RAM; + } }; } diff --git a/src/TargetController/Commands/WriteTargetMemory.hpp b/src/TargetController/Commands/WriteTargetMemory.hpp index b6b16ca8..f5737b04 100644 --- a/src/TargetController/Commands/WriteTargetMemory.hpp +++ b/src/TargetController/Commands/WriteTargetMemory.hpp @@ -34,5 +34,9 @@ namespace Bloom::TargetController::Commands [[nodiscard]] bool requiresStoppedTargetState() const override { return true; } + + [[nodiscard]] bool requiresDebugMode() const override { + return this->memoryType == Targets::TargetMemoryType::RAM; + } }; } diff --git a/src/TargetController/TargetControllerComponent.cpp b/src/TargetController/TargetControllerComponent.cpp index 9e9bab9b..aebd360e 100644 --- a/src/TargetController/TargetControllerComponent.cpp +++ b/src/TargetController/TargetControllerComponent.cpp @@ -40,6 +40,8 @@ namespace Bloom::TargetController using Commands::SetTargetPinState; using Commands::GetTargetStackPointer; using Commands::GetTargetProgramCounter; + using Commands::EnableProgrammingMode; + using Commands::DisableProgrammingMode; using Responses::Response; using Responses::TargetRegistersRead; @@ -311,6 +313,12 @@ namespace Bloom::TargetController throw Exception("Illegal target state - command requires target to be stopped"); } + if (this->target->programmingModeEnabled() && command->requiresDebugMode()) { + throw Exception( + "Illegal target state - command cannot be serviced whilst the target is in programming mode." + ); + } + this->registerCommandResponse( commandId, this->commandHandlersByCommandType.at(commandType)(*(command.get())) @@ -420,6 +428,8 @@ namespace Bloom::TargetController this->deregisterCommandHandler(SetTargetPinState::type); this->deregisterCommandHandler(GetTargetStackPointer::type); this->deregisterCommandHandler(GetTargetProgramCounter::type); + this->deregisterCommandHandler(EnableProgrammingMode::type); + this->deregisterCommandHandler(DisableProgrammingMode::type); this->eventListener->deregisterCallbacksForEventType(); @@ -506,6 +516,14 @@ namespace Bloom::TargetController std::bind(&TargetControllerComponent::handleGetTargetProgramCounter, this, std::placeholders::_1) ); + this->registerCommandHandler( + std::bind(&TargetControllerComponent::handleEnableProgrammingMode, this, std::placeholders::_1) + ); + + this->registerCommandHandler( + std::bind(&TargetControllerComponent::handleDisableProgrammingMode, this, std::placeholders::_1) + ); + this->eventListener->registerCallbackForEventType( std::bind(&TargetControllerComponent::onDebugSessionFinishedEvent, this, std::placeholders::_1) ); @@ -706,6 +724,18 @@ namespace Bloom::TargetController EventManager::triggerEvent(std::make_shared()); } + void TargetControllerComponent::enableProgrammingMode() { + this->target->enableProgrammingMode(); + + EventManager::triggerEvent(std::make_shared()); + } + + void TargetControllerComponent::disableProgrammingMode() { + this->target->disableProgrammingMode(); + + EventManager::triggerEvent(std::make_shared()); + } + Targets::TargetDescriptor& TargetControllerComponent::getTargetDescriptor() { if (!this->cachedTargetDescriptor.has_value()) { this->cachedTargetDescriptor = this->target->getDescriptor(); @@ -815,6 +845,12 @@ namespace Bloom::TargetController const auto bufferSize = command.buffer.size(); const auto bufferStartAddress = command.startAddress; + const auto& targetDescriptor = this->getTargetDescriptor(); + + if (command.memoryType == targetDescriptor.programMemoryType && !this->target->programmingModeEnabled()) { + throw Exception("Cannot write to program memory - programming mode not enabled."); + } + this->target->writeMemory(command.memoryType, bufferStartAddress, buffer); EventManager::triggerEvent( std::make_shared(command.memoryType, bufferStartAddress, bufferSize) @@ -822,6 +858,7 @@ namespace Bloom::TargetController if ( EventManager::isEventTypeListenedFor(Events::RegistersWrittenToTarget::type) + && command.memoryType == targetDescriptor.programMemoryType && this->registerDescriptorsByMemoryType.contains(command.memoryType) ) { /* @@ -908,4 +945,20 @@ namespace Bloom::TargetController ) { return std::make_unique(this->target->getProgramCounter()); } + + std::unique_ptr TargetControllerComponent::handleEnableProgrammingMode(EnableProgrammingMode& command) { + if (!this->target->programmingModeEnabled()) { + this->enableProgrammingMode(); + } + + return std::make_unique(); + } + + std::unique_ptr TargetControllerComponent::handleDisableProgrammingMode(DisableProgrammingMode& command) { + if (this->target->programmingModeEnabled()) { + this->disableProgrammingMode(); + } + + return std::make_unique(); + } } diff --git a/src/TargetController/TargetControllerComponent.hpp b/src/TargetController/TargetControllerComponent.hpp index 5b043eca..616be694 100644 --- a/src/TargetController/TargetControllerComponent.hpp +++ b/src/TargetController/TargetControllerComponent.hpp @@ -37,6 +37,8 @@ #include "Commands/SetTargetPinState.hpp" #include "Commands/GetTargetStackPointer.hpp" #include "Commands/GetTargetProgramCounter.hpp" +#include "Commands/EnableProgrammingMode.hpp" +#include "Commands/DisableProgrammingMode.hpp" // Responses #include "Responses/Response.hpp" @@ -292,6 +294,17 @@ namespace Bloom::TargetController */ void resetTarget(); + /** + * Puts the target into programming mode and disables command handlers for debug commands (commands that serve + * debug operations such as SetBreakpoint, ResumeTargetExecution, etc). + */ + void enableProgrammingMode(); + + /** + * Pulls the target out of programming mode and enables command handlers for debug commands. + */ + void disableProgrammingMode(); + /** * Returns a cached instance of the target's TargetDescriptor. * @@ -344,5 +357,7 @@ namespace Bloom::TargetController std::unique_ptr handleGetTargetProgramCounter( Commands::GetTargetProgramCounter& command ); + std::unique_ptr handleEnableProgrammingMode(Commands::EnableProgrammingMode& command); + std::unique_ptr handleDisableProgrammingMode(Commands::DisableProgrammingMode& command); }; } diff --git a/src/TargetController/TargetControllerConsole.cpp b/src/TargetController/TargetControllerConsole.cpp index 99c401f4..7fdb7a28 100644 --- a/src/TargetController/TargetControllerConsole.cpp +++ b/src/TargetController/TargetControllerConsole.cpp @@ -20,6 +20,8 @@ #include "Commands/SetTargetPinState.hpp" #include "Commands/GetTargetStackPointer.hpp" #include "Commands/GetTargetProgramCounter.hpp" +#include "Commands/EnableProgrammingMode.hpp" +#include "Commands/DisableProgrammingMode.hpp" namespace Bloom::TargetController { @@ -40,6 +42,8 @@ namespace Bloom::TargetController using Commands::SetTargetPinState; using Commands::GetTargetStackPointer; using Commands::GetTargetProgramCounter; + using Commands::EnableProgrammingMode; + using Commands::DisableProgrammingMode; using Targets::TargetDescriptor; using Targets::TargetState; @@ -214,4 +218,18 @@ namespace Bloom::TargetController this->defaultTimeout ); } + + void TargetControllerConsole::enableProgrammingMode() { + this->commandManager.sendCommandAndWaitForResponse( + std::make_unique(), + this->defaultTimeout + ); + } + + void TargetControllerConsole::disableProgrammingMode() { + this->commandManager.sendCommandAndWaitForResponse( + std::make_unique(), + this->defaultTimeout + ); + } } diff --git a/src/TargetController/TargetControllerConsole.hpp b/src/TargetController/TargetControllerConsole.hpp index a176e2ca..abdac039 100644 --- a/src/TargetController/TargetControllerConsole.hpp +++ b/src/TargetController/TargetControllerConsole.hpp @@ -183,6 +183,20 @@ namespace Bloom::TargetController */ void resetTarget(); + /** + * Enables programming mode on the target. + * + * From the point of invoking this function, the TargetController will reject any subsequent commands for + * debug operations (such as ResumeTargetExecution, ReadTargetRegisters, etc), until programming mode has + * been disabled. + */ + void enableProgrammingMode(); + + /** + * Disables programming mode on the target. + */ + void disableProgrammingMode(); + private: CommandManager commandManager = CommandManager();