2022-04-09 15:26:56 +01:00
|
|
|
#include "TargetControllerComponent.hpp"
|
2021-08-15 01:47:48 +01:00
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
#include <filesystem>
|
|
|
|
|
#include <typeindex>
|
2021-09-11 20:39:31 +01:00
|
|
|
#include <algorithm>
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
#include "src/Targets/Microchip/AVR8/TargetDescriptionFile.hpp"
|
2024-10-12 23:16:16 +01:00
|
|
|
#include "src/Targets/RiscV/Wch/TargetDescriptionFile.hpp"
|
2023-12-17 18:12:53 +00:00
|
|
|
|
2022-10-05 20:58:25 +01:00
|
|
|
#include "Responses/Error.hpp"
|
|
|
|
|
|
2024-03-16 00:07:55 +00:00
|
|
|
#include "src/Services/TargetService.hpp"
|
2023-12-17 18:12:53 +00:00
|
|
|
#include "src/Services/PathService.hpp"
|
2022-12-26 21:35:24 +00:00
|
|
|
#include "src/Services/ProcessService.hpp"
|
2023-09-20 23:37:54 +01:00
|
|
|
#include "src/Services/StringService.hpp"
|
2021-10-06 21:12:31 +01:00
|
|
|
#include "src/Logger/Logger.hpp"
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2021-08-15 01:47:48 +01:00
|
|
|
#include "src/Exceptions/InvalidConfig.hpp"
|
|
|
|
|
|
2023-08-13 15:47:51 +01:00
|
|
|
namespace TargetController
|
2022-02-05 15:32:08 +00:00
|
|
|
{
|
2023-08-13 15:47:51 +01:00
|
|
|
using namespace Targets;
|
|
|
|
|
using namespace Events;
|
|
|
|
|
using namespace Exceptions;
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2022-04-17 23:55:34 +01:00
|
|
|
using Commands::CommandIdType;
|
2022-05-01 19:23:58 +01:00
|
|
|
|
|
|
|
|
using Commands::Command;
|
2023-06-01 22:13:07 +01:00
|
|
|
using Commands::StartAtomicSession;
|
|
|
|
|
using Commands::EndAtomicSession;
|
2023-05-26 01:02:51 +01:00
|
|
|
using Commands::Shutdown;
|
2022-05-01 18:30:58 +01:00
|
|
|
using Commands::GetTargetDescriptor;
|
2022-04-28 21:02:45 +01:00
|
|
|
using Commands::GetTargetState;
|
2022-04-18 18:50:23 +01:00
|
|
|
using Commands::StopTargetExecution;
|
2022-04-19 21:12:59 +01:00
|
|
|
using Commands::ResumeTargetExecution;
|
2022-04-23 17:41:02 +01:00
|
|
|
using Commands::ResetTarget;
|
2022-04-24 16:41:40 +01:00
|
|
|
using Commands::ReadTargetRegisters;
|
2022-04-24 17:37:58 +01:00
|
|
|
using Commands::WriteTargetRegisters;
|
2022-04-24 18:55:19 +01:00
|
|
|
using Commands::ReadTargetMemory;
|
2022-04-30 01:30:57 +01:00
|
|
|
using Commands::WriteTargetMemory;
|
2022-12-11 23:25:15 +00:00
|
|
|
using Commands::EraseTargetMemory;
|
2022-04-29 22:12:09 +01:00
|
|
|
using Commands::StepTargetExecution;
|
2022-04-30 22:03:28 +01:00
|
|
|
using Commands::SetBreakpoint;
|
2022-04-30 22:45:46 +01:00
|
|
|
using Commands::RemoveBreakpoint;
|
2022-05-01 18:47:57 +01:00
|
|
|
using Commands::SetTargetProgramCounter;
|
2024-07-23 21:14:22 +01:00
|
|
|
using Commands::SetTargetStackPointer;
|
2024-08-16 22:50:06 +01:00
|
|
|
using Commands::GetTargetGpioPadStates;
|
|
|
|
|
using Commands::SetTargetGpioPadState;
|
2022-05-01 18:01:01 +01:00
|
|
|
using Commands::GetTargetStackPointer;
|
2022-05-01 18:44:04 +01:00
|
|
|
using Commands::GetTargetProgramCounter;
|
2022-06-05 16:13:43 +01:00
|
|
|
using Commands::EnableProgrammingMode;
|
|
|
|
|
using Commands::DisableProgrammingMode;
|
2022-04-18 18:50:23 +01:00
|
|
|
|
2022-04-17 23:55:34 +01:00
|
|
|
using Responses::Response;
|
2023-06-01 22:13:07 +01:00
|
|
|
using Responses::AtomicSessionId;
|
2022-04-24 16:41:40 +01:00
|
|
|
using Responses::TargetRegistersRead;
|
2022-04-24 18:55:19 +01:00
|
|
|
using Responses::TargetMemoryRead;
|
2024-08-16 22:50:06 +01:00
|
|
|
using Responses::TargetGpioPadStates;
|
2022-05-01 18:01:01 +01:00
|
|
|
using Responses::TargetStackPointer;
|
2022-05-01 18:44:04 +01:00
|
|
|
using Responses::TargetProgramCounter;
|
2023-09-20 23:37:54 +01:00
|
|
|
using Responses::Breakpoint;
|
2022-04-18 18:50:23 +01:00
|
|
|
|
2022-04-15 22:06:38 +01:00
|
|
|
TargetControllerComponent::TargetControllerComponent(
|
|
|
|
|
const ProjectConfig& projectConfig,
|
|
|
|
|
const EnvironmentConfig& environmentConfig
|
|
|
|
|
)
|
|
|
|
|
: projectConfig(projectConfig)
|
|
|
|
|
, environmentConfig(environmentConfig)
|
|
|
|
|
{}
|
|
|
|
|
|
2022-04-09 15:26:56 +01:00
|
|
|
void TargetControllerComponent::run() {
|
2022-02-05 15:32:08 +00:00
|
|
|
try {
|
|
|
|
|
this->startup();
|
|
|
|
|
|
|
|
|
|
this->setThreadStateAndEmitEvent(ThreadState::READY);
|
2023-11-23 12:59:36 +00:00
|
|
|
Logger::debug("TargetController ready");
|
2022-02-05 15:32:08 +00:00
|
|
|
|
|
|
|
|
while (this->getThreadState() == ThreadState::READY) {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->refreshExecutionState();
|
2023-05-25 00:29:46 +01:00
|
|
|
|
|
|
|
|
TargetControllerComponent::notifier.waitForNotification(std::chrono::milliseconds(60));
|
|
|
|
|
|
|
|
|
|
this->processQueuedCommands();
|
|
|
|
|
this->eventListener->dispatchCurrentEvents();
|
2021-05-30 16:52:32 +01:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
} catch (const std::exception& exception) {
|
|
|
|
|
Logger::error("The TargetController encountered a fatal error. See below for errors:");
|
2024-07-23 21:14:22 +01:00
|
|
|
Logger::error(std::string{exception.what()});
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
this->shutdown();
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-01 22:13:07 +01:00
|
|
|
void TargetControllerComponent::registerCommand(
|
|
|
|
|
std::unique_ptr<Command> command,
|
|
|
|
|
const std::optional<AtomicSessionIdType>& atomicSessionId
|
|
|
|
|
) {
|
2023-05-26 00:23:07 +01:00
|
|
|
if (TargetControllerComponent::state != TargetControllerState::ACTIVE) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{"Command rejected - TargetController not in active state."};
|
2023-05-26 00:23:07 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-01 22:13:07 +01:00
|
|
|
if (atomicSessionId.has_value()) {
|
|
|
|
|
// This command is part of an atomic session - put it in the dedicated queue
|
2023-06-02 00:16:58 +01:00
|
|
|
TargetControllerComponent::atomicSessionCommandQueue.accessor()->push(std::move(command));
|
2023-06-01 22:13:07 +01:00
|
|
|
TargetControllerComponent::notifier.notify();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-02 00:16:58 +01:00
|
|
|
TargetControllerComponent::commandQueue.accessor()->push(std::move(command));
|
2022-04-17 23:55:34 +01:00
|
|
|
TargetControllerComponent::notifier.notify();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::optional<std::unique_ptr<Responses::Response>> TargetControllerComponent::waitForResponse(
|
|
|
|
|
CommandIdType commandId,
|
|
|
|
|
std::optional<std::chrono::milliseconds> timeout
|
|
|
|
|
) {
|
|
|
|
|
auto response = std::unique_ptr<Response>(nullptr);
|
|
|
|
|
|
|
|
|
|
const auto predicate = [commandId, &response] {
|
2023-06-02 00:16:58 +01:00
|
|
|
// We will already hold the lock here, so we can use Synchronised::unsafeReference() here.
|
|
|
|
|
auto& responsesByCommandId = TargetControllerComponent::responsesByCommandId.unsafeReference();
|
2022-04-17 23:55:34 +01:00
|
|
|
auto responseIt = responsesByCommandId.find(commandId);
|
|
|
|
|
|
|
|
|
|
if (responseIt != responsesByCommandId.end()) {
|
|
|
|
|
response.swap(responseIt->second);
|
|
|
|
|
responsesByCommandId.erase(responseIt);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-02 00:16:58 +01:00
|
|
|
auto responsesByCommandIdLock = TargetControllerComponent::responsesByCommandId.lock();
|
2022-04-17 23:55:34 +01:00
|
|
|
|
|
|
|
|
if (timeout.has_value()) {
|
|
|
|
|
TargetControllerComponent::responsesByCommandIdCv.wait_for(
|
|
|
|
|
responsesByCommandIdLock,
|
|
|
|
|
timeout.value(),
|
|
|
|
|
predicate
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
TargetControllerComponent::responsesByCommandIdCv.wait(responsesByCommandIdLock, predicate);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return (response != nullptr) ? std::optional{std::move(response)} : std::nullopt;
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-18 18:49:49 +01:00
|
|
|
void TargetControllerComponent::deregisterCommandHandler(Commands::CommandType commandType) {
|
|
|
|
|
this->commandHandlersByCommandType.erase(commandType);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-09 15:26:56 +01:00
|
|
|
void TargetControllerComponent::startup() {
|
2022-02-05 15:32:08 +00:00
|
|
|
this->setName("TC");
|
|
|
|
|
Logger::info("Starting TargetController");
|
2023-05-25 23:16:30 +01:00
|
|
|
this->threadState = ThreadState::STARTING;
|
2022-07-28 22:45:21 +01:00
|
|
|
this->blockAllSignals();
|
2022-04-30 15:51:47 +01:00
|
|
|
this->eventListener->setInterruptEventNotifier(&TargetControllerComponent::notifier);
|
2022-03-20 17:37:36 +00:00
|
|
|
EventManager::registerListener(this->eventListener);
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-08-14 17:39:35 +01:00
|
|
|
// Register command handlers
|
2023-06-01 22:13:07 +01:00
|
|
|
this->registerCommandHandler<StartAtomicSession>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleStartAtomicSession, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<EndAtomicSession>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleEndAtomicSession, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2023-05-26 01:02:51 +01:00
|
|
|
this->registerCommandHandler<Shutdown>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleShutdown, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2022-08-14 17:39:35 +01:00
|
|
|
this->registerCommandHandler<GetTargetDescriptor>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleGetTargetDescriptor, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<GetTargetState>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleGetTargetState, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<StopTargetExecution>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleStopTargetExecution, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<ResumeTargetExecution>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleResumeTargetExecution, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<ResetTarget>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleResetTarget, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<ReadTargetRegisters>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleReadTargetRegisters, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<WriteTargetRegisters>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleWriteTargetRegisters, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<ReadTargetMemory>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleReadTargetMemory, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<WriteTargetMemory>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleWriteTargetMemory, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2022-12-11 23:25:15 +00:00
|
|
|
this->registerCommandHandler<EraseTargetMemory>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleEraseTargetMemory, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2022-08-14 17:39:35 +01:00
|
|
|
this->registerCommandHandler<StepTargetExecution>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleStepTargetExecution, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<SetBreakpoint>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleSetBreakpoint, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<RemoveBreakpoint>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleRemoveBreakpoint, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
this->registerCommandHandler<SetTargetStackPointer>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleSetStackPointer, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2022-08-14 17:39:35 +01:00
|
|
|
this->registerCommandHandler<SetTargetProgramCounter>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleSetProgramCounter, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2024-08-16 22:50:06 +01:00
|
|
|
this->registerCommandHandler<GetTargetGpioPadStates>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleGetTargetGpioPadStates, this, std::placeholders::_1)
|
2022-08-14 17:39:35 +01:00
|
|
|
);
|
|
|
|
|
|
2024-08-16 22:50:06 +01:00
|
|
|
this->registerCommandHandler<SetTargetGpioPadState>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleSetTargetGpioPadState, this, std::placeholders::_1)
|
2022-08-14 17:39:35 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<GetTargetStackPointer>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleGetTargetStackPointer, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<GetTargetProgramCounter>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleGetTargetProgramCounter, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<EnableProgrammingMode>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleEnableProgrammingMode, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->registerCommandHandler<DisableProgrammingMode>(
|
|
|
|
|
std::bind(&TargetControllerComponent::handleDisableProgrammingMode, this, std::placeholders::_1)
|
|
|
|
|
);
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
// Register event handlers
|
|
|
|
|
this->eventListener->registerCallbackForEventType<Events::ShutdownTargetController>(
|
2022-04-09 15:26:56 +01:00
|
|
|
std::bind(&TargetControllerComponent::onShutdownTargetControllerEvent, this, std::placeholders::_1)
|
2022-02-05 15:32:08 +00:00
|
|
|
);
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2023-05-26 00:23:07 +01:00
|
|
|
this->eventListener->registerCallbackForEventType<Events::DebugSessionFinished>(
|
|
|
|
|
std::bind(&TargetControllerComponent::onDebugSessionFinishedEvent, this, std::placeholders::_1)
|
2022-02-05 15:32:08 +00:00
|
|
|
);
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2023-05-26 00:23:07 +01:00
|
|
|
this->acquireHardware();
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (this->targetState->executionState != TargetExecutionState::RUNNING) {
|
|
|
|
|
// this->target->run();
|
|
|
|
|
// this->targetState->executionState = TargetExecutionState::RUNNING;
|
2023-05-26 00:23:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->state = TargetControllerState::ACTIVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::shutdown() {
|
|
|
|
|
const auto threadState = this->getThreadState();
|
|
|
|
|
if (threadState == ThreadState::SHUTDOWN_INITIATED || threadState == ThreadState::STOPPED) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->threadState = ThreadState::SHUTDOWN_INITIATED;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Logger::info("Shutting down TargetController");
|
|
|
|
|
this->state = TargetControllerState::INACTIVE;
|
|
|
|
|
EventManager::deregisterListener(this->eventListener->getId());
|
|
|
|
|
|
2023-06-01 22:13:07 +01:00
|
|
|
if (this->activeAtomicSession.has_value()) {
|
|
|
|
|
// Reject any commands on the dedicated queue
|
|
|
|
|
this->processQueuedCommands();
|
|
|
|
|
this->endActiveAtomicSession();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-26 00:23:07 +01:00
|
|
|
// Reject any commands still waiting in the queue
|
|
|
|
|
this->processQueuedCommands();
|
|
|
|
|
|
|
|
|
|
this->releaseHardware();
|
|
|
|
|
|
|
|
|
|
} catch (const std::exception& exception) {
|
|
|
|
|
this->target.reset();
|
|
|
|
|
this->debugTool.reset();
|
|
|
|
|
Logger::error(
|
2024-07-23 21:14:22 +01:00
|
|
|
"Failed to properly shut down TargetController. Error: " + std::string{exception.what()}
|
2023-05-26 00:23:07 +01:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->setThreadStateAndEmitEvent(ThreadState::STOPPED);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-04-17 23:55:34 +01:00
|
|
|
std::map<
|
|
|
|
|
std::string,
|
|
|
|
|
std::function<std::unique_ptr<DebugTool>()>
|
|
|
|
|
> TargetControllerComponent::getSupportedDebugTools() {
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
using namespace DebugToolDrivers::Microchip;
|
|
|
|
|
using namespace DebugToolDrivers::Wch;
|
|
|
|
|
|
2022-05-01 17:33:39 +01:00
|
|
|
// The debug tool names in this mapping should always be lower-case.
|
2022-04-17 23:55:34 +01:00
|
|
|
return std::map<std::string, std::function<std::unique_ptr<DebugTool>()>> {
|
|
|
|
|
{
|
|
|
|
|
"atmel-ice",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<AtmelIce>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"power-debugger",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<PowerDebugger>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"snap",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<MplabSnap>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"pickit-4",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<MplabPickit4>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"xplained-pro",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<XplainedPro>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"xplained-mini",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<XplainedMini>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"xplained-nano",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<XplainedNano>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"curiosity-nano",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<CuriosityNano>(this->environmentConfig.debugToolConfig);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
},
|
2022-05-02 22:51:21 +01:00
|
|
|
{
|
|
|
|
|
"jtagice3",
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
[this] {
|
|
|
|
|
return std::make_unique<JtagIce3>(this->environmentConfig.debugToolConfig);
|
2022-05-02 22:51:21 +01:00
|
|
|
}
|
|
|
|
|
},
|
2023-11-18 22:58:48 +00:00
|
|
|
{
|
|
|
|
|
"wch-link-e",
|
2024-10-06 23:32:36 +01:00
|
|
|
[this] {
|
Made the EDBG CMSIS-DAP command delay optional for all debug tools, and disabled it by default.
The command delay was really choking Bloom's EDBG driver, causing a very noticeable drag on Bloom's performance. It's much faster with the command delay disabled.
There was a good reason for why I introduced this some time ago. Without it, some EDBG debug tools were misbehaving - I remember that for certain. But now, I cannot seem to reproduce these issues. Very odd.
If the issues do reappear, I may have to enable the command delay by default, again, for some debug tools.
For now, if any users experience issues, I'll just suggest they manually enable the command delay via their project config.
Also, I'm not going to document this new config option, as I would prefer the user to approach me if they experience issues as a result of this, so that I'll know if it needs revisiting.
2024-10-27 00:25:42 +01:00
|
|
|
return std::make_unique<WchLinkE>(this->environmentConfig.debugToolConfig);
|
2023-11-18 22:58:48 +00:00
|
|
|
}
|
|
|
|
|
},
|
2022-04-17 23:55:34 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-02 01:59:55 +00:00
|
|
|
std::unique_ptr<Target> TargetControllerComponent::constructTarget(const BriefTargetDescriptor& briefDescriptor) {
|
2023-12-17 18:12:53 +00:00
|
|
|
using Services::PathService;
|
|
|
|
|
|
2024-03-02 01:59:55 +00:00
|
|
|
if (briefDescriptor.family == TargetFamily::AVR_8) {
|
2024-07-23 21:14:22 +01:00
|
|
|
return std::make_unique<Microchip::Avr8::Avr8>(
|
2023-12-17 18:12:53 +00:00
|
|
|
this->environmentConfig.targetConfig,
|
2024-07-23 21:14:22 +01:00
|
|
|
Microchip::Avr8::TargetDescriptionFile{
|
|
|
|
|
PathService::targetDescriptionFilesDirPath() + "/" + briefDescriptor.relativeTdfPath
|
|
|
|
|
}
|
2023-12-17 18:12:53 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-02 01:59:55 +00:00
|
|
|
if (briefDescriptor.family == TargetFamily::RISC_V) {
|
2024-10-12 23:16:16 +01:00
|
|
|
/*
|
|
|
|
|
* Given that WCH targets are the only RISC-V targets we support ATM, we can just assume that
|
|
|
|
|
* construction of a WchRiscV object is necessary.
|
|
|
|
|
*
|
|
|
|
|
* TODO: Review later
|
|
|
|
|
*/
|
|
|
|
|
return std::make_unique<RiscV::Wch::WchRiscV>(
|
2023-12-17 18:12:53 +00:00
|
|
|
this->environmentConfig.targetConfig,
|
2024-10-12 23:16:16 +01:00
|
|
|
RiscV::Wch::TargetDescriptionFile{
|
2024-07-23 21:14:22 +01:00
|
|
|
PathService::targetDescriptionFilesDirPath() + "/" + briefDescriptor.relativeTdfPath
|
|
|
|
|
}
|
2023-12-17 18:12:53 +00:00
|
|
|
);
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{"Cannot construct target instance - invalid target family in BriefTargetDescriptor"};
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::processQueuedCommands() {
|
2024-07-23 21:14:22 +01:00
|
|
|
auto commands = std::queue<std::unique_ptr<Command>>{};
|
2022-04-17 23:55:34 +01:00
|
|
|
|
2023-06-02 00:16:58 +01:00
|
|
|
commands.swap(
|
|
|
|
|
this->activeAtomicSession.has_value()
|
|
|
|
|
? *(TargetControllerComponent::atomicSessionCommandQueue.accessor())
|
|
|
|
|
: *(TargetControllerComponent::commandQueue.accessor())
|
|
|
|
|
);
|
2022-04-17 23:55:34 +01:00
|
|
|
|
|
|
|
|
while (!commands.empty()) {
|
|
|
|
|
const auto command = std::move(commands.front());
|
|
|
|
|
commands.pop();
|
|
|
|
|
|
|
|
|
|
const auto commandId = command->id;
|
|
|
|
|
const auto commandType = command->getType();
|
|
|
|
|
|
|
|
|
|
try {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto commandHandlerIt = this->commandHandlersByCommandType.find(commandType);
|
|
|
|
|
|
|
|
|
|
if (commandHandlerIt == this->commandHandlersByCommandType.end()) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{"No handler registered for this command."};
|
2022-04-17 23:55:34 +01:00
|
|
|
}
|
|
|
|
|
|
2023-05-26 00:23:07 +01:00
|
|
|
if (this->state != TargetControllerState::ACTIVE) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{"Command rejected - TargetController not in active state."};
|
2022-04-29 22:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (
|
|
|
|
|
command->requiresStoppedTargetState()
|
|
|
|
|
&& this->targetState->executionState != TargetExecutionState::STOPPED
|
|
|
|
|
) {
|
|
|
|
|
throw Exception{"Command rejected - command requires target execution to be stopped."};
|
2023-05-26 00:23:07 +01:00
|
|
|
}
|
2022-08-14 17:39:35 +01:00
|
|
|
|
2023-05-26 00:23:07 +01:00
|
|
|
if (this->target->programmingModeEnabled() && command->requiresDebugMode()) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{
|
2023-05-26 00:23:07 +01:00
|
|
|
"Command rejected - command cannot be serviced whilst the target is in programming mode."
|
2024-07-23 21:14:22 +01:00
|
|
|
};
|
2022-06-05 16:13:43 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
this->registerCommandResponse(commandId, commandHandlerIt->second(*(command.get())));
|
2022-04-17 23:55:34 +01:00
|
|
|
|
2023-05-25 00:29:46 +01:00
|
|
|
} catch (const DeviceFailure& exception) {
|
|
|
|
|
this->registerCommandResponse(
|
|
|
|
|
commandId,
|
|
|
|
|
std::make_unique<Responses::Error>(exception.getMessage())
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
throw exception;
|
|
|
|
|
|
2022-04-17 23:55:34 +01:00
|
|
|
} catch (const Exception& exception) {
|
|
|
|
|
this->registerCommandResponse(
|
|
|
|
|
commandId,
|
|
|
|
|
std::make_unique<Responses::Error>(exception.getMessage())
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::registerCommandResponse(
|
|
|
|
|
CommandIdType commandId,
|
|
|
|
|
std::unique_ptr<Response> response
|
|
|
|
|
) {
|
2023-06-02 00:16:58 +01:00
|
|
|
TargetControllerComponent::responsesByCommandId.accessor()->emplace(commandId, std::move(response));
|
2022-04-17 23:55:34 +01:00
|
|
|
TargetControllerComponent::responsesByCommandIdCv.notify_all();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-09 15:26:56 +01:00
|
|
|
void TargetControllerComponent::acquireHardware() {
|
2023-09-20 18:56:44 +01:00
|
|
|
const auto& debugToolName = this->environmentConfig.debugToolConfig.name;
|
|
|
|
|
const auto& targetName = this->environmentConfig.targetConfig.name;
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
static const auto supportedDebugTools = this->getSupportedDebugTools();
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto debugToolIt = supportedDebugTools.find(debugToolName);
|
2024-03-02 01:59:55 +00:00
|
|
|
const auto briefTargetDescriptor = Services::TargetService::briefDescriptor(targetName);
|
2022-12-03 22:16:21 +00:00
|
|
|
|
|
|
|
|
if (debugToolIt == supportedDebugTools.end()) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exceptions::InvalidConfig{
|
2024-10-12 23:16:33 +01:00
|
|
|
"Debug tool (\"" + debugToolName + "\") not recognised. Please check your configuration."
|
2024-07-23 21:14:22 +01:00
|
|
|
};
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2024-03-02 01:59:55 +00:00
|
|
|
if (!briefTargetDescriptor.has_value()) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exceptions::InvalidConfig{
|
2024-10-12 23:16:33 +01:00
|
|
|
"Target (\"" + targetName + "\") not recognised. Please check your configuration."
|
2024-07-23 21:14:22 +01:00
|
|
|
};
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
this->debugTool = debugToolIt->second();
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
Logger::info("Connecting to debug tool");
|
|
|
|
|
this->debugTool->init();
|
|
|
|
|
Logger::info("Debug tool connected");
|
2024-07-23 21:44:15 +01:00
|
|
|
|
|
|
|
|
this->debugTool->postInit();
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
Logger::info("Debug tool name: " + this->debugTool->getName());
|
|
|
|
|
Logger::info("Debug tool serial: " + this->debugTool->getSerialNumber());
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2024-03-02 01:59:55 +00:00
|
|
|
this->target = this->constructTarget(*briefTargetDescriptor);
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2023-05-21 21:08:25 +01:00
|
|
|
if (!this->target->supportsDebugTool(this->debugTool.get())) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exceptions::InvalidConfig{
|
2023-11-18 22:53:20 +00:00
|
|
|
"Debug tool \"" + this->debugTool->getName() + "\" is not compatible with target \""
|
2024-07-23 21:14:22 +01:00
|
|
|
+ targetName + "\"."
|
|
|
|
|
};
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
2021-04-12 19:43:42 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
this->target->setDebugTool(this->debugTool.get());
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
Logger::info("Activating target");
|
|
|
|
|
this->target->activate();
|
|
|
|
|
Logger::info("Target activated");
|
2024-09-07 13:07:40 +01:00
|
|
|
|
|
|
|
|
this->targetDescriptor = std::make_unique<const TargetDescriptor>(this->target->targetDescriptor());
|
2024-07-25 19:04:13 +01:00
|
|
|
Logger::info("Target name: " + this->targetDescriptor->name);
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2024-07-23 21:35:12 +01:00
|
|
|
this->target->postActivate();
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
this->targetState = std::make_unique<TargetState>(
|
|
|
|
|
TargetExecutionState::UNKNOWN,
|
|
|
|
|
TargetMode::DEBUGGING,
|
|
|
|
|
std::nullopt
|
|
|
|
|
);
|
|
|
|
|
this->refreshExecutionState();
|
2023-09-20 23:37:54 +01:00
|
|
|
|
|
|
|
|
if (!this->environmentConfig.targetConfig.hardwareBreakpoints) {
|
|
|
|
|
Logger::warning("Hardware breakpoints have been disabled");
|
|
|
|
|
|
2023-09-23 21:50:04 +01:00
|
|
|
} else {
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto& breakpointResources = this->targetDescriptor->breakpointResources;
|
2023-09-23 21:50:04 +01:00
|
|
|
if (breakpointResources.maximumHardwareBreakpoints.has_value()) {
|
|
|
|
|
Logger::info(
|
|
|
|
|
"Available hardware breakpoints: " + std::to_string(
|
|
|
|
|
*(breakpointResources.maximumHardwareBreakpoints)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (breakpointResources.reservedHardwareBreakpoints > 0) {
|
|
|
|
|
Logger::info(
|
2024-07-23 21:14:22 +01:00
|
|
|
"Reserved hardware breakpoints: " + std::to_string(breakpointResources.reservedHardwareBreakpoints)
|
2023-09-23 21:50:04 +01:00
|
|
|
);
|
|
|
|
|
}
|
2023-09-20 23:37:54 +01:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-09 15:26:56 +01:00
|
|
|
void TargetControllerComponent::releaseHardware() {
|
2022-03-17 00:00:40 +00:00
|
|
|
/*
|
|
|
|
|
* Transferring ownership of this->debugTool and this->target to this function block means if an exception is
|
|
|
|
|
* thrown, the objects will still be destroyed.
|
|
|
|
|
*/
|
|
|
|
|
auto debugTool = std::move(this->debugTool);
|
|
|
|
|
auto target = std::move(this->target);
|
2022-02-05 15:32:08 +00:00
|
|
|
|
|
|
|
|
if (debugTool != nullptr && debugTool->isInitialised()) {
|
|
|
|
|
if (target != nullptr) {
|
|
|
|
|
/*
|
|
|
|
|
* We call deactivate() without checking if the target is activated. This will address any cases
|
|
|
|
|
* where a target is only partially activated (where the call to activate() failed).
|
|
|
|
|
*/
|
|
|
|
|
Logger::info("Deactivating target");
|
|
|
|
|
target->deactivate();
|
|
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
Logger::info("Closing debug tool");
|
|
|
|
|
debugTool->close();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-06 21:12:31 +01:00
|
|
|
|
2023-06-01 22:13:07 +01:00
|
|
|
void TargetControllerComponent::startAtomicSession() {
|
|
|
|
|
if (this->activeAtomicSession.has_value()) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{"Atomic session already active - nested sessions are not supported"};
|
2023-06-01 22:13:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->activeAtomicSession.emplace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::endActiveAtomicSession() {
|
|
|
|
|
if (!this->activeAtomicSession.has_value()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2023-06-02 00:16:58 +01:00
|
|
|
auto commandQueue = TargetControllerComponent::atomicSessionCommandQueue.accessor();
|
2024-07-23 21:14:22 +01:00
|
|
|
auto empty = std::queue<std::unique_ptr<Commands::Command>>{};
|
2023-06-02 00:16:58 +01:00
|
|
|
commandQueue->swap(empty);
|
2023-06-01 22:13:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->activeAtomicSession.reset();
|
|
|
|
|
TargetControllerComponent::notifier.notify();
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void TargetControllerComponent::refreshExecutionState() {
|
|
|
|
|
auto newExecutionState = this->target->getExecutionState();
|
2021-10-06 21:12:31 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (newExecutionState != this->targetState->executionState) {
|
|
|
|
|
Logger::debug("Target execution state changed");
|
2021-10-06 21:12:31 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
auto newState = *(this->targetState);
|
|
|
|
|
newState.executionState = newExecutionState;
|
2022-12-03 22:16:21 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (newExecutionState == TargetExecutionState::STOPPED) {
|
|
|
|
|
Logger::debug("Target stopped");
|
|
|
|
|
newState.programCounter = this->target->getProgramCounter();
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2023-05-21 21:08:25 +01:00
|
|
|
} else {
|
2024-07-23 21:14:22 +01:00
|
|
|
Logger::debug("Target resumed");
|
|
|
|
|
newState.programCounter = std::nullopt;
|
|
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
this->updateTargetState(newState);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-06 21:12:31 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void TargetControllerComponent::updateTargetState(const TargetState& newState) {
|
|
|
|
|
if (newState == *(this->targetState)) {
|
|
|
|
|
// Nothing has changed, nothing to do
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-05-21 21:08:25 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto previousState = *(this->targetState);
|
|
|
|
|
*(this->targetState) = newState;
|
|
|
|
|
EventManager::triggerEvent(std::make_shared<TargetStateChanged>(*(this->targetState), previousState));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::stopTarget() {
|
|
|
|
|
if (this->target->getExecutionState() != TargetExecutionState::STOPPED) {
|
|
|
|
|
this->target->stop();
|
2021-10-06 21:12:31 +01:00
|
|
|
}
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
auto newState = *(this->targetState);
|
|
|
|
|
newState.executionState = TargetExecutionState::STOPPED;
|
|
|
|
|
newState.programCounter = this->target->getProgramCounter();
|
|
|
|
|
this->updateTargetState(newState);
|
2021-10-06 21:12:31 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void TargetControllerComponent::resumeTarget() {
|
|
|
|
|
if (this->target->getExecutionState() != TargetExecutionState::RUNNING) {
|
|
|
|
|
this->target->run(std::nullopt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto newState = *(this->targetState);
|
|
|
|
|
newState.executionState = TargetExecutionState::RUNNING;
|
|
|
|
|
newState.programCounter = std::nullopt;
|
|
|
|
|
this->updateTargetState(newState);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::stepTarget() {
|
|
|
|
|
this->target->step();
|
|
|
|
|
|
|
|
|
|
auto newState = *(this->targetState);
|
|
|
|
|
newState.executionState = TargetExecutionState::STEPPING;
|
|
|
|
|
newState.programCounter = std::nullopt;
|
|
|
|
|
this->updateTargetState(newState);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::resetTarget() {
|
|
|
|
|
this->target->reset();
|
|
|
|
|
EventManager::triggerEvent(std::make_shared<Events::TargetReset>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TargetRegisterDescriptorAndValuePairs TargetControllerComponent::readTargetRegisters(
|
|
|
|
|
const TargetRegisterDescriptors& descriptors
|
2021-10-06 21:12:31 +01:00
|
|
|
) {
|
2024-07-23 21:14:22 +01:00
|
|
|
return this->target->readRegisters(descriptors);
|
|
|
|
|
}
|
2021-10-06 21:12:31 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void TargetControllerComponent::writeTargetRegisters(const TargetRegisterDescriptorAndValuePairs& registers) {
|
|
|
|
|
this->target->writeRegisters(registers);
|
|
|
|
|
EventManager::triggerEvent(std::make_shared<Events::RegistersWrittenToTarget>(registers));
|
|
|
|
|
}
|
2022-12-03 22:16:21 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
Targets::TargetMemoryBuffer TargetControllerComponent::readTargetMemory(
|
|
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
|
|
|
|
TargetMemoryAddress startAddress,
|
|
|
|
|
TargetMemorySize bytes,
|
|
|
|
|
const std::set<TargetMemoryAddressRange>& excludedAddressRanges,
|
|
|
|
|
bool bypassCache
|
|
|
|
|
) {
|
2022-12-03 22:16:21 +00:00
|
|
|
if (
|
2024-07-23 21:14:22 +01:00
|
|
|
!bypassCache
|
|
|
|
|
&& this->environmentConfig.targetConfig.programMemoryCache
|
|
|
|
|
&& this->target->isProgramMemory(addressSpaceDescriptor, memorySegmentDescriptor, startAddress, bytes)
|
2021-10-06 21:12:31 +01:00
|
|
|
) {
|
2024-10-07 00:14:39 +01:00
|
|
|
auto& cache = this->getProgramMemoryCache(memorySegmentDescriptor);
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
if (!cache.contains(startAddress, bytes)) {
|
|
|
|
|
Logger::debug(
|
|
|
|
|
"Program memory cache miss at 0x" + Services::StringService::toHex(startAddress) + ", "
|
|
|
|
|
+ std::to_string(bytes) + " bytes"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: We're currently ignoring excludedAddressRanges when populating the program
|
|
|
|
|
* memory cache. This isn't a big deal, so I'll sort it later.
|
|
|
|
|
*/
|
|
|
|
|
cache.insert(
|
|
|
|
|
startAddress,
|
|
|
|
|
this->target->readMemory(
|
|
|
|
|
addressSpaceDescriptor,
|
|
|
|
|
memorySegmentDescriptor,
|
|
|
|
|
startAddress,
|
|
|
|
|
std::max(
|
|
|
|
|
bytes,
|
|
|
|
|
memorySegmentDescriptor.pageSize.value_or(0)
|
|
|
|
|
),
|
|
|
|
|
{}
|
|
|
|
|
)
|
|
|
|
|
);
|
2021-10-06 21:12:31 +01:00
|
|
|
}
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
return cache.fetch(startAddress, bytes);
|
2021-10-06 21:12:31 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return this->target->readMemory(
|
|
|
|
|
addressSpaceDescriptor,
|
|
|
|
|
memorySegmentDescriptor,
|
|
|
|
|
startAddress,
|
|
|
|
|
bytes,
|
|
|
|
|
excludedAddressRanges
|
|
|
|
|
);
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-10-06 21:12:31 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void TargetControllerComponent::writeTargetMemory(
|
|
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
|
|
|
|
Targets::TargetMemoryAddress startAddress,
|
|
|
|
|
const TargetMemoryBuffer& buffer
|
|
|
|
|
) {
|
|
|
|
|
const auto isProgramMemory = this->target->isProgramMemory(
|
|
|
|
|
addressSpaceDescriptor,
|
|
|
|
|
memorySegmentDescriptor,
|
|
|
|
|
startAddress,
|
|
|
|
|
static_cast<TargetMemorySize>(buffer.size())
|
|
|
|
|
);
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (isProgramMemory && !this->target->programmingModeEnabled()) {
|
|
|
|
|
throw Exception{"Cannot write to program memory - programming mode not enabled."};
|
|
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
this->target->writeMemory(addressSpaceDescriptor, memorySegmentDescriptor, startAddress, buffer);
|
|
|
|
|
|
|
|
|
|
if (isProgramMemory && this->environmentConfig.targetConfig.programMemoryCache) {
|
2024-10-07 00:14:39 +01:00
|
|
|
this->getProgramMemoryCache(memorySegmentDescriptor).insert(startAddress, buffer);
|
2024-07-23 21:14:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EventManager::triggerEvent(
|
|
|
|
|
std::make_shared<Events::MemoryWrittenToTarget>(
|
|
|
|
|
addressSpaceDescriptor,
|
|
|
|
|
memorySegmentDescriptor,
|
|
|
|
|
startAddress,
|
|
|
|
|
static_cast<TargetMemorySize>(buffer.size())
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::eraseTargetMemory(
|
|
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor
|
|
|
|
|
) {
|
|
|
|
|
if (this->target->isProgramMemory(
|
|
|
|
|
addressSpaceDescriptor,
|
|
|
|
|
memorySegmentDescriptor,
|
|
|
|
|
memorySegmentDescriptor.addressRange.startAddress,
|
|
|
|
|
memorySegmentDescriptor.addressRange.size()
|
|
|
|
|
)) {
|
|
|
|
|
if (!this->target->programmingModeEnabled()) {
|
|
|
|
|
throw Exception{"Cannot erase program memory - programming mode not enabled."};
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (this->environmentConfig.targetConfig.programMemoryCache) {
|
|
|
|
|
Logger::debug("Clearing program memory cache");
|
2024-10-07 00:14:39 +01:00
|
|
|
this->getProgramMemoryCache(memorySegmentDescriptor).clear();
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
this->target->eraseMemory(addressSpaceDescriptor, memorySegmentDescriptor);
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void TargetControllerComponent::setBreakpoint(const TargetBreakpoint& breakpoint) {
|
|
|
|
|
using Services::StringService;
|
2022-04-08 22:14:01 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (breakpoint.type == TargetBreakpoint::Type::HARDWARE) {
|
|
|
|
|
Logger::debug(
|
|
|
|
|
"Installing hardware breakpoint at byte address 0x" + StringService::toHex(breakpoint.address)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->target->setHardwareBreakpoint(breakpoint.address);
|
|
|
|
|
this->hardwareBreakpointsByAddress.emplace(breakpoint.address, breakpoint);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger::debug("Installing software breakpoint at byte address 0x" + StringService::toHex(breakpoint.address));
|
|
|
|
|
|
|
|
|
|
this->target->setSoftwareBreakpoint(breakpoint.address);
|
|
|
|
|
this->softwareBreakpointsByAddress.emplace(breakpoint.address, breakpoint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::removeBreakpoint(const TargetBreakpoint& breakpoint) {
|
|
|
|
|
using Services::StringService;
|
|
|
|
|
|
|
|
|
|
if (breakpoint.type == Targets::TargetBreakpoint::Type::HARDWARE) {
|
|
|
|
|
Logger::debug("Removing hardware breakpoint at byte address 0x" + StringService::toHex(breakpoint.address));
|
|
|
|
|
|
|
|
|
|
this->target->removeHardwareBreakpoint(breakpoint.address);
|
|
|
|
|
this->hardwareBreakpointsByAddress.erase(breakpoint.address);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logger::debug("Removing software breakpoint at byte address 0x" + StringService::toHex(breakpoint.address));
|
|
|
|
|
|
|
|
|
|
this->target->removeSoftwareBreakpoint(breakpoint.address);
|
|
|
|
|
this->softwareBreakpointsByAddress.erase(breakpoint.address);
|
2022-04-08 22:14:01 +01:00
|
|
|
}
|
|
|
|
|
|
2022-06-05 16:13:43 +01:00
|
|
|
void TargetControllerComponent::enableProgrammingMode() {
|
2022-06-05 21:04:47 +01:00
|
|
|
Logger::debug("Enabling programming mode");
|
2022-06-05 16:13:43 +01:00
|
|
|
this->target->enableProgrammingMode();
|
2022-06-05 21:04:47 +01:00
|
|
|
Logger::warning("Programming mode enabled");
|
2022-06-05 16:13:43 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
auto newState = *(this->targetState);
|
|
|
|
|
newState.mode = TargetMode::PROGRAMMING;
|
|
|
|
|
this->updateTargetState(newState);
|
2022-06-05 16:13:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetControllerComponent::disableProgrammingMode() {
|
2022-06-05 21:04:47 +01:00
|
|
|
Logger::debug("Disabling programming mode");
|
2022-06-05 16:13:43 +01:00
|
|
|
this->target->disableProgrammingMode();
|
2022-06-05 21:04:47 +01:00
|
|
|
Logger::info("Programming mode disabled");
|
2022-06-05 16:13:43 +01:00
|
|
|
|
2023-09-22 20:55:00 +01:00
|
|
|
Logger::info("Restoring breakpoints");
|
|
|
|
|
this->target->stop();
|
|
|
|
|
|
|
|
|
|
for (const auto& [address, breakpoint] : this->softwareBreakpointsByAddress) {
|
|
|
|
|
this->target->setSoftwareBreakpoint(address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& [address, breakpoint] : this->hardwareBreakpointsByAddress) {
|
|
|
|
|
this->target->setHardwareBreakpoint(address);
|
|
|
|
|
}
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
auto newState = *(this->targetState);
|
|
|
|
|
newState.mode = TargetMode::DEBUGGING;
|
|
|
|
|
newState.executionState = TargetExecutionState::STOPPED;
|
|
|
|
|
this->updateTargetState(newState);
|
2022-06-05 16:13:43 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetMemoryCache& TargetControllerComponent::getProgramMemoryCache(
|
2024-10-07 00:14:39 +01:00
|
|
|
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor
|
2024-07-23 21:14:22 +01:00
|
|
|
) {
|
2024-10-07 00:14:39 +01:00
|
|
|
auto cacheIt = this->programMemoryCachesBySegmentId.find(memorySegmentDescriptor.id);
|
2024-07-23 21:14:22 +01:00
|
|
|
|
2024-10-07 00:14:39 +01:00
|
|
|
if (cacheIt == this->programMemoryCachesBySegmentId.end()) {
|
|
|
|
|
cacheIt = this->programMemoryCachesBySegmentId.emplace(
|
|
|
|
|
memorySegmentDescriptor.id,
|
|
|
|
|
TargetMemoryCache{memorySegmentDescriptor}
|
2024-07-23 21:14:22 +01:00
|
|
|
).first;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-05-30 16:52:32 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return cacheIt->second;
|
2021-05-30 16:52:32 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-09 15:26:56 +01:00
|
|
|
void TargetControllerComponent::onShutdownTargetControllerEvent(const Events::ShutdownTargetController&) {
|
2022-02-05 15:32:08 +00:00
|
|
|
this->shutdown();
|
2021-05-30 16:52:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-05-26 00:23:07 +01:00
|
|
|
void TargetControllerComponent::onDebugSessionFinishedEvent(const DebugSessionFinished&) {
|
|
|
|
|
if (this->state != TargetControllerState::ACTIVE) {
|
|
|
|
|
return;
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (this->target->getExecutionState() != TargetExecutionState::RUNNING) {
|
|
|
|
|
this->target->run(std::nullopt);
|
|
|
|
|
this->refreshExecutionState();
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
2022-02-05 15:32:08 +00:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2023-06-01 22:13:07 +01:00
|
|
|
std::unique_ptr<AtomicSessionId> TargetControllerComponent::handleStartAtomicSession(StartAtomicSession& command) {
|
|
|
|
|
this->startAtomicSession();
|
|
|
|
|
return std::make_unique<AtomicSessionId>(this->activeAtomicSession->id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleEndAtomicSession(EndAtomicSession& command) {
|
|
|
|
|
if (!this->activeAtomicSession.has_value() || this->activeAtomicSession->id != command.sessionId) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{"Atomic session is not active"};
|
2023-06-01 22:13:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->endActiveAtomicSession();
|
|
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-26 01:02:51 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleShutdown(Shutdown& command) {
|
|
|
|
|
this->shutdown();
|
|
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-01 18:30:58 +01:00
|
|
|
std::unique_ptr<Responses::TargetDescriptor> TargetControllerComponent::handleGetTargetDescriptor(
|
|
|
|
|
GetTargetDescriptor& command
|
|
|
|
|
) {
|
2024-07-23 21:14:22 +01:00
|
|
|
return std::make_unique<Responses::TargetDescriptor>(*(this->targetDescriptor));
|
2022-05-01 18:30:58 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-28 21:02:45 +01:00
|
|
|
std::unique_ptr<Responses::TargetState> TargetControllerComponent::handleGetTargetState(GetTargetState& command) {
|
2024-07-23 21:14:22 +01:00
|
|
|
return std::make_unique<Responses::TargetState>(*(this->targetState));
|
2022-04-28 21:02:45 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-18 18:50:23 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleStopTargetExecution(StopTargetExecution& command) {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->stopTarget();
|
2022-04-18 18:50:23 +01:00
|
|
|
return std::make_unique<Response>();
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleResumeTargetExecution(ResumeTargetExecution& command) {
|
|
|
|
|
this->resumeTarget();
|
2022-04-19 21:12:59 +01:00
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-24 16:41:40 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleResetTarget(ResetTarget& command) {
|
2022-04-23 17:41:02 +01:00
|
|
|
this->resetTarget();
|
|
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-24 16:41:40 +01:00
|
|
|
std::unique_ptr<TargetRegistersRead> TargetControllerComponent::handleReadTargetRegisters(
|
|
|
|
|
ReadTargetRegisters& command
|
|
|
|
|
) {
|
2024-07-23 21:14:22 +01:00
|
|
|
if (command.descriptors.empty()) {
|
|
|
|
|
throw Exception{"No register descriptors provided"};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_unique<TargetRegistersRead>(this->readTargetRegisters(command.descriptors));
|
2022-04-24 16:41:40 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-24 17:37:58 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleWriteTargetRegisters(WriteTargetRegisters& command) {
|
2024-07-23 21:14:22 +01:00
|
|
|
if (command.registers.empty()) {
|
|
|
|
|
throw Exception{"No register values provided"};
|
2023-05-21 21:08:25 +01:00
|
|
|
}
|
2022-04-24 17:37:58 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
this->writeTargetRegisters(std::move(command.registers));
|
2022-04-24 17:37:58 +01:00
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-24 18:55:19 +01:00
|
|
|
std::unique_ptr<TargetMemoryRead> TargetControllerComponent::handleReadTargetMemory(ReadTargetMemory& command) {
|
2024-07-23 21:14:22 +01:00
|
|
|
if (command.bytes == 0) {
|
|
|
|
|
throw Exception{"Zero bytes requested"};
|
|
|
|
|
}
|
2023-09-22 17:52:28 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto addressRange = TargetMemoryAddressRange(
|
|
|
|
|
command.startAddress,
|
|
|
|
|
command.startAddress + command.bytes - 1
|
|
|
|
|
);
|
2023-09-22 17:52:28 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (
|
|
|
|
|
!command.addressSpaceDescriptor.addressRange.contains(addressRange)
|
|
|
|
|
|| !command.memorySegmentDescriptor.addressRange.contains(addressRange)
|
|
|
|
|
) {
|
|
|
|
|
throw Exception{"Invalid address range"};
|
2023-09-22 17:52:28 +01:00
|
|
|
}
|
|
|
|
|
|
2023-05-21 21:08:25 +01:00
|
|
|
return std::make_unique<TargetMemoryRead>(
|
2024-07-23 21:14:22 +01:00
|
|
|
this->readTargetMemory(
|
|
|
|
|
command.addressSpaceDescriptor,
|
|
|
|
|
command.memorySegmentDescriptor,
|
|
|
|
|
command.startAddress,
|
|
|
|
|
command.bytes,
|
|
|
|
|
command.excludedAddressRanges,
|
|
|
|
|
command.bypassCache
|
|
|
|
|
)
|
2023-05-21 21:08:25 +01:00
|
|
|
);
|
2022-04-24 18:55:19 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-30 01:30:57 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleWriteTargetMemory(WriteTargetMemory& command) {
|
2024-07-23 21:14:22 +01:00
|
|
|
if (command.buffer.empty()) {
|
|
|
|
|
throw Exception{"Empty buffer"};
|
2022-06-05 16:13:43 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto addressRange = TargetMemoryAddressRange{
|
|
|
|
|
command.startAddress,
|
|
|
|
|
static_cast<TargetMemoryAddress>(command.startAddress + command.buffer.size() - 1)
|
|
|
|
|
};
|
2023-09-22 17:52:28 +01:00
|
|
|
|
|
|
|
|
if (
|
2024-07-23 21:14:22 +01:00
|
|
|
!command.addressSpaceDescriptor.addressRange.contains(addressRange)
|
|
|
|
|
|| !command.memorySegmentDescriptor.addressRange.contains(addressRange)
|
2023-09-22 17:52:28 +01:00
|
|
|
) {
|
2024-07-23 21:14:22 +01:00
|
|
|
throw Exception{"Invalid address range"};
|
2023-09-22 17:52:28 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
this->writeTargetMemory(
|
|
|
|
|
command.addressSpaceDescriptor,
|
|
|
|
|
command.memorySegmentDescriptor,
|
|
|
|
|
command.startAddress,
|
|
|
|
|
command.buffer
|
2022-04-30 01:37:00 +01:00
|
|
|
);
|
2021-09-11 20:39:31 +01:00
|
|
|
|
2022-04-30 01:30:57 +01:00
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-11 23:25:15 +00:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleEraseTargetMemory(EraseTargetMemory& command) {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->eraseTargetMemory(command.addressSpaceDescriptor, command.memorySegmentDescriptor);
|
2022-12-11 23:25:15 +00:00
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-16 22:50:06 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleStepTargetExecution(StepTargetExecution&) {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->stepTarget();
|
2022-04-30 01:30:57 +01:00
|
|
|
return std::make_unique<Response>();
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2023-09-20 23:37:54 +01:00
|
|
|
std::unique_ptr<Breakpoint> TargetControllerComponent::handleSetBreakpoint(SetBreakpoint& command) {
|
|
|
|
|
using Targets::TargetBreakpoint;
|
|
|
|
|
using Services::StringService;
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto& targetBreakpointResources = this->targetDescriptor->breakpointResources;
|
2023-09-20 23:37:54 +01:00
|
|
|
if (
|
|
|
|
|
command.preferredType == Targets::TargetBreakpoint::Type::HARDWARE
|
|
|
|
|
&& this->environmentConfig.targetConfig.hardwareBreakpoints
|
2024-07-23 21:14:22 +01:00
|
|
|
&& (
|
2023-09-20 23:37:54 +01:00
|
|
|
!targetBreakpointResources.maximumHardwareBreakpoints.has_value()
|
2023-09-23 21:50:04 +01:00
|
|
|
|| this->hardwareBreakpointsByAddress.size() < (*(targetBreakpointResources.maximumHardwareBreakpoints)
|
|
|
|
|
- targetBreakpointResources.reservedHardwareBreakpoints)
|
2024-07-23 21:14:22 +01:00
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
const auto hwBreakpoint = TargetBreakpoint{command.address, TargetBreakpoint::Type::HARDWARE};
|
|
|
|
|
this->setBreakpoint(hwBreakpoint);
|
2023-09-20 23:37:54 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return std::make_unique<Breakpoint>(hwBreakpoint);
|
2023-09-20 23:37:54 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto swBreakpoint = TargetBreakpoint(command.address, TargetBreakpoint::Type::SOFTWARE);
|
|
|
|
|
this->setBreakpoint(swBreakpoint);
|
2023-09-20 23:37:54 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return std::make_unique<Breakpoint>(swBreakpoint);
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-30 22:45:46 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleRemoveBreakpoint(RemoveBreakpoint& command) {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->removeBreakpoint(command.breakpoint);
|
2022-04-30 22:45:46 +01:00
|
|
|
return std::make_unique<Response>();
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-01 18:47:57 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleSetProgramCounter(SetTargetProgramCounter& command) {
|
2022-04-30 23:10:07 +01:00
|
|
|
this->target->setProgramCounter(command.address);
|
|
|
|
|
return std::make_unique<Response>();
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleSetStackPointer(SetTargetStackPointer& command) {
|
|
|
|
|
this->target->setStackPointer(command.stackPointer);
|
|
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-16 22:50:06 +01:00
|
|
|
std::unique_ptr<TargetGpioPadStates> TargetControllerComponent::handleGetTargetGpioPadStates(
|
|
|
|
|
GetTargetGpioPadStates& command
|
2024-07-23 21:14:22 +01:00
|
|
|
) {
|
2024-08-16 22:50:06 +01:00
|
|
|
return std::make_unique<TargetGpioPadStates>(this->target->getGpioPadStates(command.padDescriptors));
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-16 22:50:06 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleSetTargetGpioPadState(SetTargetGpioPadState& command) {
|
|
|
|
|
this->target->setGpioPadState(command.padDescriptor, command.state);
|
2022-05-01 17:33:09 +01:00
|
|
|
return std::make_unique<Response>();
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
2021-11-11 19:05:24 +00:00
|
|
|
|
2022-05-01 18:01:01 +01:00
|
|
|
std::unique_ptr<TargetStackPointer> TargetControllerComponent::handleGetTargetStackPointer(
|
|
|
|
|
GetTargetStackPointer& command
|
|
|
|
|
) {
|
|
|
|
|
return std::make_unique<TargetStackPointer>(this->target->getStackPointer());
|
2021-11-11 19:05:24 +00:00
|
|
|
}
|
2022-05-01 18:44:04 +01:00
|
|
|
|
|
|
|
|
std::unique_ptr<TargetProgramCounter> TargetControllerComponent::handleGetTargetProgramCounter(
|
|
|
|
|
GetTargetProgramCounter& command
|
|
|
|
|
) {
|
|
|
|
|
return std::make_unique<TargetProgramCounter>(this->target->getProgramCounter());
|
|
|
|
|
}
|
2022-06-05 16:13:43 +01:00
|
|
|
|
2024-08-16 22:50:06 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleEnableProgrammingMode(EnableProgrammingMode&) {
|
2022-06-05 16:13:43 +01:00
|
|
|
if (!this->target->programmingModeEnabled()) {
|
|
|
|
|
this->enableProgrammingMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-16 22:50:06 +01:00
|
|
|
std::unique_ptr<Response> TargetControllerComponent::handleDisableProgrammingMode(DisableProgrammingMode&) {
|
2022-06-05 16:13:43 +01:00
|
|
|
if (this->target->programmingModeEnabled()) {
|
|
|
|
|
this->disableProgrammingMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_unique<Response>();
|
|
|
|
|
}
|
2021-11-11 19:05:24 +00:00
|
|
|
}
|