Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jtag2updi EEPROM write issue for AVR Dx parts in CLI mode #1128

Closed
mcuee opened this issue Oct 15, 2022 · 24 comments · Fixed by #1318
Closed

jtag2updi EEPROM write issue for AVR Dx parts in CLI mode #1128

mcuee opened this issue Oct 15, 2022 · 24 comments · Fixed by #1318
Labels
bug Something isn't working

Comments

@mcuee
Copy link
Collaborator

mcuee commented Oct 15, 2022

Updated:

JTAG2UPDI ATmega4808 AVR128DA32
Read from EEPROM (-U)
Write to EEPROM (-U)
SerialUPDI ATmega4808 AVR128DA32
Read from EEPROM (-U)
Write to EEPROM (-U)
@mcuee
Copy link
Collaborator Author

mcuee commented Oct 15, 2022

@MCUdude
Somehow I can not reproduce the issue using my Nano 4808 (EEPROM page size = 64) with jtag2updi.

PS C:\work\avr\avrdude_test\avrdude_bin> cat .\hex2\entest_16B.eep
:020000040000FA
:1000000054686520717569636B2062726F776E202A
:00000001FF

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git -p atmega4808 -c jtag2updi -P COM13 -b115200 -qqt
avrdude> dump eeprom
>>> dump eeprom
0000  5a 20 6a 61 67 74 20 69  6d 20 6b 6f 6d 70 6c 65  |Z jagt im komple|
0010  74 74 20 76 65 72 77 61  68 72 6c 6f 73 74 65 6e  |tt verwahrlosten|
0020  20 54 61 78 69 20 71 75  65 72 20 64 75 72 63 68  | Taxi quer durch|
0030  20 42 61 79 65 72 6e 0a  5a 20 6a 61 67 74 20 69  | Bayern Z jagt i|
0040  6d 20 6b 6f 6d 70 6c 65  74 74 20 76 65 72 77 61  |m komplett verwa|
0050  68 72 6c 6f 73 74 65 6e  20 54 61 78 69 20 71 75  |hrlosten Taxi qu|
0060  65 72 20 64 75 72 63 68  20 42 61 79 65 72 6e 0a  |er durch Bayern |
0070  5a 20 6a 61 67 74 20 69  6d 20 6b 6f 6d 70 6c 65  |Z jagt im komple|
0080  74 74 20 76 65 72 77 61  68 72 6c 6f 73 74 65 6e  |tt verwahrlosten|
0090  20 54 61 78 69 20 71 75  65 72 20 64 75 72 63 68  | Taxi quer durch|
00a0  20 42 61 79 65 72 6e 0a  5a 20 6a 61 67 74 20 69  | Bayern Z jagt i|
00b0  6d 20 6b 6f 6d 70 6c 65  74 74 20 76 65 72 77 61  |m komplett verwa|
00c0  68 72 6c 6f 73 74 65 6e  20 54 61 78 69 20 71 75  |hrlosten Taxi qu|
00d0  65 72 20 64 75 72 63 68  20 42 61 79 65 72 6e 0a  |er durch Bayern |
00e0  5a 20 6a 61 67 74 20 69  6d 20 6b 6f 6d 70 6c 65  |Z jagt im komple|
00f0  74 74 20 76 65 72 77 61  68 72 6c 6f 73 74 65 6e  |tt verwahrlosten|

avrdude> quit
>>> quit

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1121v1 -p atmega4808 -c jtag2updi -P COM13 
-b115200 -qq -U eeprom:w:.\hex2\entest_16B.eep:i && echo OK
avrdude_pr1121v1.exe: jtagmkII_paged_write(): bad response to write memory command: RSP_ILLEGAL_MEMORY_TYPE
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git -p atmega4808 -c jtag2updi -P COM13 -b115200 -qqt
avrdude> dump eeprom
>>> dump eeprom
0000  54 68 65 20 71 75 69 63  6b 20 62 72 6f 77 6e 20  |The quick brown |
0010  74 74 20 76 65 72 77 61  68 72 6c 6f 73 74 65 6e  |tt verwahrlosten|
0020  20 54 61 78 69 20 71 75  65 72 20 64 75 72 63 68  | Taxi quer durch|
0030  20 42 61 79 65 72 6e 0a  5a 20 6a 61 67 74 20 69  | Bayern Z jagt i|
0040  6d 20 6b 6f 6d 70 6c 65  74 74 20 76 65 72 77 61  |m komplett verwa|
0050  68 72 6c 6f 73 74 65 6e  20 54 61 78 69 20 71 75  |hrlosten Taxi qu|
0060  65 72 20 64 75 72 63 68  20 42 61 79 65 72 6e 0a  |er durch Bayern |
0070  5a 20 6a 61 67 74 20 69  6d 20 6b 6f 6d 70 6c 65  |Z jagt im komple|
0080  74 74 20 76 65 72 77 61  68 72 6c 6f 73 74 65 6e  |tt verwahrlosten|
0090  20 54 61 78 69 20 71 75  65 72 20 64 75 72 63 68  | Taxi quer durch|
00a0  20 42 61 79 65 72 6e 0a  5a 20 6a 61 67 74 20 69  | Bayern Z jagt i|
00b0  6d 20 6b 6f 6d 70 6c 65  74 74 20 76 65 72 77 61  |m komplett verwa|
00c0  68 72 6c 6f 73 74 65 6e  20 54 61 78 69 20 71 75  |hrlosten Taxi qu|
00d0  65 72 20 64 75 72 63 68  20 42 61 79 65 72 6e 0a  |er durch Bayern |
00e0  5a 20 6a 61 67 74 20 69  6d 20 6b 6f 6d 70 6c 65  |Z jagt im komple|
00f0  74 74 20 76 65 72 77 61  68 72 6c 6f 73 74 65 6e  |tt verwahrlosten|

avrdude> quit
>>> quit


@mcuee mcuee added the bug Something isn't working label Oct 15, 2022
@mcuee mcuee changed the title jtag2updi and serialupdi EEPROM write issue jtag2updi and serialupdi EEPROM write issue in CLI mode Oct 16, 2022
@mcuee
Copy link
Collaborator Author

mcuee commented Oct 16, 2022

Updated test results from @MCUdude here.
#1121 (comment)

In this case, the issue with jtag2updi is the same as #1069 mentioned by @avrfreak.

JTAG2UPDI ATmega4808 AVR128DA32
Read from EEPROM (-U)
Write to EEPROM (-U)
SerialUPDI ATmega4808 AVR128DA32
Read from EEPROM (-U)
Write to EEPROM (-U)
$ echo "Hello World" | ./avrdude -cjtag2updi -pavr128da32 -Ueeprom:w:-:r

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.03s

avrdude: Device signature = 0x1e9709 (probably avr128da32)
avrdude: reading input file <stdin> for eeprom
avrdude: writing 12 bytes eeprom ...

Writing |                                                    | 0% 0.00s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | ####                                               | 8% 0.02s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | ########                                           | 16% 0.02s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | #############                                      | 25% 0.03s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | #################                                  | 33% 0.03s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | #####################                              | 41% 0.04s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | #########################                          | 50% 0.04s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | #############################                      | 58% 0.05s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | #################################                  | 66% 0.06s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | ######################################             | 75% 0.06s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | ##########################################         | 83% 0.07s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | ##############################################     | 91% 0.07s
avrdude: jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;  
Writing | ################################################## | 100% 0.08s

avrdude: 12 bytes of eeprom written
avrdude: verifying eeprom memory against <stdin>

Reading | ################################################## | 100% 0.09s

avrdude: verification error, first mismatch at byte 0x0000
         0xff != 0x48
avrdude: verification error; content mismatch

avrdude done.  Thank you.

@mcuee mcuee changed the title jtag2updi and serialupdi EEPROM write issue in CLI mode jtag2updi EEPROM write issue for AVR Dx parts in CLI mode Oct 16, 2022
@mcuee
Copy link
Collaborator Author

mcuee commented Oct 16, 2022

avrdude -Cavrdude.conf -c jtag2updi -p avr128db28 -P COM1 -e -b 115200 -U flash:w:test.hex:a -U eeprom:w:test.eep:a

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.07s

avrdude: Device signature = 0x1e970e (probably avr128db28)
avrdude: erasing chip
avrdude: reading input file "test.hex"
avrdude: input file test.hex auto detected as Intel Hex
avrdude: writing flash (11976 bytes):

Writing | ################################################## | 100% 2.40s

avrdude: 11976 bytes of flash written
avrdude: verifying flash memory against test.hex:
avrdude: input file test.hex auto detected as Intel Hex

Reading | ################################################## | 100% 2.27s

avrdude: 11976 bytes of flash verified
avrdude: reading input file "test.eep"
avrdude: input file test.eep auto detected as Intel Hex
avrdude: writing eeprom (16 bytes):

Writing |                                                    | 0% 0.00savrdude:
jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ###                                                | 6% 0.05savrdude:
jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ######                                             | 12% 0.09savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | #########                                          | 18% 0.13savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | #############                                      | 25% 0.17savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ################                                   | 31% 0.21savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ###################                                | 37% 0.25savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ######################                             | 43% 0.29savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | #########################                          | 50% 0.33savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ############################                       | 56% 0.37savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ###############################                    | 62% 0.41savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ##################################                 | 68% 0.45savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ######################################             | 75% 0.49savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | #########################################          | 81% 0.53savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ############################################       | 87% 0.57savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ###############################################    | 93% 0.62savrdude:
 jtagmkII_write_byte(): bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
Writing | ################################################## | 100% 0.66s

avrdude: 16 bytes of eeprom written
avrdude: verifying eeprom memory against test.eep:
avrdude: input file test.eep auto detected as Intel Hex

Reading | ################################################## | 100% 0.78s

avrdude: verification error, first mismatch at byte 0x0000
         0xff != 0x04
avrdude: verification error; content mismatch
avrdude: jtagmkII_recv(): checksum error
avrdude: jtagmkII_program_disable(): timeout/error communicating with programmer
 (status -4)
avrdude: jtagmkII_recv(): checksum error
avrdude: jtagmkII_close(): timeout/error communicating with programmer (status -4)

avrdude done.  Thank you.

@mcuee
Copy link
Collaborator Author

mcuee commented Oct 16, 2022

From what I see, this may well be a limitation of jtag2updi. @ElTangas may further comment on this possibility.

But from #1121 I think there is a way to work-around this issue (and since terminal mode works). Hopefully @stefanrueger will be able to come out similar fix for the CLI mode.

@mcuee
Copy link
Collaborator Author

mcuee commented Nov 4, 2022

I can reproduce the same issue.

Arduino Uno clone based jtag2updi
Microchip AVR128DB48 Curiosity Nano board

$ echo "Hello World" | ./avrdude -cjtag2updi -PCOM9 -pavr128db48 -Ueeprom:w:-:r

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e970c (probably avr128db48)
avrdude: reading input file <stdin> for eeprom
         with 12 bytes in 1 section within [0, 11]
avrdude: writing 12 bytes eeprom ...

Writing | -------------------------------------------------- | 0% 0.02 s

avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude error: bad response to write memory command: RSP_ILLEGAL_MCU_STATE
 ***failed;
avrdude: 12 bytes of eeprom written
avrdude: verifying eeprom memory against <stdin>

Reading | ################################################## | 100% 0.37 s

avrdude error: verification mismatch, first encountered at addr 0x0000
        device 0xff != input 0x48
avrdude error: verification mismatch
avrdude error: wrong checksum
avrdude error: timeout/error communicating with programmer (status -4)

avrdude done.  Thank you.

@mcuee
Copy link
Collaborator Author

mcuee commented Nov 4, 2022

@MCUdude

I have an interesting finding, the following quick and dirty fix seems to solve the issue (not the right fix). The idea is to use byte size write for AVR Dx EEPROM in CLI mode, similar to #1121 (which is for terminal mode).

For the last command, there will be some stops during the write but the end results are fine.


$ git diff
diff --git a/src/jtagmkII.c b/src/jtagmkII.c
index 2f6425c..7666e83 100644
--- a/src/jtagmkII.c
+++ b/src/jtagmkII.c
@@ -2273,7 +2273,7 @@ static int jtagmkII_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AV
      if (pgm->flag & PGM_FL_IS_DW)
        unsupp = 1;
   } else if (strcmp(mem->desc, "eeprom") == 0) {
-    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM;
+    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM: MTYPE_EEPROM;
     need_progmode = 0;
     PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
   } else if (strcmp(mem->desc, "lfuse") == 0) {

$ echo "Hello World" | ./avrdude -cjtag2updi -PCOM9 -pavr128db48 -Ueeprom:w:-:r

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e970c (probably avr128db48)
avrdude: reading input file <stdin> for eeprom
         with 12 bytes in 1 section within [0, 11]
avrdude: writing 12 bytes eeprom ...

Writing | ################################################## | 100% 0.16 s

avrdude: 12 bytes of eeprom written
avrdude: verifying eeprom memory against <stdin>

Reading | ################################################## | 100% 0.36 s

avrdude: 12 bytes of eeprom verified

avrdude done.  Thank you.

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git_mod -c jtag2updi -P COM9 -b 115200 -p avr128db48 
-U eeprom:w:.\hex\entest_256B.eep:i

avrdude_git_mod: AVR device initialized and ready to accept instructions
avrdude_git_mod warning: timeout/error communicating with programmer (status -1)
avrdude_git_mod: device signature = 0x1e970c (probably avr128db48)
avrdude_git_mod: reading input file .\hex\entest_256B.eep for eeprom
                 with 256 bytes in 1 section within [0, 0xff]
avrdude_git_mod: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 23.13 s

avrdude_git_mod: 256 bytes of eeprom written
avrdude_git_mod: verifying eeprom memory against .\hex\entest_256B.eep

Reading | ################################################## | 100% 2.18 s

avrdude_git_mod: 256 bytes of eeprom verified

avrdude_git_mod done.  Thank you.

@mcuee
Copy link
Collaborator Author

mcuee commented Nov 4, 2022

@avrfreak
If you have some time, please give the quick mod (.\avrdude_git_mod.exe) a try. Thanks. No worry if you do not have time. It is not the right fix anyway, just for troubleshooting purpose.

Edit: wrong file. Please use this latest one.

avrdude_git_mod.zip

@mcuee
Copy link
Collaborator Author

mcuee commented Nov 4, 2022

Interestingly git main seems to work if I click the reset key of the Uno based jtag2updi programmer first before running avrdude, not very wll though. Writing will have a few pauses and can take quite long, reading will often have a few communication errors.

The above patch does not seem to help in this laptop.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c jtag2updi -P COM5 -b 115200 -p avr128db48 
-U eeprom:w:.\hex\entest_256B.eep:i

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e970c (probably avr128db48)
avrdude: reading input file .\hex\entest_256B.eep for eeprom
         with 256 bytes in 1 section within [0, 0xff]
avrdude: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 43.10 s

avrdude: 256 bytes of eeprom written
avrdude: verifying eeprom memory against .\hex\entest_256B.eep

Reading | #######                                            
| 14% 0.57 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | ################################################## | 100% 12.10 s

avrdude: 256 bytes of eeprom verified

avrdude done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c jtag2updi -P COM5 -b 115200 -p avr128db48
 -U eeprom:w:.\hex2\detest_256B.eep:i

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e970c (probably avr128db48)
avrdude: reading input file .\hex2\detest_256B.eep for eeprom
         with 256 bytes in 1 section within [0, 0xff]
avrdude: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 163.32 s

avrdude: 256 bytes of eeprom written
avrdude: verifying eeprom memory against .\hex2\detest_256B.eep

Reading |                                                    
| 0% 0.00 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | ##                                                 
| 3% 10.16 s avrdude warning: timeout/error communicating with programmer (status -1)
avrdude warning: timeout/error communicating with programmer (status -1)
Reading | ####                                               
| 8% 30.38 s avrdude warning: timeout/error communicating with programmer (status -1)
avrdude warning: timeout/error communicating with programmer (status -1)
Reading | #####                                              
| 10% 50.50 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | #######                                            
| 13% 60.64 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | #########                                          
| 18% 70.88 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | ####################                               
| 40% 81.78 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | #####################                              
| 42% 91.90 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | ########################                           
| 47% 102.10 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | #########################                          
| 49% 112.21 s avrdude warning: timeout/error communicating with programmer (status -1)
Reading | ################################################## | 100% 122.37 s

avrdude: 256 bytes of eeprom verified

avrdude done.  Thank you.

@mcuee
Copy link
Collaborator Author

mcuee commented Nov 4, 2022

The following mod seems to work the best, usually no issues but still sometimes got pause in writing. I still need to click the reset button on the Uno before running avrdude.

PS C:\work\avr\avrdude_test\avrdude_main> git diff
diff --git a/src/jtagmkII.c b/src/jtagmkII.c
index 2f6425c..3a646e8 100644
--- a/src/jtagmkII.c
+++ b/src/jtagmkII.c
@@ -1906,7 +1906,7 @@ static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const A
       free(cmd);
       return n_bytes;
     }
-    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM: MTYPE_EEPROM_PAGE;
+    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM_PAGE;
     PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
   } else if (strcmp(m->desc, "usersig") == 0 ||
              strcmp(m->desc, "userrow") == 0) {
@@ -2009,7 +2009,7 @@ static int jtagmkII_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AV
       /* dynamically decide between flash/boot memtype */
       dynamic_memtype = 1;
   } else if (strcmp(m->desc, "eeprom") == 0) {
-    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM: MTYPE_EEPROM_PAGE;
+    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM_PAGE;
     if (pgm->flag & PGM_FL_IS_DW)
       return -1;
   } else if (strcmp(m->desc, "prodsig") == 0) {
@@ -2104,7 +2104,7 @@ static int jtagmkII_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVR
   } else if (avr_mem_is_eeprom_type(mem)) {
     if ( (pgm->flag & PGM_FL_IS_DW) || (p->prog_modes & (PM_PDI | PM_UPDI)) ) {
       /* debugWire cannot use page access for EEPROM */
-      cmd[1] = MTYPE_EEPROM;
+      cmd[1] = MTYPE_EEPROM_XMEGA;
     } else {
       cmd[1] = MTYPE_EEPROM_PAGE;
       pagesize = mem->page_size;

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git_mod1 -c jtag2updi -P COM5 -b 115200 -p avr128db48
 -U eeprom:w:.\hex2\entest_256B.eep:i

avrdude_git_mod1: AVR device initialized and ready to accept instructions
avrdude_git_mod1: device signature = 0x1e970c (probably avr128db48)
avrdude_git_mod1: reading input file .\hex2\entest_256B.eep for eeprom
                  with 256 bytes in 1 section within [0, 0xff]
avrdude_git_mod1: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 3.03 s

avrdude_git_mod1: 256 bytes of eeprom written
avrdude_git_mod1: verifying eeprom memory against .\hex2\entest_256B.eep

Reading | ################################################## | 100% 2.03 s

avrdude_git_mod1: 256 bytes of eeprom verified

avrdude_git_mod1 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git_mod1 -c jtag2updi -P COM5 -b 115200 -p avr128db48
 -U eeprom:w:.\hex2\detest_256B.eep:i

avrdude_git_mod1: AVR device initialized and ready to accept instructions
avrdude_git_mod1: device signature = 0x1e970c (probably avr128db48)
avrdude_git_mod1: reading input file .\hex2\detest_256B.eep for eeprom
                  with 256 bytes in 1 section within [0, 0xff]
avrdude_git_mod1: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 3.04 s

avrdude_git_mod1: 256 bytes of eeprom written
avrdude_git_mod1: verifying eeprom memory against .\hex2\detest_256B.eep

Reading | ################################################## | 100% 2.03 s

avrdude_git_mod1: 256 bytes of eeprom verified

avrdude_git_mod1 done.  Thank you.

avrdude_git_mod1.zip

@mcuee
Copy link
Collaborator Author

mcuee commented Nov 4, 2022

This may be a bit better. I do not need to reset the Uno now and so far I have not got failure. I have tested on the Nano 4808 and it has no regressions for ATmega4808.

PS C:\work\avr\avrdude_test\avrdude_main> git diff
diff --git a/src/jtagmkII.c b/src/jtagmkII.c
index 2f6425c..f3cc989 100644
--- a/src/jtagmkII.c
+++ b/src/jtagmkII.c
@@ -1906,7 +1906,7 @@ static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const A
       free(cmd);
       return n_bytes;
     }
-    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM: MTYPE_EEPROM_PAGE;
+    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM_PAGE;
     PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
   } else if (strcmp(m->desc, "usersig") == 0 ||
              strcmp(m->desc, "userrow") == 0) {
@@ -2009,7 +2009,7 @@ static int jtagmkII_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AV
       /* dynamically decide between flash/boot memtype */
       dynamic_memtype = 1;
   } else if (strcmp(m->desc, "eeprom") == 0) {
-    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM: MTYPE_EEPROM_PAGE;
+    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM_PAGE;
     if (pgm->flag & PGM_FL_IS_DW)
       return -1;
   } else if (strcmp(m->desc, "prodsig") == 0) {
@@ -2102,9 +2102,11 @@ static int jtagmkII_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVR
     paddr_ptr = &PDATA(pgm)->flash_pageaddr;
     cache_ptr = PDATA(pgm)->flash_pagecache;
   } else if (avr_mem_is_eeprom_type(mem)) {
-    if ( (pgm->flag & PGM_FL_IS_DW) || (p->prog_modes & (PM_PDI | PM_UPDI)) ) {
+    if (pgm->flag & PGM_FL_IS_DW) {
       /* debugWire cannot use page access for EEPROM */
       cmd[1] = MTYPE_EEPROM;
+    } else if(p->prog_modes & (PM_PDI | PM_UPDI) ) {
+      cmd[1] = MTYPE_EEPROM_XMEGA;
     } else {
       cmd[1] = MTYPE_EEPROM_PAGE;
       pagesize = mem->page_size;

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git_mod2 -c jtag2updi -P COM5 -b 115200 -p avr128db48
 -U eeprom:w:.\hex2\detest_256B.eep:i

avrdude_git_mod2: AVR device initialized and ready to accept instructions
avrdude_git_mod2: device signature = 0x1e970c (probably avr128db48)
avrdude_git_mod2: reading input file .\hex2\detest_256B.eep for eeprom
                  with 256 bytes in 1 section within [0, 0xff]
avrdude_git_mod2: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 3.22 s

avrdude_git_mod2: 256 bytes of eeprom written
avrdude_git_mod2: verifying eeprom memory against .\hex2\detest_256B.eep

Reading | ################################################## | 100% 2.22 s

avrdude_git_mod2: 256 bytes of eeprom verified

avrdude_git_mod2 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git_mod2 -c jtag2updi -P COM5 -b 115200 -p avr128db48
 -U eeprom:w:.\hex2\entest_256B.eep:i

avrdude_git_mod2: AVR device initialized and ready to accept instructions
avrdude_git_mod2: device signature = 0x1e970c (probably avr128db48)
avrdude_git_mod2: reading input file .\hex2\entest_256B.eep for eeprom
                  with 256 bytes in 1 section within [0, 0xff]
avrdude_git_mod2: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 3.19 s

avrdude_git_mod2: 256 bytes of eeprom written
avrdude_git_mod2: verifying eeprom memory against .\hex2\entest_256B.eep

Reading | ################################################## | 100% 2.24 s

avrdude_git_mod2: 256 bytes of eeprom verified

avrdude_git_mod2 done.  Thank you.

$ echo "Hello World" | ./avrdude_git_mod2 -cjtag2updi -PCOM5 -b 115200 -pavr128db48 -Ueeprom:w:-:r

avrdude_git_mod2: AVR device initialized and ready to accept instructions
avrdude_git_mod2: device signature = 0x1e970c (probably avr128db48)
avrdude_git_mod2: reading input file <stdin> for eeprom
                  with 12 bytes in 1 section within [0, 11]
avrdude_git_mod2: writing 12 bytes eeprom ...

Writing | ################################################## | 100% 0.15 s

avrdude_git_mod2: 12 bytes of eeprom written
avrdude_git_mod2: verifying eeprom memory against <stdin>

Reading | ################################################## | 100% 0.36 s

avrdude_git_mod2: 12 bytes of eeprom verified

avrdude_git_mod2 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git_mod2 -c jtag2updi -P COM5 -b 115200 -p atmega4808
 -U eeprom:w:.\hex2\detest_256B.eep:i

avrdude_git_mod2: AVR device initialized and ready to accept instructions
avrdude_git_mod2: device signature = 0x1e9650 (probably m4808)
avrdude_git_mod2: reading input file .\hex2\detest_256B.eep for eeprom
                  with 256 bytes in 1 section within [0, 0xff]
                  using 4 pages and 0 pad bytes
avrdude_git_mod2: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 0.08 s

avrdude_git_mod2: 256 bytes of eeprom written
avrdude_git_mod2: verifying eeprom memory against .\hex2\detest_256B.eep

Reading | ################################################## | 100% 0.08 s

avrdude_git_mod2: 256 bytes of eeprom verified

avrdude_git_mod2 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git_mod2 -c jtag2updi -P COM5 -b 115200 -p atmega4808
 -U eeprom:w:.\hex2\entest_256B.eep:i

avrdude_git_mod2: AVR device initialized and ready to accept instructions
avrdude_git_mod2: device signature = 0x1e9650 (probably m4808)
avrdude_git_mod2: reading input file .\hex2\entest_256B.eep for eeprom
                  with 256 bytes in 1 section within [0, 0xff]
                  using 4 pages and 0 pad bytes
avrdude_git_mod2: writing 256 bytes eeprom ...

Writing | ################################################## | 100% 0.08 s

avrdude_git_mod2: 256 bytes of eeprom written
avrdude_git_mod2: verifying eeprom memory against .\hex2\entest_256B.eep

Reading | ################################################## | 100% 0.07 s

avrdude_git_mod2: 256 bytes of eeprom verified

avrdude_git_mod2 done.  Thank you.

avrdude_git_mod2.zip

@mcuee
Copy link
Collaborator Author

mcuee commented Nov 4, 2022

@stefanrueger @MCUdude @janegilruud
Please help to review the above change to see if it is valid or not. Thanks.

@llinjupt
Copy link
Contributor

llinjupt commented Mar 3, 2023

@stefanrueger @mcuee
Refer to #1121 (comment) and the feedback #1121 (comment)

@stefanrueger THX for your quick response.
Please check jtagmkII_write_byte.

  if (strcmp(mem->desc, "flash") == 0) {
     if ((addr & 1) == 1) {
       /* odd address = high byte */
       writedata = 0xFF;	/* don't modify the low byte */
       writedata2 = data;
       addr &= ~1L;
     }
     writesize = 2;
     need_progmode = 0;         // I wonder why it is set it to 0
     PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
     if (pgm->flag & PGM_FL_IS_DW)
       unsupp = 1;
  } else if (strcmp(mem->desc, "eeprom") == 0) {
    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM;
    need_progmode = 0;        // the same as the above one
    PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
  }

Below need_progmode is used to determine if it need to leave prog mode.

  if (need_progmode) {
    if (jtagmkII_program_enable(pgm) < 0)
      return -1;
  } else {
    if (jtagmkII_program_disable(pgm) < 0) // it goes here and leave prog mode
      return -1;
  }

In https://github.com/ElTangas/jtag2updi/blob/master/source/JTAG2.cpp

  void JTAG2::write_mem() {
    if (UPDI::CPU_mode() != 0x08) { // it always fails here
      // fail if not in program mode
      set_status(RSP_ILLEGAL_MCU_STATE, 0x01);
    }

So it's clear that when the page size is not given, avrdude calls jtagmkII_write_byte, and it always fails. Unluckly .avrdx series' eeprom section don't implement page section that doesn't like other e.g. MEGA3209 does.

Remove need_progmode checking will fix this issue. But I wonder why it exists and if it will bring new issues.

@stefanrueger
Copy link
Collaborator

Unluckly .avrdx series' eeprom section don't implement page section that doesn't like other e.g. MEGA3209 does

Is that a real difference of dx parts to non-dx parts? Or is it an omission in avrdude.conf.in?

If the former (that is the dx parts just behave differently) then I guess that the family_id string in avrdude.conf can be used to figure out whether need_progmode checking can be overridden. Typing in bash

$ avrdude -p*/St | grep family_id  | grep -v common

informs me that .dx parts have either the 7-character ID " AVR" or "AVR " (Why two different ones? @mcuee @MCUdude @dl8dtl). So we could use

   // Is this a .dx family part?
   if(strcmp(p->family_id, "AVR    ") == 0 || strcmp(p->family_id, "    AVR") == 0) {
     // Do the right thing
   }

If the latter (dx parts really have paged memory in some sense and the size is 2) then we can change the eeprom page_size property in avrdude.conf.ing

@MCUdude
Copy link
Collaborator

MCUdude commented Mar 3, 2023

informs me that .dx parts have either the 7-character ID " AVR" or "AVR " Why two different ones?

I asked a Microchip developer about this. On the AVR-DA it's AVR, but this is a (silicon?)bug that's too late to fix. That's why the newer AVR-DB/DD/EA have AVR instead.

@stefanrueger
Copy link
Collaborator

Remove need_progmode checking will fix this issue. But I wonder why it exists and if it will bring new issues.

@llinjupt Seeing as you have the part and the programmer, please could you create a PR that fixes the issue. Make sure that your code only changes the normal workings when strcmp(p->family_id, "AVR ") == 0 || strcmp(p->family_id, " AVR") == 0 is true (ie, when it is a dx part) to exclude the possibility for regressions for other parts. When testing, please also check reading/writing all memories for the DX part, not only EEPROM (signature, lock bytes, fuses etc).

Thanks for contributing.

@llinjupt
Copy link
Contributor

llinjupt commented Mar 5, 2023

Remove need_progmode checking will fix this issue. But I wonder why it exists and if it will bring new issues.

@llinjupt Seeing as you have the part and the programmer, please could you create a PR that fixes the issue. Make sure that your code only changes the normal workings when strcmp(p->family_id, "AVR ") == 0 || strcmp(p->family_id, " AVR") == 0 is true (ie, when it is a dx part) to exclude the possibility for regressions for other parts. When testing, please also check reading/writing all memories for the DX part, not only EEPROM (signature, lock bytes, fuses etc).

Thanks for contributing.

I am gald to but I am afraid I am going to mess it up. While searching the whole source code with keyword need_progmode, also found it in jtagmkI.c. After tarcking the git log, there is no clue when and why need_progmode was introduced. Since I am not very familar with AVR chips, would you pelease clarify why it needs to disable prog mode when do byte-writing of EEPROM and FLASH? By intuition,it doesn't make sense to me when do writing without staying in prog mode.In my opinion, it's the key to fix this issue.

On the other hand, I am not sure if there is another AVR series which has no paged EEPROM as the AVR Dx does. If so, that series may have the same issue and this fix doesn't work.

BTW, Interesing there was a page_size = 1 in old avrdude.conf of these Dx parts:

    memory "eeprom"
        page_size = 0x1; // It makes avrdude to call jtagmkII_paged_write instead of jtagmkII_write_byte
        ......
    ;

Why it was removed in 7.1?

@stefanrueger
Copy link
Collaborator

why [disable] prog mode when byte-writing of EEPROM and FLASH

I wouldn't worry about that too much. Above comment suggests the current code base works for older parts, xmega, newer non-dx parts. Sometimes, the firmware of AVR programmers have mysterious ways of working, too. I would not touch that unless you can prove by checking all possible working parts so far that something is not necessary.

I would focus on what needs doing to make programming work for DX parts. Unfortunately, I cannot translate your observations into C code as they are ambiguous to me. I simply don't know how the code would look like when you say "Remove need_progmode checking will fix this issue." Please share working code. Ideally the working C code would only change what's done in case this is a DX part to avoid regression.

Why [was the page_size setting] removed in 7.1?

1 is the default setting for page_size. You can check this yourself:

$ avrdude -pAVR*D*/At | grep eeprom.page_size
.ptmm	AVR32DA28	eeprom	page_size	1
.ptmm	AVR32DA32	eeprom	page_size	1
.ptmm	AVR32DA48	eeprom	page_size	1
.ptmm	AVR64DA28	eeprom	page_size	1
.ptmm	AVR64DA32	eeprom	page_size	1
.ptmm	AVR64DA48	eeprom	page_size	1
.ptmm	AVR64DA64	eeprom	page_size	1
.ptmm	AVR128DA28	eeprom	page_size	1
.ptmm	AVR128DA32	eeprom	page_size	1
.ptmm	AVR128DA48	eeprom	page_size	1
.ptmm	AVR128DA64	eeprom	page_size	1
.ptmm	AVR32DB28	eeprom	page_size	1
.ptmm	AVR32DB32	eeprom	page_size	1
.ptmm	AVR32DB48	eeprom	page_size	1
.ptmm	AVR64DB28	eeprom	page_size	1
.ptmm	AVR64DB32	eeprom	page_size	1
.ptmm	AVR64DB48	eeprom	page_size	1
.ptmm	AVR64DB64	eeprom	page_size	1
.ptmm	AVR128DB28	eeprom	page_size	1
.ptmm	AVR128DB32	eeprom	page_size	1
.ptmm	AVR128DB48	eeprom	page_size	1
.ptmm	AVR128DB64	eeprom	page_size	1
.ptmm	AVR16DD14	eeprom	page_size	1
.ptmm	AVR16DD20	eeprom	page_size	1
.ptmm	AVR16DD28	eeprom	page_size	1
.ptmm	AVR16DD32	eeprom	page_size	1
.ptmm	AVR32DD14	eeprom	page_size	1
.ptmm	AVR32DD20	eeprom	page_size	1
.ptmm	AVR32DD28	eeprom	page_size	1
.ptmm	AVR32DD32	eeprom	page_size	1
.ptmm	AVR64DD14	eeprom	page_size	1
.ptmm	AVR64DD20	eeprom	page_size	1
.ptmm	AVR64DD28	eeprom	page_size	1
.ptmm	AVR64DD32	eeprom	page_size	1

Avrdude 7.1 has powerful options to see how Avrdude understands part and programmer parameters

$ avrdude -p/?
$ avrdude -p/?
avrdude: flags for developer option -p <wildcard>/<flags> not recognised
Wildcard examples (these need protecting in the shell through quoting):
         * all known parts
  ATtiny10 just this part
  *32[0-9] matches ATmega329, ATmega325 and ATmega328
      *32? matches ATmega329, ATmega32A, ATmega325 and ATmega328
Flags (one or more of the characters below):
       d  description of core part features
       A  show entries of avrdude.conf parts with all values
       S  show entries of avrdude.conf parts with necessary values
       s  show short entries of avrdude.conf parts using parent
       r  show entries of avrdude.conf parts as raw dump
       c  check and report errors in address bits of SPI commands
       o  opcodes for SPI programming parts and memories
       w  wd_... constants for ISP parts
       *  all of the above except s and S
       t  use tab separated values as much as possible
       i  inject assignments from source code table
Examples:
  $ avrdude -p ATmega328P/s
  $ avrdude -p m328*/st | grep chip_erase_delay
  avrdude -p*/r | sort
Notes:
  -p * is the same as -p */s
  This help message is printed using any unrecognised flag, eg, -p/h
  Leaving no space after -p can be an OK substitute for quoting in shells
  /s, /S and /A outputs are designed to be used as input in avrdude.conf
  Sorted /r output should stay invariant when rearranging avrdude.conf
  The /c, /o and /w flags are less generic and may be removed sometime
  These options are just to help development, so not further documented

@llinjupt
Copy link
Contributor

llinjupt commented Mar 6, 2023

@stefanrueger

I cannot translate your observations into C code as they are ambiguous to me.

In jtagmkII.c, for your reference:

static int jtagmkII_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
			       unsigned long addr, unsigned char data)
{
  unsigned char cmd[12];
  unsigned char *resp = NULL, writedata, writedata2 = 0xFF;
  int status, tries, need_progmode = 1, unsupp = 0, writesize = 1;

  pmsg_notice2("jtagmkII_write_byte(.., %s, 0x%lx, ...)\n", mem->desc, addr);

  addr += mem->offset;

  writedata = data;
  cmd[0] = CMND_WRITE_MEMORY;
  cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_FLASH: MTYPE_SPM;
  if (strcmp(mem->desc, "flash") == 0) {
     if ((addr & 1) == 1) {
       /* odd address = high byte */
       writedata = 0xFF;	/* don't modify the low byte */
       writedata2 = data;
       addr &= ~1L;
     }
     writesize = 2;
     //need_progmode = 0;      // comment out this line
     PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
     if (pgm->flag & PGM_FL_IS_DW)
       unsupp = 1;
  } else if (strcmp(mem->desc, "eeprom") == 0) {
    cmd[1] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_EEPROM_XMEGA: MTYPE_EEPROM;
    //need_progmode = 0;      // comment out this line
    PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
  }

I am not sure if need to do the same thing in jtagmkI_write_byte() for other programmers, and thanks for other helpful info.

@stefanrueger
Copy link
Collaborator

@llinjupt Like so PR #1318?

@llinjupt
Copy link
Contributor

llinjupt commented Mar 16, 2023

@stefanrueger, see the reference above, that's my solution by removing need_progmode, but I didn't get any response.
@mcuee @MCUdude If anyone of you likes to fix it, this solution is for your reference and feel free.

@stefanrueger
Copy link
Collaborator

see the reference above, that's my solution by removing need_progmode

Well, that's how I implemented it (I think!): the difference is that I have left need_progmode for non-dx parts to avoid potential for regression.

@llinjupt
Copy link
Contributor

llinjupt commented Mar 16, 2023

see the reference above, that's my solution by removing need_progmode

Well, that's how I implemented it (I think!): the difference is that I have left need_progmode for non-dx parts to avoid potential for regression.

IMHO, parts which have page_size (> 1) never call this byte-write funciton, instead, they go jtagmkII_paged_write in which it doesn't bother need_progmode. Anyway, be careful is alway good.

@stefanrueger
Copy link
Collaborator

never call this byte-write funciton

Whilst avrdude might not call this function when page_size > 1, the function is also part of libavrdude. I don't know whether anyone out there has their own application that would stop working when we remove need_progmode. Unless someone can conclusively prove that code fragment is hogwash, I tend not to remove (presumably) working code.

@mcuee
Copy link
Collaborator Author

mcuee commented Mar 18, 2023

Initial test shows PR #1318 is good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants