Improved performance of driver-side masked memory reads, within the AVR8 EDBG driver

This commit is contained in:
Nav
2021-10-21 19:28:31 +01:00
parent 901b3a0fe5
commit 086d5e45b9
2 changed files with 46 additions and 40 deletions

View File

@@ -1166,9 +1166,9 @@ void EdbgAvr8Interface::clearEvents() {
TargetMemoryBuffer EdbgAvr8Interface::readMemory(
Avr8MemoryType type,
std::uint32_t address,
std::uint32_t startAddress,
std::uint32_t bytes,
std::set<std::uint32_t> excludedAddresses
const std::set<std::uint32_t>& excludedAddresses
) {
if (!excludedAddresses.empty() && this->avoidMaskedMemoryRead) {
/*
@@ -1180,33 +1180,39 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
* of the masked read memory EDBG command.
*/
auto output = TargetMemoryBuffer();
auto segmentStartAddress = address;
output.reserve(bytes);
for (std::uint32_t i = 0; i < bytes; i++) {
const auto byteAddress = address + i;
auto segmentStartAddress = startAddress;
const auto endAddress = startAddress + bytes - 1;
if (excludedAddresses.contains(byteAddress)) {
auto segmentBuffer = this->readMemory(
type,
segmentStartAddress,
(byteAddress - segmentStartAddress)
);
output.insert(output.end(), segmentBuffer.begin(), segmentBuffer.end());
output.emplace_back(0x00);
segmentStartAddress = byteAddress + 1;
} else if (i == (bytes - 1)) {
// Read final segment
auto segmentBuffer = this->readMemory(
type,
segmentStartAddress,
(byteAddress - segmentStartAddress + 1)
);
output.insert(output.end(), segmentBuffer.begin(), segmentBuffer.end());
for (const auto excludedAddress : excludedAddresses) {
if (excludedAddress < startAddress || excludedAddress > endAddress) {
// This excluded address is outside of the range from which we are reading, so it can be ignored.
continue;
}
auto segmentBuffer = this->readMemory(
type,
segmentStartAddress,
(excludedAddress - segmentStartAddress)
);
output.insert(output.end(), segmentBuffer.begin(), segmentBuffer.end());
output.emplace_back(0x00);
segmentStartAddress = excludedAddress + 1;
}
// Read final segment
const auto finalReadBytes = (endAddress - segmentStartAddress) + 1;
if (finalReadBytes > 0) {
auto segmentBuffer = this->readMemory(
type,
segmentStartAddress,
finalReadBytes
);
output.insert(output.end(), segmentBuffer.begin(), segmentBuffer.end());
}
return output;
@@ -1220,13 +1226,13 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
// Flash reads must be done in pages
auto pageSize = this->targetParameters.flashPageSize.value();
if ((bytes % pageSize) != 0 || (address % pageSize) != 0) {
if ((bytes % pageSize) != 0 || (startAddress % pageSize) != 0) {
/*
* The number of bytes to read and/or the start address are not aligned.
*
* Align both and call this function again.
*/
auto alignedAddress = address;
auto alignedAddress = startAddress;
auto alignedBytesToRead = bytes;
if ((bytes % pageSize) != 0) {
@@ -1237,9 +1243,9 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
alignedBytesToRead = (pagesRequired * pageSize);
}
if ((address % pageSize) != 0) {
if ((startAddress % pageSize) != 0) {
alignedAddress = static_cast<std::uint32_t>(std::floor(
static_cast<float>(address) / static_cast<float>(pageSize)
static_cast<float>(startAddress) / static_cast<float>(pageSize)
) * pageSize);
/*
@@ -1276,9 +1282,9 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
* align them for us, but it will result in an unnecessary recursion, so we'll just align the
* additional bytes here.
*/
if ((address - alignedAddress) > (alignedBytesToRead - bytes)) {
if ((startAddress - alignedAddress) > (alignedBytesToRead - bytes)) {
alignedBytesToRead += static_cast<std::uint32_t>(std::ceil(
static_cast<float>(address - alignedAddress) / static_cast<float>(pageSize)
static_cast<float>(startAddress - alignedAddress) / static_cast<float>(pageSize)
)) * pageSize;
}
}
@@ -1289,8 +1295,8 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
*/
auto memoryBuffer = this->readMemory(type, alignedAddress, alignedBytesToRead, excludedAddresses);
return TargetMemoryBuffer(
memoryBuffer.begin() + (address - alignedAddress),
memoryBuffer.begin() + (address - alignedAddress) + bytes
memoryBuffer.begin() + (startAddress - alignedAddress),
memoryBuffer.begin() + (startAddress - alignedAddress) + bytes
);
}
@@ -1302,7 +1308,7 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
TargetMemoryBuffer memoryBuffer;
for (auto i = 1; i <= pagesRequired; i++) {
auto pageBuffer = this->readMemory(type, address + (pageSize * i), pageSize);
auto pageBuffer = this->readMemory(type, startAddress + (pageSize * i), pageSize);
memoryBuffer.insert(memoryBuffer.end(), pageBuffer.begin(), pageBuffer.end());
}
@@ -1339,7 +1345,7 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
(singlePacketSize * 2) : bytes - output.size());
auto data = this->readMemory(
type,
static_cast<std::uint32_t>(address + output.size()),
static_cast<std::uint32_t>(startAddress + output.size()),
bytesToRead,
excludedAddresses
);
@@ -1352,7 +1358,7 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
auto commandFrame = CommandFrames::Avr8Generic::ReadMemory();
commandFrame.setType(type);
commandFrame.setAddress(address);
commandFrame.setAddress(startAddress);
commandFrame.setBytes(bytes);
commandFrame.setExcludedAddresses(excludedAddresses);

View File

@@ -560,7 +560,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
* @param type
* The type of memory to access (Flash, EEPROM, SRAM, etc). See protocol documentation for more on this.
*
* @param address
* @param startAddress
* The start address (byte address)
*
* @param bytes
@@ -574,9 +574,9 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
*/
Targets::TargetMemoryBuffer readMemory(
Avr8MemoryType type,
std::uint32_t address,
std::uint32_t startAddress,
std::uint32_t bytes,
std::set<std::uint32_t> excludedAddresses = {}
const std::set<std::uint32_t>& excludedAddresses = {}
);
/**