Hi list,

I have subscribed in order to report/discuss an issue with avrdude, and one 
working solution.  Apologies if this is not the preferred way.  Also I am 
aware it is possible I may have mis-diagnosed.

In brief:
When programming the ATMega2560 using an stk500 (v1) compatible ISP, avrdude 
doesn't set the extended address byte in the target device.  As a result it 
cannot be certain whether it is programming above or below the 128K bytes 
threshold.  One manifestation of this is reports of verify errors at 0x1e000 
when programming the Mega2560 bootloader using the ArduinoISP.  A patch that 
resolves this is attached - modifying the stk500 code to set the extended 
byte when necessary.

More details:
The stk500 v1 protocol only allows 2 bytes for the (word) address, so with 
this type of programmer, flash >128K has to be handled specially (within 
avrdude).  Since stk500 also does not include a dedicated means to set the 
extended addr byte, it has to be done using cmd-universal direct to the 
target SPI.

The stk500 programming process has been studied in detail with a logic 
analyser, capturing Tx, Rx and all SPI signals for the whole 90s of a 
bootloader programming cycle on the Mega2560.  Nowhere is the ext-addr-byte 
set.  When the whole of flash is read for the verify, whichever half is 
presently set in the target device is actually read through twice. On my test 
unit, this was always the upper half, so the bootloader appears to 
avrdude-read 'ghosted' at the top of the lower half of flash as well as at 
the top of the upper half.  This gives the verify error.  It is in this case 
not possible to read or write the real lower half of flash.

At present I have continued to use avrdude 5.11.1 as 6.0.1 doesn't build 
(separate issue) but I don't see any indication that the ext addr has been 
identified and resolved in the later release - please correct me if it has.

The patch here for stk500.c adds an extended address byte cmd for any device 
where the flash size >128K, and sets it initially and when a 128K boundary is 
crossed.  With these changes the bootloader program completes without errors, 
and it is clear from the analyser that the correct memory locations are now 
being accessed.  This is not necessarily a 'final' patch, but should apply to 
6.01 cleanly.

This could be fixed in other different ways - and may be better pushed up the 
layers in avrdude into avr.c; I am posting for your comments, awareness etc.  
If there is important info missed, ask and I will try to respond.

Hope this is useful,

Regards

Alan
--- stk500-orig.c	2011-09-15 15:37:04.000000000 +0100
+++ stk500.c	2013-12-06 22:45:30.000000000 +0000
@@ -689,14 +689,31 @@
 }
 
 
-static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr)
+static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr, char ext_addr)
 {
   unsigned char buf[16];
   int tries;
+  static unsigned char prev_ext_byte = 0xff; /* Ensures it is set first time */
+  unsigned char ext_byte;
 
   tries = 0;
  retry:
   tries++;
+
+  /* To support flash > 64K words the correct Extended Address Byte has to be programmed. Use cmnd-universal */
+  if (ext_addr) {
+    ext_byte = (addr >> 16) & 0xff;
+    if (ext_byte != prev_ext_byte) {
+      /* 'Load Extended Address Byte' 0x4d,0x00 see Atmel datasheets, 'Serial Programming Instructions' */
+      buf[0] = 0x4d;
+      buf[1] = 0x00;
+      buf[2] = ext_byte;
+      buf[3] = 0x00;
+      stk500_cmd(pgm, buf, buf);
+      prev_ext_byte = ext_byte;
+    }
+  }
+
   buf[0] = Cmnd_STK_LOAD_ADDRESS;
   buf[1] = addr & 0xff;
   buf[2] = (addr >> 8) & 0xff;
@@ -751,6 +768,7 @@
   unsigned int n;
   unsigned int i;
   int flash;
+  char use_ext_addr = 0;
 
   if (page_size == 0) {
     // MIB510 uses page size of 256 bytes
@@ -765,6 +783,9 @@
   if (strcmp(m->desc, "flash") == 0) {
     memtype = 'F';
     flash = 1;
+    /* To support flash > 128K (64K words) use an Extended Address Byte */
+    if (m->size > 131072)
+      use_ext_addr = 1;
   }
   else if (strcmp(m->desc, "eeprom") == 0) {
     memtype = 'E';
@@ -822,7 +843,7 @@
     tries = 0;
   retry:
     tries++;
-    stk500_loadaddr(pgm, addr/a_div);
+    stk500_loadaddr(pgm, addr/a_div, use_ext_addr);
 
     /* build command block and avoid multiple send commands as it leads to a crash
         of the silabs usb serial driver on mac os x */
@@ -895,9 +916,13 @@
   int tries;
   unsigned int n;
   int block_size;
+  char use_ext_addr = 0;
 
   if (strcmp(m->desc, "flash") == 0) {
     memtype = 'F';
+    /* To support flash > 128K (64K words) use an Extended Address Byte */
+    if (m->size > 131072)
+      use_ext_addr = 1;
   }
   else if (strcmp(m->desc, "eeprom") == 0) {
     memtype = 'E';
@@ -939,7 +964,7 @@
     tries = 0;
   retry:
     tries++;
-    stk500_loadaddr(pgm, addr/a_div);
+    stk500_loadaddr(pgm, addr/a_div, use_ext_addr);
     buf[0] = Cmnd_STK_READ_PAGE;
     buf[1] = (block_size >> 8) & 0xff;
     buf[2] = block_size & 0xff;
_______________________________________________
avrdude-dev mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/avrdude-dev

Reply via email to