load command should not zero other data within a flash sector when data to be loaded does not cover the entire sector; it should leave it untouched
diff --git a/main.cpp b/main.cpp index 0f4c5b1..056b672 100644 --- a/main.cpp +++ b/main.cpp
@@ -134,7 +134,15 @@ bool empty() const { return from >= to; } - bool contains(uint32_t addr) const { return addr>=from && addr<to; } + + int size() const { + return to - from; + } + + bool contains(uint32_t addr) const { + return addr>=from && addr<to; + } + uint32_t clamp(uint32_t addr) const { if (addr < from) addr = from; if (addr > to) addr = to; @@ -149,7 +157,6 @@ bool intersects(const range& other) const { return !(other.from >= to || other.to < from); } - }; static void __noreturn fail(int code, string msg) { @@ -1843,32 +1850,39 @@ // new scope for progress bar { progress_bar bar("Loading into " + memory_names[type] + ": "); - uint32_t batch_size = FLASH_SECTOR_ERASE_SIZE; bool ok = true; - vector<uint8_t> file_buf; - vector<uint8_t> device_buf; - for (uint32_t base = mem_range.from; base < mem_range.to && ok; ) { - uint32_t this_batch = std::min(mem_range.to - base, batch_size); - if (type == flash) { - // we have to erase an entire page, so then fill with zeros - range aligned_range(base & ~(FLASH_SECTOR_ERASE_SIZE - 1), (base & ~(FLASH_SECTOR_ERASE_SIZE - 1)) + FLASH_SECTOR_ERASE_SIZE); - range read_range(base, base + this_batch); + vector<uint8_t> batch_buffer; + if (type == flash) { + for (uint32_t base = mem_range.from & ~(FLASH_SECTOR_ERASE_SIZE-1); base < mem_range.to && ok; base += FLASH_SECTOR_ERASE_SIZE) { + range aligned_range(base, base + FLASH_SECTOR_ERASE_SIZE); + range read_range(mem_range.from, mem_range.to); read_range.intersect(aligned_range); - file_access.read_into_vector(read_range.from, read_range.to - read_range.from, file_buf); - // zero padding up to FLASH_SECTOR_ERASE_SIZE - file_buf.insert(file_buf.begin(), read_range.from - aligned_range.from, 0); - file_buf.insert(file_buf.end(), aligned_range.to - read_range.to, 0); - assert(file_buf.size() == FLASH_SECTOR_ERASE_SIZE); + file_access.read_into_vector(read_range.from, read_range.to - read_range.from, batch_buffer); + assert(batch_buffer.size() == read_range.size()); + if (read_range.size() != FLASH_SECTOR_ERASE_SIZE) { + // we have to erase an entire page, so if not filling an entire page we read the previous contents + auto previous_contents = raw_access.read_vector<uint8_t>(aligned_range.from, FLASH_SECTOR_ERASE_SIZE); + // and insert it around the new contents + batch_buffer.insert(batch_buffer.begin(), previous_contents.begin(), + previous_contents.begin() + read_range.from - aligned_range.from); + batch_buffer.insert(batch_buffer.end(), + previous_contents.begin() + read_range.to - aligned_range.from, + previous_contents.end()); + } + assert(batch_buffer.size() == FLASH_SECTOR_ERASE_SIZE); con.exit_xip(); con.flash_erase(aligned_range.from, FLASH_SECTOR_ERASE_SIZE); - raw_access.write_vector(aligned_range.from, file_buf); - base = read_range.to; // about to add batch_size - } else { - file_access.read_into_vector(base, this_batch, file_buf); - raw_access.write_vector(base, file_buf); - base += this_batch; + raw_access.write_vector(aligned_range.from, batch_buffer); + bar.progress(read_range.to - mem_range.from, mem_range.to - mem_range.from); } - bar.progress(base - mem_range.from, mem_range.to - mem_range.from); + } else { + uint32_t batch_size = FLASH_SECTOR_ERASE_SIZE; + for (uint32_t base = mem_range.from; base < mem_range.to && ok; base += batch_size) { + uint32_t this_batch = std::min(mem_range.to - base, batch_size); + file_access.read_into_vector(base, this_batch, batch_buffer); + raw_access.write_vector(base, batch_buffer); + bar.progress(base + this_batch - mem_range.from, mem_range.to - mem_range.from); + } } } if (settings.load.verify) {