From ff8f519a34ed4e167be442ca4abeac6f11cccdca Mon Sep 17 00:00:00 2001
From: Stefan Rueger <stefan.rueger@urclocks.com>
Date: Sun, 10 Jul 2022 23:25:31 +0100
Subject: [PATCH] Fix PICKit2 ATmega2560 flash paged flash read

The paged read in pickit2.c has two errors:
  - It drops load extended address commands unless a paged read happens at a
    64k byte boundary; this is invalid when reading files with holes
  - It wrongly assumed that flash memory is byte addressed

The fix is to carry out a load extended address command, if needed, at the
beginning of each paged flash read with the correct word address. Although the
pickit2_paged_load() has independent parameters page_size, addr and n_bytes,
AVRDUDE only ever calls paged read/write functions with page_size and n_bytes
both set to mem->page_size and addr aligned with a page boundary. Therefore, it
is sufficient to set the load extended address at the beginning of each page
read.
---
 src/pickit2.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/src/pickit2.c b/src/pickit2.c
index 9e4be94c..ac3781f5 100644
--- a/src/pickit2.c
+++ b/src/pickit2.c
@@ -491,18 +491,15 @@ static int  pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
 
     pgm->pgm_led(pgm, ON);
 
+    if (lext) {
+       memset(cmd, 0, sizeof(cmd));
+       avr_set_bits(lext, cmd);
+       avr_set_addr(lext, cmd, addr/2);
+       pgm->cmd(pgm, cmd, res);
+    }
+
     for (addr_base = addr; addr_base < max_addr; )
     {
-        if ((addr_base == 0 || (addr_base % /*ext_address_boundary*/ 65536) == 0)
-                && lext != NULL)
-        {
-            memset(cmd, 0, sizeof(cmd));
-
-            avr_set_bits(lext, cmd);
-            avr_set_addr(lext, cmd, addr_base);
-            pgm->cmd(pgm, cmd, res);
-        }
-
         // bytes to send in the next packet -- not necessary as pickit2_spi() handles breaking up
         // the data into packets -- but we need to keep transfers frequent so that we can update the
         // status indicator bar