diff --git a/src/Insight/InsightWorker/Tasks/WriteTargetMemory.cpp b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.cpp index e3a441d6..e3580808 100644 --- a/src/Insight/InsightWorker/Tasks/WriteTargetMemory.cpp +++ b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace Bloom { @@ -17,36 +18,51 @@ namespace Bloom * 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( + const auto maxBlockSize = std::max( TargetMemorySize(256), memoryDescriptor.pageSize.value_or(TargetMemorySize(0)) ); - const auto totalBytes = this->data.size(); - TargetMemorySize bytesWritten = 0; + const TargetMemorySize totalBytesToWrite = std::accumulate( + this->blocks.begin(), + this->blocks.end(), + TargetMemorySize{0}, + [] (TargetMemorySize bytes, const Block& block) { + return bytes + block.data.size(); + } + ); - while (bytesWritten < totalBytes) { - const auto bytesToWrite = std::min( - blockSize, - static_cast(totalBytes - bytesWritten) - ); + TargetMemorySize totalBytesWritten = 0; - targetControllerService.writeMemory( - this->memoryDescriptor.type, - this->startAddress + bytesWritten, - Targets::TargetMemoryBuffer( - this->data.begin() + bytesWritten, - this->data.begin() + bytesWritten + bytesToWrite - ) - ); + for (const auto& block : this->blocks) { + const auto totalBytes = block.data.size(); - bytesWritten += bytesToWrite; + TargetMemorySize bytesWritten = 0; - this->setProgressPercentage(static_cast( - (static_cast(bytesWritten) + 1) / (static_cast(totalBytes) / 100) - )); + while (bytesWritten < totalBytes) { + const auto bytesToWrite = std::min( + maxBlockSize, + static_cast(totalBytes - bytesWritten) + ); + + targetControllerService.writeMemory( + this->memoryDescriptor.type, + block.startAddress + bytesWritten, + Targets::TargetMemoryBuffer( + block.data.begin() + bytesWritten, + block.data.begin() + bytesWritten + bytesToWrite + ) + ); + + bytesWritten += bytesToWrite; + totalBytesWritten += bytesToWrite; + + this->setProgressPercentage(static_cast( + (static_cast(totalBytesWritten) + 1) / (static_cast(totalBytesToWrite) / 100) + )); + } } - emit this->targetMemoryWritten(bytesWritten); + emit this->targetMemoryWritten(totalBytesWritten); } } diff --git a/src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp index b943575c..14318f0d 100644 --- a/src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp +++ b/src/Insight/InsightWorker/Tasks/WriteTargetMemory.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "InsightWorkerTask.hpp" #include "src/Targets/TargetMemory.hpp" @@ -11,14 +13,37 @@ namespace Bloom Q_OBJECT public: + /* + * A Block is just a block of contiguous data to write. A single WriteTargetMemory task can write multiple + * blocks to a particular memory. + */ + struct Block { + Targets::TargetMemoryAddress startAddress; + const Targets::TargetMemoryBuffer data; + + Block( + Targets::TargetMemoryAddress startAddress, + const Targets::TargetMemoryBuffer& data + ) + : startAddress(startAddress) + , data(data) + {} + }; + + WriteTargetMemory( + const Targets::TargetMemoryDescriptor& memoryDescriptor, + std::vector&& blocks + ) + : memoryDescriptor(memoryDescriptor) + , blocks(std::move(blocks)) + {} + WriteTargetMemory( const Targets::TargetMemoryDescriptor& memoryDescriptor, Targets::TargetMemoryAddress startAddress, const Targets::TargetMemoryBuffer& data ) - : memoryDescriptor(memoryDescriptor) - , startAddress(startAddress) - , data(data) + : WriteTargetMemory(memoryDescriptor, std::vector({{startAddress, data}})) {} QString brief() const override { @@ -31,7 +56,7 @@ namespace Bloom return TaskGroups({ TaskGroup::USES_TARGET_CONTROLLER, }); - }; + } signals: void targetMemoryWritten(Targets::TargetMemorySize bytesWritten); @@ -41,7 +66,6 @@ namespace Bloom private: Targets::TargetMemoryDescriptor memoryDescriptor; - Targets::TargetMemoryAddress startAddress; - Targets::TargetMemoryBuffer data; + std::vector blocks; }; }