diff --git a/src/Insight/CMakeLists.txt b/src/Insight/CMakeLists.txt index 37612ccc..ed895837 100755 --- a/src/Insight/CMakeLists.txt +++ b/src/Insight/CMakeLists.txt @@ -31,6 +31,7 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/RefreshTargetPinStates.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/SetTargetPinState.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ReadTargetMemory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/WriteTargetMemory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ReadStackPointer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ReadProgramCounter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/GetTargetState.cpp diff --git a/src/Insight/InsightWorker/Tasks/WriteTargetMemory.cpp b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.cpp new file mode 100644 index 00000000..e3a441d6 --- /dev/null +++ b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.cpp @@ -0,0 +1,52 @@ +#include "WriteTargetMemory.hpp" + +#include +#include + +namespace Bloom +{ + using Services::TargetControllerService; + + void WriteTargetMemory::run(TargetControllerService& targetControllerService) { + using Targets::TargetMemorySize; + + /* + * To prevent locking up the TargetController for too long, we split the write operation into numerous + * operations. + * + * This allows the TargetController to service other commands in-between reads, reducing the likelihood of + * command timeouts when we're writing lots of data. + */ + const auto blockSize = std::max( + TargetMemorySize(256), + memoryDescriptor.pageSize.value_or(TargetMemorySize(0)) + ); + const auto totalBytes = this->data.size(); + + TargetMemorySize bytesWritten = 0; + + while (bytesWritten < totalBytes) { + const auto bytesToWrite = std::min( + blockSize, + static_cast(totalBytes - bytesWritten) + ); + + targetControllerService.writeMemory( + this->memoryDescriptor.type, + this->startAddress + bytesWritten, + Targets::TargetMemoryBuffer( + this->data.begin() + bytesWritten, + this->data.begin() + bytesWritten + bytesToWrite + ) + ); + + bytesWritten += bytesToWrite; + + this->setProgressPercentage(static_cast( + (static_cast(bytesWritten) + 1) / (static_cast(totalBytes) / 100) + )); + } + + emit this->targetMemoryWritten(bytesWritten); + } +} diff --git a/src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp new file mode 100644 index 00000000..b943575c --- /dev/null +++ b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "InsightWorkerTask.hpp" + +#include "src/Targets/TargetMemory.hpp" + +namespace Bloom +{ + class WriteTargetMemory: public InsightWorkerTask + { + Q_OBJECT + + public: + WriteTargetMemory( + const Targets::TargetMemoryDescriptor& memoryDescriptor, + Targets::TargetMemoryAddress startAddress, + const Targets::TargetMemoryBuffer& data + ) + : memoryDescriptor(memoryDescriptor) + , startAddress(startAddress) + , data(data) + {} + + QString brief() const override { + return + "Writing to target " + + QString(this->memoryDescriptor.type == Targets::TargetMemoryType::EEPROM ? "EEPROM" : "RAM"); + } + + TaskGroups taskGroups() const override { + return TaskGroups({ + TaskGroup::USES_TARGET_CONTROLLER, + }); + }; + + signals: + void targetMemoryWritten(Targets::TargetMemorySize bytesWritten); + + protected: + void run(Services::TargetControllerService& targetControllerService) override; + + private: + Targets::TargetMemoryDescriptor memoryDescriptor; + Targets::TargetMemoryAddress startAddress; + Targets::TargetMemoryBuffer data; + }; +}