#include "WriteTargetMemory.hpp" #include #include #include #include "src/Exceptions/Exception.hpp" using Services::TargetControllerService; void WriteTargetMemory::run(TargetControllerService& targetControllerService) { using Targets::TargetMemorySize; if (!this->memoryDescriptor.access.writeableDuringDebugSession) { throw Exceptions::Exception("Invalid request - cannot write to this memory type during a debug session."); } /* * 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 maxBlockSize = std::max( TargetMemorySize(256), this->memoryDescriptor.pageSize.value_or(TargetMemorySize(0)) ); const TargetMemorySize totalBytesToWrite = std::accumulate( this->blocks.begin(), this->blocks.end(), TargetMemorySize{0}, [] (TargetMemorySize bytes, const Block& block) { return bytes + block.data.size(); } ); TargetMemorySize totalBytesWritten = 0; for (const auto& block : this->blocks) { const auto totalBytes = block.data.size(); TargetMemorySize bytesWritten = 0; 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(totalBytesWritten); }