avrdudes / avrdude

AVRDUDE is a utility to program AVR microcontrollers
GNU General Public License v2.0
730 stars 136 forks source link

Arduino ATmega2560 stk500v2 (Wiring) bootloader issue #1379

Closed mcuee closed 1 year ago

mcuee commented 1 year ago

Reference:

This is most likely not an avrdude issue but a Arduino STK500 V2 bootloader firmware issue.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git -c wiring -P COM11 -p m2560 -t
avrdude_git: AVR device initialized and ready to accept instructions
avrdude_git: device signature = 0x1e9801 (probably m2560)
avrdude> dump flash 0x400 0x10
Reading | ################################################## | 100% 0.11 s
00400  00 00 00 00 00 00 ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.02 s
avrdude> flush
avrdude_git: synching cache to device ...
Reading | ################################################## | 100% 35.30 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude_git error: command failed
avrdude_git error: chip erase failed
avrdude> quit
avrdude_git: synching cache to device ...
Reading | ################################################## | 100% 0.01 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude_git error: command failed
avrdude_git error: chip erase failed

avrdude_git done.  Thank you.
mcuee commented 1 year ago

Bootloader FW source codes: https://github.com/MCUdude/MegaCore/tree/master/avr/bootloaders/stk500v2

It is a minor fix of the original Arduino version which has EEPROM bug. https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/stk500v2

mcuee commented 1 year ago

BTW, I have some HW stability issues with this bootloader before with one paticular board. But this board seems to work normally under Arduino, so the issue may be different. It seems to be limited to terminal mode.

CLI mode works fine.

$ ./avrdude -c wiring -P COM11 -p m2560 -D -U entest.hex
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude: reading input file entest.hex for flash
         with 512 bytes in 1 section within [0, 0x1ff]
         using 2 pages and 0 pad bytes
avrdude: writing 512 bytes flash ...
Writing | ################################################## | 100% 0.08 s
avrdude: 512 bytes of flash written
avrdude: verifying flash memory against entest.hex
Reading | ################################################## | 100% 0.07 s
avrdude: 512 bytes of flash verified

avrdude done.  Thank you.
mcuee commented 1 year ago

I was worrying about timeout in terminal mode but using pipeline does not help.

$ echo "dump flash 0x400 0x10" | ./avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> dump flash 0x400 0x10
Reading | ################################################## | 100% 0.11 s
00400  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>
avrdude done.  Thank you.

$ echo "write flash 0x400 0xaa 0x55 0xaa 0x55" | ./avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Writing | ################################################## | 100% 0.07 s

avrdude done.  Thank you.

$ echo "dump flash 0x400 0x10" | ./avrdude -c wiring -P COM11 -p m2560 -D -qqt
avrdude> dump flash 0x400 0x10
00400  aa 55 aa 55 ff ff ff ff  ff ff ff ff ff ff ff ff  |.U.U............|
avrdude>

$ echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | ./avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Reading | ################################################## | 100% 34.77 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude error: command failed
avrdude error: chip erase failed

avrdude done.  Thank you.

$ echo "dump flash 0x400 0x10" | ./avrdude -c wiring -P COM11 -p m2560 -D -qqt
avrdude> dump flash 0x400 0x10
00400  00 00 00 00 ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>

$ echo "dump flash 0x400 0x10" | ./avrdude -c wiring -P COM11 -p m2560 -D -qqt
avrdude> dump flash 0x400 0x10
00400  00 00 00 00 ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>

$ echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | ./avrdude -c wiring -P COM11 -p m2560 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Reading | ################################################## | 100% 34.83 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude error: command failed
avrdude error: chip erase failed

avrdude done.  Thank you.

$ echo "dump flash 0x400 0x10" | ./avrdude -c wiring -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  00 00 00 00 ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>
mcuee commented 1 year ago

I think this is a limitation of the Arduino STK500v2 bootloader limitation (no support of page erase)

No issues with urboot bootloader.

$ echo "dump flash 0x400 0x10" | ./avrdude -c urclock -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>

$ echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | ./avrdude -c urclock -P COM11 -p m2560 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.07 s
avrdude> avrdude: synching cache to device ...
Writing | ################################################## | 100% 0.06 s

avrdude done.  Thank you.

$ echo "write flash 0x400 0xaa 0x55 0xaa 0x55" | ./avrdude -c urclock -P COM11 -p m2560 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.07 s
avrdude> avrdude: synching cache to device ... done

avrdude done.  Thank you.

$ echo "dump flash 0x400 0x10" | ./avrdude -c urclock -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  aa 55 aa 55 ff ff ff ff  ff ff ff ff ff ff ff ff  |.U.U............|
avrdude>
mcuee commented 1 year ago

No issues using the Optiboot bootloader from MegaCore either.

$ echo "dump flash 0x400 0x10" | ./avrdude -c arduino -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>

$ echo "write flash 0x400 0xaa 0x55 0xaa 0x55" | ./avrdude -c arduino -P COM11 -p m2560 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.07 s
avrdude> avrdude: synching cache to device ...
Writing | ################################################## | 100% 0.06 s

avrdude done.  Thank you.

$ echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | ./avrdude -c arduino -P COM11 -p m2560 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ... done

avrdude done.  Thank you.

$ echo "dump flash 0x400 0x10" | ./avrdude -c arduino -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  55 aa 55 aa ff ff ff ff  ff ff ff ff ff ff ff ff  |U.U.............|
avrdude>
mcuee commented 1 year ago

As mentioned in the comments of PR #1376, that PR does not help for this issue.

$ echo "dump flash 0x400 0x10" | ./avrdude -c arduino -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  55 aa 55 aa ff ff ff ff  ff ff ff ff ff ff ff ff  |U.U.............|
avrdude>

$ echo "dump flash 0x400 0x10" | ./avrdude_pr1376 -c wiring -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>

$ echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | ./avrdude_pr1376 -c wiring -P COM11 -p m2560 -t
avrdude_pr1376: AVR device initialized and ready to accept instructions
avrdude_pr1376: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude_pr1376: synching cache to device ...
Writing | ################################################## | 100% 0.07 s

avrdude_pr1376 done.  Thank you.

$ echo "dump flash 0x400 0x10" | ./avrdude_pr1376 -c wiring -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  55 aa 55 aa ff ff ff ff  ff ff ff ff ff ff ff ff  |U.U.............|
avrdude>
xiaof@LAPTOP-913SIMUD MINGW64 /c/work/avr/avrdude_test/avrdude_bin

avrdude_pr1376: AVR device initialized and ready to accept instructions
avrdude_pr1376: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude_pr1376: synching cache to device ...
Reading | ################################################## | 100% 34.86 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude_pr1376 error: command failed
avrdude_pr1376 error: chip erase failed

avrdude_pr1376 done.  Thank you.

$ echo "dump flash 0x400 0x10" | ./avrdude_pr1376 -c wiring -P COM11 -p m2560 -qqt
avrdude> dump flash 0x400 0x10
00400  00 00 00 00 ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
avrdude>
mcuee commented 1 year ago

I will conclude this to be a limitation of the Arduino STK500v2 bootloader for ATmega2560.

mcuee commented 1 year ago

@stefanrueger

I was wrong previously in #1337. Therefore, I would like to double check with you if I am right or wrong here. I think that this is an Arduino STK500 V2 bootloader limitation and not an avrdude issue. Thanks.

stefanrueger commented 1 year ago

I think you are right, @mcuee.

But yes, if you have the source of the wiring bootloader it will become obvious what it does when asked to do a CE.

mcuee commented 1 year ago

But yes, if you have the source of the wiring bootloader it will become obvious what it does when asked to do a CE.

@stefanrueger

The bootloader code is here. https://github.com/MCUdude/MegaCore/tree/master/avr/bootloaders/stk500v2

It is a minor EEPROM fix of the original Arduino source code. https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/stk500v2

It does not support CE.

https://github.com/MCUdude/MegaCore/blob/master/avr/bootloaders/stk500v2/stk500boot.c#L974-L979

                case CMD_CHIP_ERASE_ISP:
                    eraseAddress    =   0;
                    msgLength       =   2;
                //  msgBuffer[1]    =   STATUS_CMD_OK;
                    msgBuffer[1]    =   STATUS_CMD_FAILED;  //* isue 543, return FAILED instead of OK
                    break;
mcuee commented 1 year ago

@stefanrueger

I am not sure if we can fix the bootloader or provide a work-around in the -c wiring programmer. Please help to check if you got a chance.

Or we can just leave this as it is if you feel it is not worth the time to fix a very old bootloader.

Other than the EEPROM read issue, there are also other issues reported in Arduino. https://github.com/arduino/ArduinoCore-avr/issues?q=is%3Aissue+is%3Aopen+stk500v2

And the original repo which is the base for Arduino stk500v2 bootloader. https://github.com/msproul/Arduino-stk500v2-bootloader/issues

stefanrueger commented 1 year ago

provide a work-around

One work-around is to use -D asking AVRDUDE to not do a CE

mcuee commented 1 year ago

provide a work-around

One work-around is to use -D asking AVRDUDE to not do a CE

Yes -D is used already in some of the tests.

$ echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | ./avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Reading | ################################################## | 100% 34.77 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude error: command failed
avrdude error: chip erase failed

avrdude done.  Thank you.

In fact, -c wiring rejects -e command.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude.exe -c wiring -P COM11 -qqp m2560 -e
avrdude error: command failed
mcuee commented 1 year ago

New tests with a refresh bootloader, using -D.

PS C:\work\avr\avrdude_test\avrdude_bin> echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | .\avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Writing | ################################################## | 100% 0.07 s

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> echo "write flash 0x400 0xaa 0x55 0xaa 0x55" | .\avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Reading | ################################################## | 100% 35.47 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude error: command failed
avrdude error: chip erase failed
avrdude: synching cache to device ...
Reading | ################################################## | 100% 0.01 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude error: command failed
avrdude error: chip erase failed

avrdude done.  Thank you.
mcuee commented 1 year ago

BTW, the following fix does not help.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c avrispmkii -p m2560 -U .\goodHexFiles_stk500boot_v2_mega2560.hex
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude: Note: flash memory has been specified, an erase cycle will be performed.
         To disable this feature, specify the -D option.
avrdude: erasing chip

avrdude: processing -U flash:w:.\goodHexFiles_stk500boot_v2_mega2560.hex:i
avrdude: reading input file .\goodHexFiles_stk500boot_v2_mega2560.hex for flash
         with 6186 bytes in 1 section within [0x3e000, 0x3f829]
         using 25 pages and 214 pad bytes
avrdude: writing 6186 bytes flash ...
Writing | ################################################## | 100% 0.15 s
avrdude: 6186 bytes of flash written
avrdude: verifying flash memory against .\goodHexFiles_stk500boot_v2_mega2560.hex
Reading | ################################################## | 100% 0.07 s
avrdude: 6186 bytes of flash verified

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> echo "write flash 0x400 0xaa 0x55 0xaa 0x55" | .\avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.07 s
avrdude> avrdude: synching cache to device ...
Writing | ################################################## | 100% 0.07 s

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | .\avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Reading | ################################################## | 100% 35.42 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude error: command failed
avrdude error: chip erase failed
avrdude: synching cache to device ...
Reading | ################################################## | 100% 0.01 s
Erasing | -------------------------------------------------- | 0% 0.01 s
avrdude error: command failed
avrdude error: chip erase failed

avrdude done.  Thank you.
stefanrueger commented 1 year ago

Ah, I see.

I do wonder why the terminal cache decides it needs to do a read/CE/write cycle. That is not necessary if the bootloader erases the page before writing it. The code you pointed me to, @mcuee, has (on my reading) a few peculiarities

This code https://github.com/MCUdude/MegaCore/blob/8b5f16e1da21b6c3014d9accd3bb801a07ed1938/avr/bootloaders/stk500v2/stk500boot.c#L1003-L1025

better be

    // Write only to main section (bootloader protection)
    if(tempAddress < APP_END) {
      boot_page_erase(tempAddress); // Erase page before writing
      boot_spm_busy_wait();

      do {
        lowByte  = *p++;
        highByte = *p++;
        data     = (highByte << 8) | lowByte;
        boot_page_fill(address, data);
        address += 2;
        size    -= 2;
      } while (size);

      boot_page_write(tempaddress);
      boot_spm_busy_wait();
      boot_rww_enable();
    }

With above (untested!) suggested code the eraseAddress can be ditched (if kept there will be a compiler warning). There are a few more traps lurking in the original code: If a malicious uploader asks to program an odd size the code loops endlessly; defuse this by making size an int and condition on do { ... } while(size > 0), but anyhow sth to the effect of above would improve the bootloader.

That are the kind of problems that are really hard to work-around in AVRDUDE, and I would prefer people fix their wiring bootloader.

mcuee commented 1 year ago

That are the kind of problems that are really hard to work-around in AVRDUDE, and I would prefer people fix their wiring bootloader.

@stefanrueger

I agree with you. I will try your suggestions and incorporate some of the changes mentioned in other places to see if I can get the wiring bootloader working better.

For Arduino people, they probably do not care about this issue. And they do not really care about EEPROM read/write using avrdude either. So I guess they will not fix it.

But @MCUdude may be interested to fix the bootloader in MegaCore.

mcuee commented 1 year ago

@MCUdude

You may be interested to know about this issue and some other issues about the wiring bootloader.

I have not checked the details of the other issues reported here. https://github.com/msproul/Arduino-stk500v2-bootloader/issues

mcuee commented 1 year ago

@stefanrueger

With your fix, it seems to work now.

I have also incorporated the changes from the following two places.

$ diff -u stk500boot_org.c stk500boot.c
--- stk500boot_org.c    2022-10-15 16:30:43.793333800 +0800
+++ stk500boot.c        2023-06-10 15:32:29.859681800 +0800
@@ -268,12 +268,12 @@
 //#define BOOTSIZE 1024
 #if FLASHEND > 0x0F000
        #define BOOTSIZE 8192
+       #define APP_END  ((FLASHEND - BOOTSIZE) + 1)
 #else
        #define BOOTSIZE 2048
+       #define APP_END  (FLASHEND - (2*BOOTSIZE) + 1)
 #endif

-#define APP_END  (FLASHEND -(2*BOOTSIZE) + 1)
-
 /*
  * Signature bytes are not available in avr-gcc io_xxx.h
  */
@@ -532,7 +532,7 @@
 int main(void)
 {
        address_t               address                 =       0;
-       address_t               eraseAddress    =       0;
+//     address_t               eraseAddress    =       0;
        unsigned char   msgParseState;
        unsigned int    ii                              =       0;
        unsigned char   checksum                =       0;
@@ -972,7 +972,7 @@
                                        break;
        #endif
                                case CMD_CHIP_ERASE_ISP:
-                                       eraseAddress    =       0;
+//                                     eraseAddress    =       0;
                                        msgLength               =       2;
                                //      msgBuffer[1]    =       STATUS_CMD_OK;
                                        msgBuffer[1]    =       STATUS_CMD_FAILED;      //*     isue 543, return FAILED instead of OK
@@ -1000,29 +1000,24 @@

                                                if ( msgBuffer[0] == CMD_PROGRAM_FLASH_ISP )
                                                {
-                                                       // erase only main section (bootloader protection)
-                                                       if (eraseAddress < APP_END )
-                                                       {
-                                                               boot_page_erase(eraseAddress);  // Perform page erase
-                                                               boot_spm_busy_wait();           // Wait until the memory is erased.
-                                                               eraseAddress += SPM_PAGESIZE;   // point to next page to be erase
+                                                       // Write only to main section (bootloader protection)
+                                                       if(tempaddress < APP_END) {
+                                                         boot_page_erase(tempaddress); // Erase page before writing
+                                                         boot_spm_busy_wait();
+
+                                                         do {
+                                                               lowByte  = *p++;
+                                                               highByte = *p++;
+                                                               data     = (highByte << 8) | lowByte;
+                                                               boot_page_fill(address, data);
+                                                               address += 2;
+                                                               size    -= 2;
+                                                         } while (size);
+
+                                                         boot_page_write(tempaddress);
+                                                         boot_spm_busy_wait();
+                                                         boot_rww_enable();
                                                        }
-
-                                                       /* Write FLASH */
-                                                       do {
-                                                               lowByte         =       *p++;
-                                                               highByte        =       *p++;
-
-                                                               data            =       (highByte << 8) | lowByte;
-                                                               boot_page_fill(address,data);
-
-                                                               address =       address + 2;    // Select next word in memory
-                                                               size    -=      2;                              // Reduce number of bytes to write by two
-                                                       } while (size);                                 // Loop until all bytes written
-
-                                                       boot_page_write(tempaddress);
-                                                       boot_spm_busy_wait();
-                                                       boot_rww_enable();                              // Re-enable the RWW section
                                                }
                                                else
                                                {
@@ -1304,9 +1299,9 @@

        do {
        #if (FLASHEND > 0x10000)
-               theChar =       pgm_read_byte_far((uint16_t)dataPtr++);
+               theChar =       pgm_read_byte_far((uint32_t)dataPtr++);
        #else
-               theChar =       pgm_read_byte_near((uint16_t)dataPtr++);
+               theChar =       pgm_read_byte_near((uint32_t)dataPtr++);
        #endif
                if (theChar != 0)
                {
@@ -1564,9 +1559,9 @@
        PrintNewLine();
        ii                      =       0;
 #if (FLASHEND > 0x10000)
-       while (((theChar = pgm_read_byte_far(((uint16_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
+       while (((theChar = pgm_read_byte_far(((uint32_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
 #else
-       while (((theChar = pgm_read_byte_near(((uint16_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
+       while (((theChar = pgm_read_byte_near(((uint32_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
 #endif
        {
                eeprom_write_byte((uint8_t *)ii, theChar);

PS C:\work\avr\avrdude_test\avrdude_bin> echo "write flash 0x400 0xaa 0x55 0xaa 0x55" | .\avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0xaa 0x55 0xaa 0x55
Caching | ################################################## | 100% 0.08 s
avrdude> avrdude: synching cache to device ...
Writing | ################################################## | 100% 0.07 s

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> echo "write flash 0x400 0x55 0xaa 0x55 0xaa" | .\avrdude -c wiring -P COM11 -p m2560 -D -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9801 (probably m2560)
avrdude> write flash 0x400 0x55 0xaa 0x55 0xaa
Caching | ################################################## | 100% 0.09 s
avrdude> avrdude: synching cache to device ... done

avrdude done.  Thank you.
mcuee commented 1 year ago

@MCUdude

Maybe you want to give the above mod a try. Thanks.

The following is the zip file contains the mod to the Arduino stk500v2 bootloader directory. I use your file as the starting point. https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/stk500v2 Arduino-stk500v2_mod.zip

stefanrueger commented 1 year ago

What's the big deal about a wiring bootloader for the m2560 et al? Urboot works, and at a fraction of used space, too?

@mcuee: I don't get the2* in the line #define APP_END (FLASHEND - (2*BOOTSIZE) + 1). Why keep a gap of BOOTSIZE `between the application and the bootloader? Oh well, I suspect I don't want to know.

mcuee commented 1 year ago

What's the big deal about a wiring bootloader for the m2560 et al?

@stefanrueger

The only reason is that Arduino ships the ancient stk500v2 bootloader with their Arduino Mega (Mega2560). So all the clones will do the same as well.

@MCUdude is mainly using Optiboot with MegaCore but he added the STK500v2 bootloader last year so as to make it possible to use MegaCore with any Arduino Mega 2560 without replacing the bootloader or uploading using an ISP programmer https://github.com/MCUdude/MegaCore/commit/2b1655dcc7b64ae3b761834842b2695fbe3dab82

Then I informed him about the EEPROM issue and he updated the stk500v2 bootloader a bit later. https://github.com/MCUdude/MegaCore/commit/eba4f4a827aa3597b8e65144caee83f69724f280

mcuee commented 1 year ago

@mcuee: I don't get the2* in the line #define APP_END (FLASHEND - (2*BOOTSIZE) + 1). Why keep a gap of BOOTSIZE `between the application and the bootloader? Oh well, I suspect I don't want to know.

@stefanrueger

It is from the original code and the following fixes it for ATmega2560 but leaves that code for smaller Flash parts. I guess it may be related to the size of bootloader section in some parts. But even in that case, the proper fix is probably to define APP_END for each part if a single formula can not cut it.

In any case, this Arduino stk500v2 bootloader is only popular in ATmega1280/2560 and similar larger Flash part.

mcuee commented 1 year ago

Urboot works, and at a fraction of used space, too?

@stefanrueger and @MCUdude

I agree. So I created an issue here.

mcuee commented 1 year ago

@stefanrueger

BTW, there is a fork here. No idea how good it is. https://github.com/joede/stk500v2-bootloader

But stk500v2 is used in the XMega For Arduino project along with Caterina (USB AVR109 protocol) https://github.com/XMegaForArduino/arduino/tree/master/bootloaders/xmega

More interestingly there is a port for PIC32 MIPS32 core MCUs. https://github.com/chipKIT32/PIC32-avrdude-bootloader https://github.com/chipKIT32/pic32-Arduino-Bootloader https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original

mcuee commented 1 year ago

More interestingly there is a port for PIC32 MIPS32 core MCUs. https://github.com/chipKIT32/PIC32-avrdude-bootloader https://github.com/chipKIT32/pic32-Arduino-Bootloader https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original

I am not so sure about rhe avrdude version they are using. One of the above repo says avrdude 5.8.

There is a website which has the 5.10 binary and corresponding avrdude.conf file. http://www.cpustick.polydevelopment.com/bootloader.htm

The avrdude.conf file here has some entries for PIC32 MCUs. http://www.cpustick.polydevelopment.com/downloads/avrdude.conf


#------------------------------------------------------------
# Pic32 changes from Mark
#------------------------------------------------------------

part
    id               = "pic32";
    desc             = "32MX795F512L";
    signature        = 0x50 0x49 0x43;
    has_jtag         = yes;
#   stk500_devcode   = 0x??; # No STK500v1 support?
#   avr910_devcode   = 0x??; # Try the ATmega16 one
    avr910_devcode   = 0x74;
    pagel            = 0xd7;
    bs2              = 0xa0;
    chip_erase_delay = 9000;
    pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                       "0 0 0 0  0 0 0 0    0 0 0 0  0 0 0 0";

    chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                       "0 0 0 0  0 0 0 0    0 0 0 0  0 0 0 0";

    timeout             = 200;
    stabdelay           = 100;
    cmdexedelay         = 25;
    synchloops          = 32;
    bytedelay           = 0;
    pollindex           = 3;
    pollvalue           = 0x53;
    predelay            = 1;
    postdelay           = 1;
    pollmethod          = 1;

    pp_controlstack     =
        0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
        0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
        0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
        0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
    hventerstabdelay    = 100;
    progmodedelay       = 0;
    latchcycles         = 5;
    togglevtg           = 1;
    poweroffdelay       = 15;
    resetdelayms        = 1;
    resetdelayus        = 0;
    hvleavestabdelay    = 15;
    chiperasepulsewidth = 0;
    chiperasepolltimeout = 10;
    programfusepulsewidth = 0;
    programfusepolltimeout = 5;
    programlockpulsewidth = 0;
    programlockpolltimeout = 5;

    idr                 = 0x31;
    spmcr               = 0x57;
    allowfullpagebitstream = no;

    memory "eeprom"
        paged           = no; /* leave this "no" */
        page_size       = 8;  /* for parallel programming */
        size            = 2048;
        min_write_delay = 9000;
        max_write_delay = 9000;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read            = "  1   0   1   0      0   0   0   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  o   o   o   o      o   o   o   o";

        write           = "  1   1   0   0      0   0   0   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        loadpage_lo     = "  1   1   0   0      0   0   0   1",
                          "  0   0   0   0      0   0   0   0",
                          "  0   0   0   0      0  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "  1   1   0   0      0   0   1   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3   0   0   0",
                          "  x   x   x   x      x   x   x   x";

        mode            = 0x41;
        delay           = 10;
        blocksize       = 4;
        readsize        = 256;
      ;

    memory "flash"
        paged           = yes;
        size            = 524288;
        page_size       = 256;
        num_pages       = 2048;
        min_write_delay = 4500;
        max_write_delay = 4500;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read_lo         = "   0   0   1   0      0   0   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   o   o   o   o      o   o   o   o";

        read_hi         = "   0   0   1   0      1   0   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   o   o   o   o      o   o   o   o";

        loadpage_lo     = "  0   1   0   0      0   0   0   0",
                          "  0   0   0   0      0   0   0   0",
                          "  a7 a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        loadpage_hi     = "  0   1   0   0      1   0   0   0",
                          "  0   0   0   0      0   0   0   0",
                          "  a7 a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "   0   1   0   0      1   1   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   0   0   0   0      0   0   0   0";

        mode            = 0x41;
        delay           = 10;
        blocksize       = 128;
        readsize        = 256;
      ;

    memory "lock"
        size            = 1;
        read            = "0 1 0 1  1 0 0 0   0 0 0 0  0 0 0 0",
                          "x x x x  x x x x   x x o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 1 1 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   1 1 i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "lfuse"
        size            = 1;
        read            = "0 1 0 1  0 0 0 0   0 0 0 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 0 1 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   i i i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "hfuse"
        size            = 1;
        read            = "0 1 0 1  1 0 0 0   0 0 0 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 0 1 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0   i i i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "efuse"
        size            = 1;

        read            = "0 1 0 1  0 0 0 0  0 0 0 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0  o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 1 0 0",
                          "0 0 0 0  0 0 0 0  1 1 1 1  1 i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "signature"
        size            = 3;
        read            = "0  0  1  1   0  0  0  0   0  0  0  0   0  0  0  0",
                          "0  0  0  0   0  0 a1 a0   o  o  o  o   o  o  o  o";
      ;

    memory "calibration"
        size            = 1;

        read            = "0 0 1 1  1 0 0 0   0 0 0 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";
        ;
  ;

#------------------------------------------------------------
# Pic32 changes from Mark
#------------------------------------------------------------

part
    id               = "pic32-360";
    desc             = "32MX360F512L";
    signature        = 0x50 0x49 0x43;
    has_jtag         = yes;
#   stk500_devcode   = 0x??; # No STK500v1 support?
#   avr910_devcode   = 0x??; # Try the ATmega16 one
    avr910_devcode   = 0x74;
    pagel            = 0xd7;
    bs2              = 0xa0;
    chip_erase_delay = 9000;
    pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                       "0 0 0 0  0 0 0 0    0 0 0 0  0 0 0 0";

    chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                       "0 0 0 0  0 0 0 0    0 0 0 0  0 0 0 0";

    timeout             = 200;
    stabdelay           = 100;
    cmdexedelay         = 25;
    synchloops          = 32;
    bytedelay           = 0;
    pollindex           = 3;
    pollvalue           = 0x53;
    predelay            = 1;
    postdelay           = 1;
    pollmethod          = 1;

    pp_controlstack     =
        0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
        0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
        0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
        0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
    hventerstabdelay    = 100;
    progmodedelay       = 0;
    latchcycles         = 5;
    togglevtg           = 1;
    poweroffdelay       = 15;
    resetdelayms        = 1;
    resetdelayus        = 0;
    hvleavestabdelay    = 15;
    chiperasepulsewidth = 0;
    chiperasepolltimeout = 10;
    programfusepulsewidth = 0;
    programfusepolltimeout = 5;
    programlockpulsewidth = 0;
    programlockpolltimeout = 5;

    idr                 = 0x31;
    spmcr               = 0x57;
    allowfullpagebitstream = no;

    memory "eeprom"
        paged           = no; /* leave this "no" */
        page_size       = 8;  /* for parallel programming */
        size            = 2048;
        min_write_delay = 9000;
        max_write_delay = 9000;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read            = "  1   0   1   0      0   0   0   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  o   o   o   o      o   o   o   o";

        write           = "  1   1   0   0      0   0   0   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        loadpage_lo     = "  1   1   0   0      0   0   0   1",
                          "  0   0   0   0      0   0   0   0",
                          "  0   0   0   0      0  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "  1   1   0   0      0   0   1   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3   0   0   0",
                          "  x   x   x   x      x   x   x   x";

        mode            = 0x41;
        delay           = 10;
        blocksize       = 4;
        readsize        = 256;
      ;

    memory "flash"
        paged           = yes;
        size            = 524288;
        page_size       = 256;
        num_pages       = 2048;
        min_write_delay = 4500;
        max_write_delay = 4500;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read_lo         = "   0   0   1   0      0   0   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   o   o   o   o      o   o   o   o";

        read_hi         = "   0   0   1   0      1   0   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   o   o   o   o      o   o   o   o";

        loadpage_lo     = "  0   1   0   0      0   0   0   0",
                          "  0   0   0   0      0   0   0   0",
                          "  a7 a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        loadpage_hi     = "  0   1   0   0      1   0   0   0",
                          "  0   0   0   0      0   0   0   0",
                          "  a7 a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "   0   1   0   0      1   1   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   0   0   0   0      0   0   0   0";

        mode            = 0x41;
        delay           = 10;
        blocksize       = 128;
        readsize        = 256;
      ;

    memory "lock"
        size            = 1;
        read            = "0 1 0 1  1 0 0 0   0 0 0 0  0 0 0 0",
                          "x x x x  x x x x   x x o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 1 1 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   1 1 i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "lfuse"
        size            = 1;
        read            = "0 1 0 1  0 0 0 0   0 0 0 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 0 1 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   i i i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "hfuse"
        size            = 1;
        read            = "0 1 0 1  1 0 0 0   0 0 0 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 0 1 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0   i i i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "efuse"
        size            = 1;

        read            = "0 1 0 1  0 0 0 0  0 0 0 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0  o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 1 0 0",
                          "0 0 0 0  0 0 0 0  1 1 1 1  1 i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "signature"
        size            = 3;
        read            = "0  0  1  1   0  0  0  0   0  0  0  0   0  0  0  0",
                          "0  0  0  0   0  0 a1 a0   o  o  o  o   o  o  o  o";
      ;

    memory "calibration"
        size            = 1;

        read            = "0 0 1 1  1 0 0 0   0 0 0 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";
        ;
  ;

#------------------------------------------------------------
# Pic32 changes from Mark
#------------------------------------------------------------

part
    id               = "pic32-360";
    desc             = "32MX320F064H";
    signature        = 0x50 0x49 0x43;
    has_jtag         = yes;
#   stk500_devcode   = 0x??; # No STK500v1 support?
#   avr910_devcode   = 0x??; # Try the ATmega16 one
    avr910_devcode   = 0x74;
    pagel            = 0xd7;
    bs2              = 0xa0;
    chip_erase_delay = 9000;
    pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                       "0 0 0 0  0 0 0 0    0 0 0 0  0 0 0 0";

    chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                       "0 0 0 0  0 0 0 0    0 0 0 0  0 0 0 0";

    timeout             = 200;
    stabdelay           = 100;
    cmdexedelay         = 25;
    synchloops          = 32;
    bytedelay           = 0;
    pollindex           = 3;
    pollvalue           = 0x53;
    predelay            = 1;
    postdelay           = 1;
    pollmethod          = 1;

    pp_controlstack     =
        0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
        0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
        0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
        0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
    hventerstabdelay    = 100;
    progmodedelay       = 0;
    latchcycles         = 5;
    togglevtg           = 1;
    poweroffdelay       = 15;
    resetdelayms        = 1;
    resetdelayus        = 0;
    hvleavestabdelay    = 15;
    chiperasepulsewidth = 0;
    chiperasepolltimeout = 10;
    programfusepulsewidth = 0;
    programfusepolltimeout = 5;
    programlockpulsewidth = 0;
    programlockpolltimeout = 5;

    idr                 = 0x31;
    spmcr               = 0x57;
    allowfullpagebitstream = no;

    memory "eeprom"
        paged           = no; /* leave this "no" */
        page_size       = 8;  /* for parallel programming */
        size            = 2048;
        min_write_delay = 9000;
        max_write_delay = 9000;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read            = "  1   0   1   0      0   0   0   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  o   o   o   o      o   o   o   o";

        write           = "  1   1   0   0      0   0   0   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        loadpage_lo     = "  1   1   0   0      0   0   0   1",
                          "  0   0   0   0      0   0   0   0",
                          "  0   0   0   0      0  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "  1   1   0   0      0   0   1   0",
                          "  0   0   0   0      0 a10  a9  a8",
                          " a7  a6  a5  a4     a3   0   0   0",
                          "  x   x   x   x      x   x   x   x";

        mode            = 0x41;
        delay           = 10;
        blocksize       = 4;
        readsize        = 256;
      ;

    memory "flash"
        paged           = yes;
        size            = 65536;
        page_size       = 256;
        num_pages       = 256;
        min_write_delay = 4500;
        max_write_delay = 4500;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read_lo         = "   0   0   1   0      0   0   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   o   o   o   o      o   o   o   o";

        read_hi         = "   0   0   1   0      1   0   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   o   o   o   o      o   o   o   o";

        loadpage_lo     = "  0   1   0   0      0   0   0   0",
                          "  0   0   0   0      0   0   0   0",
                          "  a7 a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        loadpage_hi     = "  0   1   0   0      1   0   0   0",
                          "  0   0   0   0      0   0   0   0",
                          "  a7 a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "   0   1   0   0      1   1   0   0",
                          " a15 a14 a13 a12    a11 a10  a9  a8",
                          "  a7  a6  a5  a4     a3  a2  a1  a0",
                          "   0   0   0   0      0   0   0   0";

        mode            = 0x41;
        delay           = 10;
        blocksize       = 128;
        readsize        = 256;
      ;

    memory "lock"
        size            = 1;
        read            = "0 1 0 1  1 0 0 0   0 0 0 0  0 0 0 0",
                          "x x x x  x x x x   x x o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 1 1 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   1 1 i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "lfuse"
        size            = 1;
        read            = "0 1 0 1  0 0 0 0   0 0 0 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 0 1 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   i i i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "hfuse"
        size            = 1;
        read            = "0 1 0 1  1 0 0 0   0 0 0 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 0 1 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0   i i i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "efuse"
        size            = 1;

        read            = "0 1 0 1  0 0 0 0  0 0 0 0  1 0 0 0",
                          "0 0 0 0  0 0 0 0  o o o o  o o o o";

        write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 1 0 0",
                          "0 0 0 0  0 0 0 0  1 1 1 1  1 i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "signature"
        size            = 3;
        read            = "0  0  1  1   0  0  0  0   0  0  0  0   0  0  0  0",
                          "0  0  0  0   0  0 a1 a0   o  o  o  o   o  o  o  o";
      ;

    memory "calibration"
        size            = 1;

        read            = "0 0 1 1  1 0 0 0   0 0 0 0  0 0 0 0",
                          "0 0 0 0  0 0 0 0   o o o o  o o o o";
        ;
  ;

#------------------------------------------------------------
# Pic CPU added by Mark Sproul, May 2011
#------------------------------------------------------------

part
    id               = "pic32-360";
    desc             = "32MX320F128H";
    signature        = 0x50 0x49 0x43;
    has_jtag         = no;
#    stk500_devcode   = 0xB2;
#    avr910_devcode   = 0x43;
    chip_erase_delay = 9000;
    pagel            = 0xD7;
    bs2              = 0xA0;
    reset            = dedicated;
    pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                       "x x x x  x x x x    x x x x  x x x x";

    chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                       "x x x x  x x x x    x x x x  x x x x";

    timeout     = 200;
    stabdelay       = 100;
    cmdexedelay     = 25;
    synchloops      = 32;
    bytedelay       = 0;
    pollindex       = 3;
    pollvalue       = 0x53;
    predelay        = 1;
    postdelay       = 1;
    pollmethod      = 1;

    pp_controlstack     =
        0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
        0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
        0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
        0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02;
    hventerstabdelay    = 100;
    progmodedelay       = 0;
    latchcycles         = 5;
    togglevtg           = 1;
    poweroffdelay       = 15;
    resetdelayms        = 1;
    resetdelayus        = 0;
    hvleavestabdelay    = 15;
    chiperasepulsewidth = 0;
    chiperasepolltimeout = 10;
    programfusepulsewidth = 0;
    programfusepolltimeout = 5;
    programlockpulsewidth = 0;
    programlockpolltimeout = 5;

    idr                 = 0x31;
    spmcr               = 0x57;
    rampz               = 0x3b;
    allowfullpagebitstream = no;

    memory "eeprom"
        paged           = no; /* leave this "no" */
        page_size       = 8;  /* for parallel programming */
        size            = 4096;
        min_write_delay = 9000;
        max_write_delay = 9000;
        readback_p1     = 0x00;
        readback_p2     = 0x00;
        read            = "  1   0   1   0      0   0   0   0",
                          "  x   x   x   x    a11 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  o   o   o   o      o   o   o   o";

        write           = "  1   1   0   0      0   0   0   0",
                          "  x   x   x   x    a11 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0", 
                          "  i   i   i   i      i   i   i   i";

    loadpage_lo = "  1   1   0   0      0   0   0   1",
              "  0   0   0   0      0   0   0   0",
              "  0   0   0   0      0  a2  a1  a0",
              "  i   i   i   i      i   i   i   i";

    writepage   = "  1   1   0   0      0   0   1   0",
              "  0   0   x   x    a11 a10  a9  a8",
              " a7  a6  a5  a4     a3   0   0   0",
              "  x   x   x   x      x   x   x   x";

    mode        = 0x41;
    delay       = 10;
    blocksize   = 8;
    readsize    = 256;
      ;

    memory "flash"
        paged           = yes;
#        size            = 262144;
#-        size          = 13631488;
        size            = 131072;
        page_size       = 256;
        num_pages       = 512;
#        num_pages       = 26624;
#        num_pages       = 53248;
        min_write_delay = 4500;
        max_write_delay = 4500;
        readback_p1     = 0x00;
        readback_p2     = 0x00;
        read_lo         = "  0   0   1   0      0   0   0   0",
                          "a15 a14 a13 a12    a11 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  o   o   o   o      o   o   o   o";

        read_hi         = "  0   0   1   0      1   0   0   0",
                          "a15 a14 a13 a12    a11 a10  a9  a8",
                          " a7  a6  a5  a4     a3  a2  a1  a0",
                          "  o   o   o   o      o   o   o   o";

        loadpage_lo     = "  0   1   0   0      0   0   0   0",
                          "  x   x   x   x      x   x   x   x",
                          "  x  a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        loadpage_hi     = "  0   1   0   0      1   0   0   0",
                          "  x   x   x   x      x   x   x   x",
                          "  x  a6  a5  a4     a3  a2  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "  0   1   0   0      1   1   0   0",
                          "a15 a14 a13 a12    a11 a10  a9  a8",
                          " a7   x   x   x      x   x   x   x",
                          "  x   x   x   x      x   x   x   x";

        load_ext_addr   = "  0   1   0   0      1   1   0   1",
                          "  0   0   0   0      0   0   0   0",
                          "  0   0   0   0      0   0   0 a16",
                          "  0   0   0   0      0   0   0   0";

    mode        = 0x41;
    delay       = 10;
    blocksize   = 256;
    readsize    = 256;
      ;

    memory "lfuse"
        size            = 1;
        write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 0 0 0",
                          "x x x x  x x x x  i i i i  i i i i";

        read            = "0 1 0 1  0 0 0 0  0 0 0 0  0 0 0 0",
                          "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "hfuse"
        size            = 1;
        write           = "1 0 1 0  1 1 0 0  1 0 1 0  1 0 0 0",
                          "x x x x  x x x x  i i i i  i i i i";

        read            = "0 1 0 1  1 0 0 0  0 0 0 0  1 0 0 0",
                          "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "efuse"
        size            = 1;
        write           = "1 0 1 0  1 1 0 0  1 0 1 0  0 1 0 0",
                          "x x x x  x x x x  x x x x  x i i i";

        read            = "0 1 0 1  0 0 0 0  0 0 0 0  1 0 0 0",
                          "x x x x  x x x x  o o o o  o o o o";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "lock"
        size            = 1;
        read            = "0 1 0 1  1 0 0 0   0 0 0 0  0 0 0 0",
                          "x x x x  x x x x   x x o o  o o o o";

        write           = "1 0 1 0  1 1 0 0   1 1 1 x  x x x x",
                          "x x x x  x x x x   1 1 i i  i i i i";
        min_write_delay = 9000;
        max_write_delay = 9000;
      ;

    memory "calibration"
        size            = 1;
        read            = "0 0 1 1  1 0 0 0    x x x x  x x x x",
                          "0 0 0 0  0 0 0 0    o o o o  o o o o";
      ;

    memory "signature"
        size            = 3;
        read            = "0  0  1  1   0  0  0  0   x  x  x  x   x  x  x  x",
                          "x  x  x  x   x  x a1 a0   o  o  o  o   o  o  o  o";
      ;
  ;
mcuee commented 1 year ago

And interestingly we were discussing stk500v2 bootloader for PIC32 recently here.