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

Write flash rarely works in terminal mode for classic AVRs #1020

Closed
stefanrueger opened this issue Jul 7, 2022 · 35 comments
Closed

Write flash rarely works in terminal mode for classic AVRs #1020

stefanrueger opened this issue Jul 7, 2022 · 35 comments
Assignees
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@stefanrueger
Copy link
Collaborator

The reason for this is that terminal mode relies on the generic avr_write_byte() routine

avrdude/src/term.c

Lines 569 to 570 in 64ee485

for (i = 0; i < (len + data.bytes_grown); i++) {
int32_t rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]);

  • Which in turn dispatches to the individual programmer's write byte routine
  • Which in turn more often than not (see below for affected programmers) falls back on avr_write_byte_default()
  • Which in turn only caters for low-level TPI (these cannot write a byte to flash!) and for low-level "classic" AVR ISP
  • Which in turn for flash only does a proper write for 11 parts with byte-write commands (since you asked: ATtiny12, ATtiny15, AT90S1200, AT90S4414, AT90S2313, AT90S2333, AT90S2343, AT90S4433, AT90S4434, AT90S8515, AT90S8535)
  • Which in turn means that for the other 153 classic AVR parts known to AVRDUDE (don't ask) only a page load is carried out
  • Which in turn means that when term.c reads back to check there will be a failure

    avrdude/src/term.c

    Lines 581 to 586 in 64ee485

    rc = pgm->read_byte(pgm, p, mem, addr+i, &b);
    if (b != buf[i]) {
    avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
    progname, buf[i], addr+i, b);
    werror = true;
    }

Affected programmers: avrftdi.c, buspirate.c, ft245r.c, linuxgpio.c, linuxspi.c, par.c, pickit2.c, serbb_posix.c, serbb_win32.c, stk500.c, usbasp.c, usbtiny.c

For those who prefer to test, run avrdude -t with your favourite AVR part and your favourite programmer:

$ echo  'write flash 0x3100 "hello, world\n"' | avrdude -qqp m328p -c usbtiny -t
avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x100 "hello, world\n" 
avrdude (write): error writing 0x68 at 0x03100 cell=0xff
avrdude (write): error writing 0x65 at 0x03101 cell=0xff
avrdude (write): error writing 0x6c at 0x03102 cell=0xff
avrdude (write): error writing 0x6c at 0x03103 cell=0xff
avrdude (write): error writing 0x6f at 0x03104 cell=0xff
avrdude (write): error writing 0x2c at 0x03105 cell=0xff
avrdude (write): error writing 0x20 at 0x03106 cell=0xff
avrdude (write): error writing 0x77 at 0x03107 cell=0xff
avrdude (write): error writing 0x6f at 0x03108 cell=0xff
avrdude (write): error writing 0x72 at 0x03109 cell=0xff
avrdude (write): error writing 0x6c at 0x0310a cell=0xff
avrdude (write): error writing 0x64 at 0x0310b cell=0xff
avrdude (write): error writing 0x5c at 0x0310c cell=0xff
avrdude (write): error writing 0x6e at 0x0310d cell=0xff
avrdude (write): error writing 0x00 at 0x0310e cell=0xff

I have not looked at those programmers that specify their own write byte routine; these might work in terminal mode.

Of course, if any program should be able to modify a flash byte interactively, it should be AVRDUDE, not? Although AVRDUDE started out as a simple uploader/downloader 20 years ago, it's now considered the ultimate AVR programming tool these days.

@stefanrueger
Copy link
Collaborator Author

My proposal is to provide in avr.c generic avr_read_byte_cache() and avr_write_byte_cache() routines that, for programmers that have paged read/write functions,

  • Maintain a page-sized flash read/write cache for all parts with paged flash memory (not only classic AVRs)
  • Maintain a 256-byte EEPROM read/write cache (or less if the EEPROM is smaller) for all parts with EEPROM memory
  • Flush the respective cache (if modified) on switching a page or trying to access a byte outside the valid address range
  • Fall back to avr_read_byte_default() and avr_write_byte_default(), respectively, otherwise

term.c and SPM programmers (which serve bootloaders that normally only have paged r/w) can make use of the avr_..._byte_cache() functions instead of the current avr_..._byte_default() routines.

I have written a cache for the urclock SPM programmer draft that can be utilised here, see #940 (comment)

Thoughts?

@MCUdude
Copy link
Collaborator

MCUdude commented Jul 7, 2022

Of course, if any program should be able to modify a flash byte interactively, it should be AVRDUDE, not? Although AVRDUDE started out as a simple uploader/downloader 20 years ago, it's now considered the ultimate AVR programming tool these days.

Sorry for the short answer, but I'm replying on my phone. I agree with everything you say, and I'm a huge fan of the terminal mode. That's why I spend so much time improving the write command to support other data than bytes, which has turned out to be quite useful for testing purposes.

So would we be able to modify a single byte write access? Perhaps by reading a flash page, modifying the content and writing it back again?

@stefanrueger
Copy link
Collaborator Author

by reading a flash page, modifying the content and writing it back again

Exactly! With a r/w cache (for speed and lest wearing out memory unnecessarily) and using the paged r/w functions of the programmer (for generality)

@stefanrueger
Copy link
Collaborator Author

support other data than bytes

Yes, I noted the addition of strings, etc. Vvv useful!

@stefanrueger stefanrueger self-assigned this Jul 7, 2022
@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 7, 2022

Interesting side note: when I tried to update my STK500 using an AVRISPmkII (as the built-in avr910 loader failed), that doesn't work either – it's an AT90S8535 (where the byte write ought to work) but somehow, stk500v2 broke that. Maybe due to decomissioning the SPI_MULTI command.

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 7, 2022

There are already some programmers implementing caches (I think JTAG programmers). Generalizing that might be a good move.

@dl8dtl dl8dtl added the bug Something isn't working label Jul 7, 2022
@mcuee
Copy link
Collaborator

mcuee commented Jul 8, 2022

Just some quick tests to confirm that there are problems with avrftdi (JTAGkey2), usbasp, usbtinyisp, ft245r (arduino-ft232r) and optiboot (stk500v1 bootloader).

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' | .\avrdude 
-qqp m328p -c jtagkey -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude.exe (write): error writing 0x68 at 0x03100 cell=0xff
avrdude.exe (write): error writing 0x65 at 0x03101 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03102 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03103 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03104 cell=0xff
avrdude.exe (write): error writing 0x2c at 0x03105 cell=0xff
avrdude.exe (write): error writing 0x20 at 0x03106 cell=0xff
avrdude.exe (write): error writing 0x77 at 0x03107 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03108 cell=0xff
avrdude.exe (write): error writing 0x72 at 0x03109 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x0310a cell=0xff
avrdude.exe (write): error writing 0x64 at 0x0310b cell=0xff
avrdude.exe (write): error writing 0x5c at 0x0310c cell=0xff
avrdude.exe (write): error writing 0x6e at 0x0310d cell=0xff
avrdude.exe (write): error writing 0x00 at 0x0310e cell=0xff
avrdude>

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' | .\avrdude -qqp m2560 
-c usbasp -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude.exe (write): error writing 0x68 at 0x03100 cell=0xff
avrdude.exe (write): error writing 0x65 at 0x03101 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03102 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03103 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03104 cell=0xff
avrdude.exe (write): error writing 0x2c at 0x03105 cell=0xff
avrdude.exe (write): error writing 0x20 at 0x03106 cell=0xff
avrdude.exe (write): error writing 0x77 at 0x03107 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03108 cell=0xff
avrdude.exe (write): error writing 0x72 at 0x03109 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x0310a cell=0xff
avrdude.exe (write): error writing 0x64 at 0x0310b cell=0xff
avrdude.exe (write): error writing 0x5c at 0x0310c cell=0xff
avrdude.exe (write): error writing 0x6e at 0x0310d cell=0xff
avrdude.exe (write): error writing 0x00 at 0x0310e cell=0xff
avrdude>

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' | .\avrdude 
-qqp m328p -c usbtiny -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude.exe (write): error writing 0x68 at 0x03100 cell=0xff
avrdude.exe (write): error writing 0x65 at 0x03101 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03102 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03103 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03104 cell=0xff
avrdude.exe (write): error writing 0x2c at 0x03105 cell=0xff
avrdude.exe (write): error writing 0x20 at 0x03106 cell=0xff
avrdude.exe (write): error writing 0x77 at 0x03107 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03108 cell=0xff
avrdude.exe (write): error writing 0x72 at 0x03109 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x0310a cell=0xff
avrdude.exe (write): error writing 0x64 at 0x0310b cell=0xff
avrdude.exe (write): error writing 0x5c at 0x0310c cell=0xff
avrdude.exe (write): error writing 0x6e at 0x0310d cell=0xff
avrdude.exe (write): error writing 0x00 at 0x0310e cell=0xff
avrdude>

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' | .\avrdude 
-qqp m328p -c arduino-ft232r -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude.exe (write): error writing 0x68 at 0x03100 cell=0xff
avrdude.exe (write): error writing 0x65 at 0x03101 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03102 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x03103 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03104 cell=0xff
avrdude.exe (write): error writing 0x2c at 0x03105 cell=0xff
avrdude.exe (write): error writing 0x20 at 0x03106 cell=0xff
avrdude.exe (write): error writing 0x77 at 0x03107 cell=0xff
avrdude.exe (write): error writing 0x6f at 0x03108 cell=0xff
avrdude.exe (write): error writing 0x72 at 0x03109 cell=0xff
avrdude.exe (write): error writing 0x6c at 0x0310a cell=0xff
avrdude.exe (write): error writing 0x64 at 0x0310b cell=0xff
avrdude.exe (write): error writing 0x5c at 0x0310c cell=0xff
avrdude.exe (write): error writing 0x6e at 0x0310d cell=0xff
avrdude.exe (write): error writing 0x00 at 0x0310e cell=0xff
avrdude>

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' | .\avrdude 
-qqp m328p -c arduino -P COM12 -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude.exe (write): error writing 0x68 at 0x03100 cell=0x00
avrdude.exe (write): error writing 0x65 at 0x03101 cell=0x00
avrdude.exe (write): error writing 0x6c at 0x03102 cell=0x00
avrdude.exe (write): error writing 0x6c at 0x03103 cell=0x00
avrdude.exe (write): error writing 0x6f at 0x03104 cell=0x00
avrdude.exe (write): error writing 0x2c at 0x03105 cell=0x00
avrdude.exe (write): error writing 0x20 at 0x03106 cell=0x00
avrdude.exe (write): error writing 0x77 at 0x03107 cell=0x00
avrdude.exe (write): error writing 0x6f at 0x03108 cell=0x00
avrdude.exe (write): error writing 0x72 at 0x03109 cell=0x00
avrdude.exe (write): error writing 0x6c at 0x0310a cell=0x00
avrdude.exe (write): error writing 0x64 at 0x0310b cell=0x00
avrdude.exe (write): error writing 0x5c at 0x0310c cell=0x00
avrdude.exe (write): error writing 0x6e at 0x0310d cell=0x00
avrdude>


But wiring bootloader (stk500v2) works fine.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' | .\avrdude -qqp m2560 
-c wiring -P COM12 -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude>

PICkit 2 (with #1004 fix) also works fine.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' |
.\avrdude_issue1004v1.exe -qqp m2560 -c pickit2 -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude>

@mcuee
Copy link
Collaborator

mcuee commented Jul 8, 2022

@stefanrueger Your prediction is pretty accurate except PICKit2.

@stefanrueger
Copy link
Collaborator Author

@mcuee Many thanks for testing! And for developing a good test bench. I am convinced that this will improve the quality of AVRDUDE over time (actually, it already has!), and it gives us more confidence for merging PRs.

pretty accurate except PICKit2

I still think terminal write won't work for PICKit2. Could you please try the test again after erasing flash.

Explanation: before testing -c pickit2 the test -c wiring succeeded, which means that the test-string was in flash (for the first time in the test series). The test with -c pickit2 tried writing to flash and will have failed, but since the string was actually there from the previous successful -c wiring test, the -c pickit2 avr_write_byte() routine did not notice the problem on reading back().

Maybe include into the test protocol the preparation of the MCU to defined state or alternating test strings between tests?

@mcuee
Copy link
Collaborator

mcuee commented Jul 8, 2022

I still think terminal write won't work for PICKit2. Could you please try the test again after erasing flash.

Explanation: before testing -c pickit2 the test -c wiring succeeded, which means that the test-string was in flash (for the first time in the test series). The test with -c pickit2 tried writing to flash and will have failed, but since the string was actually there from the previous successful -c wiring test, the -c pickit2 avr_write_byte() routine did not notice the problem on reading back().

Maybe include into the test protocol the preparation of the MCU to defined state or alternating test strings between tests?

@stefanrueger
Ah, you are exactly right. PICKit 2 also does not work.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude_issue1004v3.exe -p m2560 -c pickit2 -e

avrdude_issue1004v3.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude_issue1004v3.exe: Device signature = 0x1e9801 (probably m2560)
avrdude_issue1004v3.exe: erasing chip

avrdude_issue1004v3.exe done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> echo  'write flash 0x3100 "hello, world\n"' | 
.\avrdude_issue1004v3.exe -qqp m2560 -c pickit2 -t
avrdude> >>> write flash 0x3100 "hello, world\n"
avrdude_issue1004v3.exe (write): error writing 0x68 at 0x03100 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x65 at 0x03101 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x6c at 0x03102 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x6c at 0x03103 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x6f at 0x03104 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x2c at 0x03105 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x20 at 0x03106 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x77 at 0x03107 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x6f at 0x03108 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x72 at 0x03109 cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x6c at 0x0310a cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x64 at 0x0310b cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x5c at 0x0310c cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x6e at 0x0310d cell=0xff
avrdude_issue1004v3.exe (write): error writing 0x00 at 0x0310e cell=0xff
avrdude>

@mcuee
Copy link
Collaborator

mcuee commented Jul 8, 2022

And I verfied again that wiring bootloader works fine.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude -qqp m2560 -c wiring -P COM6 -t
avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"
avrdude> dump flash 0x3100 0x10
>>> dump flash 0x3100 0x10
3100  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 5c 6e 00 ff  |hello, world\n..|

avrdude> q
>>> q

@mcuee
Copy link
Collaborator

mcuee commented Jul 8, 2022

ATmega328PB should count as classic AVR. xplainedmini programer (built-in programmer for the Microchip ATmega328PB-XMINI) seems to work fine.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude.exe -qqp m328pb -c xplainedmini -t
avrdude>  write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"
avrdude> dump flash 0x3100 0x10
>>> dump flash 0x3100 0x10
3100  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 5c 6e 00 ff  |hello, world\n..|

Then I tested two new UPDI AVRs and they work fine as well.

  1. Arduino Nano Every official board with ATmega4809 and built-in jtag2updi programmer
PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> mode COM7 baud=12 dtr=on > nul
PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> mode COM7 baud=12 dtr=off > nul
PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude.exe -qqp m4809 -c jtag2updi -P COM7 -t
avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"
avrdude> dump flash 0x3100 0x10
>>> dump flash 0x3100 0x10
3100  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 5c 6e 00 ff  |hello, world\n..|
  1. Microchip ATmega128DB48 Curiosity Nano with built-in pkobn_updi programmer.
PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude.exe -c pkobn_updi -qqp avr128db48 -t
             Vtarget                      : 3.31 V
             PDI/UPDI clock Xmega/megaAVR : 100 kHz

avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"
avrdude> dump flash 0x3100 0x10
>>> dump flash 0x3100 0x10
3100  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 5c 6e 00 ff  |hello, world\n..|

@mcuee
Copy link
Collaborator

mcuee commented Jul 8, 2022

AVR109 bootloader for Arduino Leonardo does not seem to support flash write at all in terminal mode.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\leonardo_terminal_test.bat
COM5

Status for device COM5:
-----------------------
    Baud:            1200
    Parity:          None
    Data Bits:       8
    Stop Bits:       1
    Timeout:         OFF
    XON/XOFF:        OFF
    CTS handshaking: OFF
    DSR handshaking: OFF
    DSR sensitivity: OFF
    DTR circuit:     OFF
    RTS circuit:     ON

COM30

Status for device COM30:
------------------------
    Baud:            57600
    Parity:          None
    Data Bits:       8
    Stop Bits:       1
    Timeout:         OFF
    XON/XOFF:        OFF
    CTS handshaking: OFF
    DSR handshaking: OFF
    DSR sensitivity: OFF
    DTR circuit:     OFF
    RTS circuit:     ON


C:\work\avr\avrdude_test\avrdude-7.0_bin64>.\avrdude -p atmega32u4 -c avr109 -P COM30 -b 57600 -t

Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"

Writing |                   | 0% 0.00savrdude (write): error writing 0x68 at 0x03100, rc=-1
write operation not supported on memory type "flash"
avrdude: ser_send(): write error: sorry no info avail
avrdude: ser_recv(): read error: The device does not recognize the command.

avrdude: butterfly_recv(): programmer is not responding
avrdude: error: programmer did not respond to command: set addr
avrdude: ser_send(): write error: sorry no info avail
avrdude: ser_recv(): read error: The device does not recognize the command.

avrdude: butterfly_recv(): programmer is not responding
avrdude (write): error writing 0x68 at 0x03100 cell=0x00
avrdude (write): error writing 0x65 at 0x03101, rc=-1
write operation not supported on memory type "flash"
avrdude (write): error writing 0x65 at 0x03101 cell=0x00
...

@MCUdude
Copy link
Collaborator

MCUdude commented Jul 8, 2022

With ATmega4808, I am not able to write to flash in terminal mode using pickit4_updi, snap_updi, or serialupdi.

$ ./avrdude -cpickit4_updi -patmega4808 -t -qq
         Vtarget                      : 5.06 V
         JTAG clock megaAVR/program   : 1000 kHz
         JTAG clock megaAVR/debug     : 100 kHz
         PDI/UPDI clock Xmega/megaAVR : 100 kHz

avrdude> write flash 0x00 "Hello World!"
>>> write flash 0x00 "Hello World!" 
avrdude (write): error writing 0x48 at 0x00000 cell=0xff
avrdude (write): error writing 0x65 at 0x00001 cell=0xff
avrdude (write): error writing 0x6c at 0x00002 cell=0xff
avrdude (write): error writing 0x6c at 0x00003 cell=0xff
avrdude (write): error writing 0x6f at 0x00004 cell=0xff
avrdude (write): error writing 0x20 at 0x00005 cell=0xff
avrdude (write): error writing 0x57 at 0x00006 cell=0xff
avrdude (write): error writing 0x6f at 0x00007 cell=0xff
avrdude (write): error writing 0x72 at 0x00008 cell=0xff
avrdude (write): error writing 0x6c at 0x00009 cell=0xff
avrdude (write): error writing 0x64 at 0x0000a cell=0xff
avrdude (write): error writing 0x21 at 0x0000b cell=0xff
avrdude (write): error writing 0x00 at 0x0000c cell=0xff
avrdude> read flash 0 0x40
>>> read flash 0 0x40 
0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> q
>>> q 

$ ./avrdude -csnap_updi -patmega4808 -t -qq
avrdude: usbhid_open(): No device found
         Vtarget                      : 5.06 V
         JTAG clock megaAVR/program   : 1000 kHz
         JTAG clock megaAVR/debug     : 100 kHz
         PDI/UPDI clock Xmega/megaAVR : 100 kHz

avrdude> write flash 0x00 "Hello World!"
>>> write flash 0x00 "Hello World!" 
avrdude (write): error writing 0x48 at 0x00000 cell=0xff
avrdude (write): error writing 0x65 at 0x00001 cell=0xff
avrdude (write): error writing 0x6c at 0x00002 cell=0xff
avrdude (write): error writing 0x6c at 0x00003 cell=0xff
avrdude (write): error writing 0x6f at 0x00004 cell=0xff
avrdude (write): error writing 0x20 at 0x00005 cell=0xff
avrdude (write): error writing 0x57 at 0x00006 cell=0xff
avrdude (write): error writing 0x6f at 0x00007 cell=0xff
avrdude (write): error writing 0x72 at 0x00008 cell=0xff
avrdude (write): error writing 0x6c at 0x00009 cell=0xff
avrdude (write): error writing 0x64 at 0x0000a cell=0xff
avrdude (write): error writing 0x21 at 0x0000b cell=0xff
avrdude (write): error writing 0x00 at 0x0000c cell=0xff
avrdude> read flash 0 0x40
>>> read flash 0 0x40 
0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> q
>>> q 

$ ./avrdude -cserialupdi -P /dev/cu.usbserial-1410 -patmega4808 -t -qq
avrdude: UPDI link initialization OK
avrdude: NVM type 0: 16-bit, page oriented write
avrdude: Entering NVM programming mode
avrdude> write flash 0x00 "Hello World!"
>>> write flash 0x00 "Hello World!" 
avrdude: Commit data command failed
avrdude (write): error writing 0x48 at 0x00000, rc=-1
write operation not supported on memory type "flash"
avrdude (write): error writing 0x48 at 0x00000 cell=0x00
^C

With ATmega32, pickit4_isp and snap_isp flash write works. However, I'm only able to write zeros, so a chip erase is necessary to flip the bits. It would be really cool if we could read a page, erase the page and write back the modified content.

$ ./avrdude -cpickit4_isp -patmega32 -t -qq
avrdude> write flash 0x00 0x10 0x55 ...
>>> write flash 0x00 0x10 0x55 ... 
avrdude> read flash 0x00 0x40
>>> read flash 0x00 0x40 
0000  55 55 55 55 55 55 55 55  55 55 55 55 55 55 55 55  |UUUUUUUUUUUUUUUU|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0x00 0x10 0xAA ...
>>> write flash 0x00 0x10 0xAA ... 
avrdude: stk500v2_paged_write: write command failed
avrdude> read flash 0x00 0x40
>>> read flash 0x00 0x40 
0000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 aa  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> q
>>> q 

$ ./avrdude -csnap_isp -patmega32 -t -qq
avrdude: usbhid_open(): No device found
avrdude> write flash 0x20 0x10 0x55 ...
>>> write flash 0x20 0x10 0x55 ... 
avrdude> read flash 0x00 0x40
>>> read flash 0x00 0x40 
0000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0020  55 55 55 55 55 55 55 55  55 55 55 55 55 55 55 55  |UUUUUUUUUUUUUUUU|
0030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0x20 0x10 0xaa ...
>>> write flash 0x20 0x10 0xaa ... 
avrdude: stk500v2_paged_write: write command failed
avrdude> read flash 0x00 0x40
>>> read flash 0x00 0x40 
0000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 aa  |................|
0030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> q
>>> q 

@mcuee
Copy link
Collaborator

mcuee commented Jul 9, 2022

@MCUdude
Yes it will be great that we could read a page, erase the page and write back the modified content, for both Flash and EEPROM.

BTW, it is very strange that pickit4_updi and snap_updi perform differently from pkobn_updi.
I am not familiar with serialupdi -- I thought it should be similar to jtag2updi but they seem to perform differently for the ATmega4808.

@mcuee
Copy link
Collaborator

mcuee commented Jul 9, 2022

@stefanrueger
So the issue may be more than classic AVRs and may affect more programmers. Not so sure if the root cause is the same or not, but the solution may be the same as you mentioned.

@mcuee
Copy link
Collaborator

mcuee commented Jul 9, 2022

@MCUdude
I think I have the similar issue as your second issue (pickit4_isp and snap_isp) after the initial good flash write with my Nano 4808. Looks like a page erase is needed between two flash write operation.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude.exe -qqp m4808 -c jtag2updi -P COM29 -t
avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"
avrdude> dump flash 0x3100 0x10
>>> dump flash 0x3100 0x10
3100  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 5c 6e 00 ff  |hello, world\n..|

avrdude> write flash 0x3100 "Good morning, world\n"
>>> write flash 0x3100 "Good morning, world\n"
avrdude.exe (write): error writing 0x47 at 0x03100 cell=0x40
avrdude.exe (write): error writing 0x6f at 0x03101 cell=0x65
avrdude.exe (write): error writing 0x6f at 0x03102 cell=0x6c
avrdude.exe (write): error writing 0x6d at 0x03105 cell=0x2c
avrdude.exe (write): error writing 0x6f at 0x03106 cell=0x20
avrdude.exe (write): error writing 0x69 at 0x03109 cell=0x60
avrdude.exe (write): error writing 0x6e at 0x0310a cell=0x6c
avrdude.exe (write): error writing 0x67 at 0x0310b cell=0x64
avrdude.exe (write): error writing 0x2c at 0x0310c cell=0x0c
avrdude.exe (write): error writing 0x77 at 0x0310e cell=0x00
avrdude> dump flash 0x3100 0x20
>>> dump flash 0x3100 0x20
3100  40 65 6c 64 20 2c 20 72  6e 60 6c 64 0c 20 00 6f  |@eld , rn`ld  .o|
3110  72 6c 64 5c 6e 00 ff ff  ff ff ff ff ff ff ff ff  |rld\n...........|

Same for the the ATmega328PB with xplainedmini.

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude.exe -qqp m328pb -c xplainedmini -e
PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude.exe -qqp m328pb -c xplainedmini -t
avrdude> write flash 0x3100 "Good morning, world\n"
>>> write flash 0x3100 "Good morning, world\n"
avrdude> dump flash 0x3100 0x20
>>> dump flash 0x3100 0x20
3100  47 6f 6f 64 20 6d 6f 72  6e 69 6e 67 2c 20 77 6f  |Good morning, wo|
3110  72 6c 64 5c 6e 00 ff ff  ff ff ff ff ff ff ff ff  |rld\n...........|

avrdude> write flash 0x3100 "Hello, world\n"
>>> write flash 0x3100 "Hello, world\n"
avrdude> dump flash 0x3100 0x20
>>> dump flash 0x3100 0x20
3100  40 65 6c 64 20 2c 20 72  6e 60 6c 64 0c 20 00 6f  |@eld , rn`ld  .o|
3110  72 6c 64 5c 6e 00 ff ff  ff ff ff ff ff ff ff ff  |rld\n...........|

@mcuee
Copy link
Collaborator

mcuee commented Jul 9, 2022

Same for an AVRISPMKII clone and a STK500v2 clone (just got them today, the STK500v2 clone is just the programming part and do not support high voltage isp).

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude_issue1004v3.exe -c avrispmkII  -p m328p -t

avrdude_issue1004v3.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude_issue1004v3.exe: Device signature = 0x1e950f (probably m328p)
avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"

Writing | ################################################## | 100% 0.80s

avrdude> dump flash 0x3100 0x20
>>> dump flash 0x3100 0x20

Reading | ################################################## | 100% 0.06s

3100  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 5c 6e 00 ff  |hello, world\n..|
3110  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0x3100 "Good morning, world\n"
>>> write flash 0x3100 "Good morning, world\n"

Writing | ################################################## | 100% 1.23s

avrdude> dump flash 0x3100 0x20
>>> dump flash 0x3100 0x20

Reading | ################################################## | 100% 0.06s

3100  40 65 6c 64 20 2c 20 72  6e 60 6c 64 0c 20 00 6f  |@eld , rn`ld  .o|
3110  72 6c 64 5c 6e 00 ff ff  ff ff ff ff ff ff ff ff  |rld\n...........|

PS C:\work\avr\avrdude_test\avrdude-7.0_bin64> .\avrdude_issue1004v3.exe -c stk500v2 -P COM6  -qqp m328p -t
avrdude> erase flash
>>> erase flash
avrdude_issue1004v3.exe: erasing chip
avrdude> write flash 0x3100 "hello, world\n"
>>> write flash 0x3100 "hello, world\n"
avrdude> dump flash 0x3100 0x20
>>> dump flash 0x3100 0x20
3100  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 5c 6e 00 ff  |hello, world\n..|
3110  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0x3100 "Good morning, world\n"
>>> write flash 0x3100 "Good morning, world\n"
avrdude> dump flash 0x3100 0x20
>>> dump flash 0x3100 0x20
3100  40 65 6c 64 20 2c 20 72  6e 60 6c 64 0c 20 00 6f  |@eld , rn`ld  .o|
3110  72 6c 64 5c 6e 00 ff ff  ff ff ff ff ff ff ff ff  |rld\n...........|

@stefanrueger
Copy link
Collaborator Author

Before starting on the flash write problem I checked a few edge cases of integer inputs for terminal write. I know from experience that parsing number strings in C is hard. Real hard (so I know where to look ;).

Analysis of the few detected edge-case problems below. I have now read the source and know what to do to fix the problems.

For the out-of-range problems it's best to make a distinction between unsigned and signed data types. Easy, I'll add the U suffix just like C. Unlike C I plan to treat hex constants without 'U' as unsigned, as users would not understand that 0xff as a signed data type would require two bytes (highest signed byte is 0x7f). Generally, I'd like to treat hex numbers "special" to "do the right thing", for example, making 0x0002 write 2 bytes, so that people can cut and paste tables.

Also, I'd like to introduce double as new data type for terminal write (in anticipation of Jörg's promised avr-libc extension for 64-bit double @dl8dtl ;), and get strings and character constants parsed like in C. I have code that I wrote for another project, so that's straightforward.

I expect a PR soon-ish for making term.c ready to deal with the write flash problem, but if anyone has a comment or different suggestion, do drop a line.

Here my test analysis:

$ avrdude -qqp m328p -c usbtiny -t
avrdude> write eeprom 0x180 16 0x55 ...
>>> write eeprom 0x180 16 0x55 ...
avrdude> read  eeprom 0x180 16
>>> read  eeprom 0x180 16
0180  55 55 55 55 55 55 55 55  55 55 55 55 55 55 55 55  |UUUUUUUUUUUUUUUU|

Above write in fill mode initialises 16 bytes with 0x55: cool feature! This is used in all tests to "clear the canvas" like so:

$ avrdude -qqp m328p -c usbtiny -t
avrdude> write eeprom 0x180 16 0x55 ...
>>> write eeprom 0x180 16 0x55 ... 
avrdude> write eeprom 0x182 0xff
>>> write eeprom 0x182 0xff 
avrdude> read  eeprom 0x180 16
>>> read eeprom 0x180 16 
0180  55 55 ff 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

This write command writes one byte, 0xff, to EEPROM location 0x182. Works as expected!

The following tests all clear the canvas, carry out one write and then show the read back. For clarity only the relevant write and the read-back will be shown, but each test was carried out as above.

avrdude> write eeprom 0x182 0xff
0180  55 55 ff 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

Same as above.

avrdude> write eeprom 0x182 -128
0180  55 55 80 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

Good. As expected.

avrdude> write eeprom 0x182 0177
0180  55 55 7f 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

Octal, perfect.

avrdude> write eeprom 0x182 "hi"
0180  55 55 68 69 00 55 55 55  55 55 55 55 55 55 55 55  |UUhi.UUUUUUUUUUU|

Strings. Cool.

avrdude> write eeprom 0x182 01234567
Warning: no size suffix specified for "01234567". Writing 4 byte(s)
0180  55 55 77 39 05 00 55 55  55 55 55 55 55 55 55 55  |UUw9..UUUUUUUUUU|

Octal 01234567 is 0x53977, indeed. Might be neater if a number used the min space of 1, 2, 4, 8 bytes without warning?

avrdude> write eeprom 0x182 'a'
0180  55 55 61 55 55 55 55 55  55 55 55 55 55 55 55 55  |UUaUUUUUUUUUUUUU|

Characters. Cool.

avrdude> write eeprom 0x182 "hi" 0x1234 'a'
0180  55 55 68 69 00 34 12 61  55 55 55 55 55 55 55 55  |UUhi.4.aUUUUUUUU|

Mixed use. Very cool.

avrdude> write eeprom 0x182 12 "hi" ...
0180  55 55 68 69 00 68 69 00  68 69 00 68 69 00 55 55  |UUhi.hi.hi.hi.UU|

Fill mode repeats the string. How cool is that?

avrdude> write eeprom 0x182 13 "hit" ...
0180  55 55 68 69 74 00 68 69  74 00 68 69 74 00 68 55  |UUhit.hit.hit.hU|

... and fills until it runs out of road. Very good.

avrdude> write eeprom 0x182 12 "hi" 01234567 ...
Warning: no size suffix specified for "01234567". Writing 4 byte(s)
0180  55 55 68 69 00 77 39 05  00 77 39 05 00 77 55 55  |UUhi.w9..w9..wUU|

Same if the last argument is a 4-byte long. Good.

avrdude> write eeprom 0x182 127L
0180  55 55 7f 00 00 00 55 55  55 55 55 55 55 55 55 55  |UU....UUUUUUUUUU|

Explicit size works fine.

avrdude> write eeprom 0x182 12 "abc" 127L ...
0180  55 55 61 62 63 00 7f 00  00 00 7f 7f 7f 7f 55 55  |UUabc.........UU|

Bug? What happened to the "repeat last item" fill? Not expecting that only 0x7f gets filled?

avrdude> write eeprom 0x182 -128L
0180  55 55 80 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

Bug? Why is -128L not a long?

avrdude> write eeprom 0x182 12 "abc" -128L ...
0180  55 55 61 62 63 00 80 80  80 80 80 80 80 80 55 55  |UUabc.........UU|

Again, only low byte of the long is used for filling.

avrdude> write eeprom 0x182 -0xff
Warning: no size suffix specified for "-0xff". Writing 1 byte(s)
0180  55 55 01 ff 55 55 55 55  55 55 55 55 55 55 55 55  |UU..UUUUUUUUUUUU|

In signed interpretation this should write two bytes (-255 does not fit into one byte as signed), and it does. But why a warning saying one byte is being written?

avrdude> write eeprom 0x182 +0xff
0180  55 55 0f 00 00 00 55 55  55 55 55 55 55 55 55 55  |UU....UUUUUUUUUU|

Bug? Why is 0x0f written, not 0xff?

avrdude> write eeprom 0x182 0xffff
0180  55 55 ff ff 55 55 55 55  55 55 55 55 55 55 55 55  |UU..UUUUUUUUUUUU|

Good. As expected.

avrdude> write eeprom 0x182 0xffffFFFF
0180  55 55 ff ff ff ff 55 55  55 55 55 55 55 55 55 55  |UU....UUUUUUUUUU|

Good. As expected.

avrdude> write eeprom 0x182 0xffffFFFFffffFFFF
0180  55 55 ff ff ff ff ff ff  ff 7f 55 55 55 55 55 55  |UU........UUUUUU|

Bug? Why is 0x7fffFFFFffffFFFF written?

avrdude> write eeprom 0x182 0x0123456789abcdef
0180  55 55 ef cd ab 89 67 45  23 01 55 55 55 55 55 55  |UU....gE#.UUUUUU|

This is correct, as expected.

avrdude> write eeprom 0x182 0x89abcdef01234567
0180  55 55 ff ff ff ff ff ff  ff 7f 55 55 55 55 55 55  |UU........UUUUUU|

Bug? Again 0x7fffFFFFffffFFFF is written, but input completely different. There seems to be a problem when an 64-bit input has the high bit set.

avrdude> write eeprom 0x182 -0xff
Warning: no size suffix specified for "-0xff". Writing 1 byte(s)
0180  55 55 01 ff 55 55 55 55  55 55 55 55 55 55 55 55  |UU..UUUUUUUUUUUU|

Picking up on -0xff... tests. Seen this before.

avrdude> write eeprom 0x182 -0xffff
Warning: no size suffix specified for "-0xffff". Writing 2 byte(s)
0180  55 55 01 00 ff ff 55 55  55 55 55 55 55 55 55 55  |UU....UUUUUUUUUU|

4 bytes correctly written, but warning says 2 bytes.

avrdude> write eeprom 0x182 -0xffffFFFF
Warning: no size suffix specified for "-0xffffFFFF". Writing 4 byte(s)
0180  55 55 01 00 00 00 ff ff  ff ff 55 55 55 55 55 55  |UU........UUUUUU|

8 bytes correctly written, but warning says 4 bytes.

avrdude> write eeprom 0x182 -0xffffFFFFffffFFFF
Warning: no size suffix specified for "-0xffffFFFFffffFFFF". Writing 1 byte(s)
0180  55 55 00 00 00 00 00 00  00 80 55 55 55 55 55 55  |UU........UUUUUU|

OK, if 0xffffFFFFffffFFFF is interpreted as C-style unsigned number, then -0xffffFFFFffffFFFF should be 1. Interpreted as signed number this should be an "out of range" error. However, 0x8000000000000000 is written.

avrdude> write eeprom 0x182 0x00ff
0180  55 55 ff 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

This is correct, but (as a suggestion for improvement) it might be neater if two bytes were written (think a table of hex words being cut and paste)

avrdude> write eeprom 0x182 0x000000ff
0180  55 55 ff 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

Correct, but might be neater if 4 bytes were written.

avrdude> write eeprom 0x182 0x00000000000000ff
0180  55 55 ff 55 55 55 55 55  55 55 55 55 55 55 55 55  |UU.UUUUUUUUUUUUU|

Correct, but might be neater if 8 bytes were written.

avrdude> write eeprom 0x182 9223372036854775807
Warning: no size suffix specified for "9223372036854775807". Writing 8 byte(s)
0180  55 55 ff ff ff ff ff ff  ff 7f 55 55 55 55 55 55  |UU........UUUUUU|

Correct.

avrdude> write eeprom 0x182 -9223372036854775807
Warning: no size suffix specified for "-9223372036854775807". Writing 8 byte(s)
0180  55 55 01 00 00 00 00 00  00 80 55 55 55 55 55 55  |UU........UUUUUU|

Correct.

avrdude> write eeprom 0x182 18446744073709551615
Warning: no size suffix specified for "18446744073709551615". Writing 8 byte(s)
0180  55 55 ff ff ff ff ff ff  ff 7f 55 55 55 55 55 55  |UU........UUUUUU|

Input is 2^64-1, but 2^63-1 is written. Probably the same (undetected) overflow error as before.

avrdude> write eeprom 0x182 -18446744073709551615
0180  55 55 00 00 00 00 00 00  00 80 55 55 55 55 55 55  |UU........UUUUUU|

Input is -2^64+1, but -2^63 is written. Probably the same (undetected) overflow error as before.

@stefanrueger
Copy link
Collaborator Author

Here the worked out proposal for data representation in terminal write:

Usage: write <memory> <addr> <data>[,] {<data>[,]} 
       write <memory> <addr> <len> <data>[,] {<data>[,]} ...

Ellipsis ... writes <len> bytes padded by repeating the last <data> item.

<data> can be hexadecimal, octal or decimal integers, double, float,
C-style strings and chars. For numbers, an optional case-insensitive suffix
specifies the data size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit, F:
32-bit float. Hexadecimal floating point notation is supported. The 
ambiguous trailing F in 0x1.8F makes the number be interpreted as double;
use a zero exponent as in 0x1.8p0F to denote a hexadecimal float.

An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.

Ordinary 0x hex numbers with n hex digits (counting leading zeros) use    
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them  
in their respective representation.

@MCUdude
Copy link
Collaborator

MCUdude commented Jul 11, 2022

Analysis of the few detected edge-case problems below. I have now read the source and know what to do to fix the problems.

Thanks for taking your time to look at some of the terminal write edge cases. It looks like I haven't tested all of them myself, so there are obviously a few bugs left. If you have a solution for this, it would be great with a separate PR for this. I'll admit that I've never worked with C strings like this before, so it was quite a challenge to get it (almost) right.

Unlike C I plan to treat hex constants without 'U' as unsigned, as users would not understand that 0xff as a signed data type would require two bytes (highest signed byte is 0x7f).

Please do!

Generally, I'd like to treat hex numbers "special" to "do the right thing", for example, making 0x0002 write 2 bytes, so that people can cut and paste tables.

I agree! When thinking about it, I would also expect 0x0002 to write two bytes.

Also, I'd like to introduce double as new data type for terminal write (in anticipation of Jörg's promised avr-libc extension for 64-bit double [at]dl8dtl

Great! I never got time to look at this myself. Perhaps with suffix d or D?

... and get strings and character constants parsed like in C

Can you elaborate? Change how strings in double-quotes and characters in single-quotes are handled?

Here the worked out proposal for data representation in terminal write: ...

Looks great to me! Way better than a Norwegian like me could come up with. I'll assume this would be added to the TEXI documentation and perhaps the manpage?

@stefanrueger
Copy link
Collaborator Author

@MCUdude PR #1025 available. I take it you volunteer to review? ;) Thanks!

added to the TEXI documentation and perhaps the manpage

Sure, I'd like to avoid git conflicts, so prob after the PR queue has come down. I am confident @dl8dtl won't complain if we get those merged that are useful, fix problems and have been tested.

strings and character constants parsed like in C

un-escaping backslash: '\n' or `"house\tyard\tgarden\n"

For now double without suffix are the default, suffix 'F' makes them 32-bit float (as before).

@mcuee
Copy link
Collaborator

mcuee commented Jul 30, 2022

Just an update: PR #1025 has been merged.

@mcuee
Copy link
Collaborator

mcuee commented Jul 30, 2022

Finally I got avr109 bootloader working with Arduino Uno (ATmega328p, tested with avrdude and avrosp2). But it does not seem to support Flash writing in terminal mode even with all the bootloader options enabled. EEPROM support is okay.

Ref: avrosp2: https://xdevs.com/doc/xDevs.com/M16/AVROSP2/

/* Uncomment the following to save code space */
//#define REMOVE_AVRPROG_SUPPORT
//#define REMOVE_FUSE_AND_LOCK_BIT_SUPPORT
//#define REMOVE_BLOCK_SUPPORT
//#define REMOVE_EEPROM_BYTE_SUPPORT
//#define REMOVE_FLASH_BYTE_SUPPORT

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_git.exe -c avr109 -P COM9
 -b 57600 -qqp m328p -D -t
Connecting to programmer: .
Found programmer: Id = "AVRBOOT"; type = S
    Software Version = 1.5; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:

avrdude> write flash 0x3100 "Good morning, world\n"
>>> write flash 0x3100 "Good morning, world\n"
avrdude_git.exe (write): error writing 0x47 at 0x03100, rc=-1
                         write operation not supported on memory type flash
avrdude_git.exe (write): error writing 0x47 at 0x03100 cell=0xff
avrdude_git.exe (write): error writing 0x6f at 0x03101, rc=-1
                         write operation not supported on memory type flash
avrdude_git.exe (write): error writing 0x6f at 0x03101 cell=0xff
...

avrdude> write eeprom 0x180 16 0x55 ...
>>> write eeprom 0x180 16 0x55 ...
avrdude> write eeprom 0x182 "hi" 0x1234 'a'
>>> write eeprom 0x182 "hi" 0x1234 'a'
avrdude> read  eeprom 0x180 16
>>> read eeprom 0x180 16
0180  55 55 68 69 00 34 12 61  55 55 55 55 55 55 55 55  |UUhi.4.aUUUUUUUU|

@mcuee
Copy link
Collaborator

mcuee commented Aug 22, 2022

FYI as well.
https://avrdudes.github.io/avrdude/7.0/avrdude_39.html#Troubleshooting

Problem: Updating the flash ROM from terminal mode does not work with the JTAG ICEs.

Solution: None at this time. Currently, the JTAG ICE code cannot write to the flash ROM one byte at a time.

Not so sure if the issue is only relevant to JTAG1 or it affects JTAG2 (JTAGICE mkii or AVR Dragon) and JTAG3 (JTAG ICE 3 and Atmel-ICE and Power Debugger) in JTAG mode.
[Note: PICKit 4 and SNAP do not work in JTAG mode yet}.

  1. JTAG 1
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c jtag1 -P COM2 -qqp m128a -t
avrdude> dump flash 0 0x20
>>> dump flash 0 0x20
0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0 "hello, world\n"
>>> write flash 0 "hello, world\n"
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x68 at 0x00000 cell=0x00
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp  )
avrdude.exe (write): error writing 0x65 at 0x00001 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6c at 0x00002, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6c at 0x00002 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6c at 0x00003, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6c at 0x00003 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6f at 0x00004, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6f at 0x00004 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x2c at 0x00005, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x2c at 0x00005 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x20 at 0x00006, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x20 at 0x00006 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x77 at 0x00007, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x77 at 0x00007 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6f at 0x00008, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6f at 0x00008 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x72 at 0x00009, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x72 at 0x00009 cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6c at 0x0000a, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x6c at 0x0000a cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x64 at 0x0000b, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x64 at 0x0000b cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x0a at 0x0000c, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x0a at 0x0000c cell=0x00
avrdude.exe: jtagmkI_program_disable(): timeout/error communicating with programmer (resp )
avrdude.exe (write): error writing 0x00 at 0x0000d, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkI_read_byte(): timeout/error communicating with programmer (resp )

JTAG2 (AVR Dragon in JTAG mode).

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c dragon_jtag -qqp m128a -e
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c dragon_jtag -qqp m128a -t
avrdude> dump flash 0 0x10
>>> dump flash 0 0x10
0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0 "hello world"
>>> write flash 0 "hello world"
avrdude.exe: jtagmkII_write_byte(): bad response to write memory command: RSP_FAILED
avrdude.exe (write): error writing 0x68 at 0x00000, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x68 at 0x00000 cell=0x00
avrdude.exe: jtagmkII_program_disable(): bad response to leave progmode command: 
Unknown JTAG ICE mkII result code 0x82
avrdude.exe (write): error writing 0x65 at 0x00001, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x65 at 0x00001 cell=0x00
avrdude.exe: jtagmkII_write_byte(): bad response to write memory command: RSP_FAILED
avrdude.exe (write): error writing 0x6c at 0x00002, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x6c at 0x00002 cell=0x00
avrdude.exe: jtagmkII_program_disable(): bad response to leave progmode command: 
Unknown JTAG ICE mkII result code 0x82
avrdude.exe (write): error writing 0x6c at 0x00003, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x6c at 0x00003 cell=0x00
avrdude.exe: jtagmkII_write_byte(): bad response to write memory command: RSP_FAILED
avrdude.exe (write): error writing 0x6f at 0x00004, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x6f at 0x00004 cell=0x00
avrdude.exe: jtagmkII_program_disable(): bad response to leave progmode command: 
Unknown JTAG ICE mkII result code 0x82
avrdude.exe (write): error writing 0x20 at 0x00005, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x20 at 0x00005 cell=0x00
avrdude.exe: jtagmkII_write_byte(): bad response to write memory command: RSP_FAILED
avrdude.exe (write): error writing 0x77 at 0x00006, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x77 at 0x00006 cell=0x00
avrdude.exe: jtagmkII_program_disable(): bad response to leave progmode command: 
Unknown JTAG ICE mkII result code 0x82
avrdude.exe (write): error writing 0x6f at 0x00007, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x6f at 0x00007 cell=0x00
avrdude.exe: jtagmkII_write_byte(): bad response to write memory command: RSP_FAILED
avrdude.exe (write): error writing 0x72 at 0x00008, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x72 at 0x00008 cell=0x00
avrdude.exe: jtagmkII_program_disable(): bad response to leave progmode command: 
Unknown JTAG ICE mkII result code 0x82
avrdude.exe (write): error writing 0x6c at 0x00009, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x6c at 0x00009 cell=0x00
avrdude.exe: jtagmkII_write_byte(): bad response to write memory command: RSP_FAILED
avrdude.exe (write): error writing 0x64 at 0x0000a, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude.exe (write): error writing 0x64 at 0x0000a cell=0x00
avrdude.exe: jtagmkII_program_disable(): bad response to leave progmode command: 
Unknown JTAG ICE mkII result code 0x82
avrdude.exe (write): error writing 0x00 at 0x0000b, rc=-1
                     write operation not supported on memory type flash
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: 
Unknown JTAG ICE mkII result code 0x80
avrdude> dump flash 0 0x10
>>> dump flash 0 0x10
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: RSP_ILLEGAL_MCU_STATE
avrdude.exe (dump): error reading flash address 0x00000 of part ATmega128A
                    read operation not supported on memory type flash
avrdude> dump flash 0 0x10
>>> dump flash 0 0x10
avrdude.exe: jtagmkII_read_byte(): bad response to read memory command: RSP_ILLEGAL_MCU_STATE
avrdude.exe (dump): error reading flash address 0x00000 of part ATmega128A
                    read operation not supported on memory type flash
avrdude> quit
>>> quit
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c dragon_jtag -qqp m128a -t
avrdude> dump flash 0 0x10
>>> dump flash 0 0x10
0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

@mcuee
Copy link
Collaborator

mcuee commented Aug 22, 2022

@MCUdude
Please help to check out Atmel ICE (JTAG mode) in terms of flash writing in terminal mode.

@dl8dtl
Is this an avrdude limitation or it is a general limitation of JTAG mode?

@MCUdude
Copy link
Collaborator

MCUdude commented Aug 22, 2022

@MCUdude
Please help to check out Atmel ICE (JTAG mode) in terms of flash writing in terminal mode.

Writing zeros works, but writing 1's doesn't.

Atmel ICE (JTAG) and ATmega128

$ ./avrdude -catmelice -patmega128 -t

         Vtarget                      : 5.03 V
         JTAG clock megaAVR/program   : 1500 kHz
         JTAG clock megaAVR/debug     : 200 kHz
         JTAG clock Xmega             : 1000 kHz
         PDI/UPDI clock Xmega/megaAVR : 500 kHz

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9702 (probably m128)
avrdude> read flash 0x1000 0x100
>>> read flash 0x1000 0x100 

Reading | ################################################## | 100% 0.01s

1000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1050  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1060  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1070  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1080  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10c0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10d0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10f0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0x1000 "Hello World! 1234567890"
>>> write flash 0x1000 "Hello World! 1234567890" 

Writing | ################################################## | 100% 1.07s

avrdude> read flash 0x1000 0x100
>>> read flash 0x1000 0x100 

Reading | ################################################## | 100% 0.00s

1000  48 65 6c 6c 6f 20 57 6f  72 6c 64 21 20 31 32 33  |Hello World! 123|
1010  34 35 36 37 38 39 30 00  ff ff ff ff ff ff ff ff  |4567890.........|
1020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1050  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1060  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1070  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1080  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10c0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10d0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10f0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> quit
>>> quit 

avrdude done.  Thank you.

Atmel ICE (JTAG) and AT90CAN128

$ ./avrdude -catmelice -pat90can128 -t

         Vtarget                      : 5.03 V
         JTAG clock megaAVR/program   : 1500 kHz
         JTAG clock megaAVR/debug     : 200 kHz
         JTAG clock Xmega             : 1000 kHz
         PDI/UPDI clock Xmega/megaAVR : 500 kHz

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9781 (probably c128)
avrdude> read flash 0x1000 0x100
>>> read flash 0x1000 0x100 

Reading | ################################################## | 100% 0.01s

1000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1050  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1060  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1070  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1080  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10c0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10d0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10f0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> write flash 0x1000 "Hello World! 1234567890"
>>> write flash 0x1000 "Hello World! 1234567890" 

Writing | ################################################## | 100% 1.07s

avrdude> read flash 0x1000 0x100
>>> read flash 0x1000 0x100 

Reading | ################################################## | 100% 0.00s

1000  48 65 6c 6c 6f 20 57 6f  72 6c 64 21 20 31 32 33  |Hello World! 123|
1010  34 35 36 37 38 39 30 00  ff ff ff ff ff ff ff ff  |4567890.........|
1020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1050  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1060  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1070  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1080  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
1090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10c0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10d0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
10f0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> quit
>>> quit 

avrdude done.  Thank you.

@mcuee
Copy link
Collaborator

mcuee commented Aug 23, 2022

https://avrdudes.github.io/avrdude/7.0/avrdude_39.html#Troubleshooting

Problem: Updating the flash ROM from terminal mode does not work with the JTAG ICEs.

Solution: None at this time. Currently, the JTAG ICE code cannot write to the flash ROM one byte at a time.

Based on the test results, the solution may need some minor updates.

Something like the following.

Solution: None at this time. Currently, jtagmkI and jtagmkII codes cannot write to the flash ROM one byte at a time. jtag3 codes may be able to write 0's to EEPROM but not 1's.

@mcuee mcuee added the enhancement New feature or request label Aug 23, 2022
@mcuee
Copy link
Collaborator

mcuee commented Aug 24, 2022

From the following datasheet, by right JTAG can write Flash in words (two bytes) or in Page, after chip erase (can not write 1's).

https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8151-8-bit-AVR-ATmega128A_Datasheet.pdf

For JTAG

31.10.17. Programming the Flash
Before programming the Flash a Chip Erase must be performed. See Performing Chip Erase on page 410.

  1. Enter JTAG instruction PROG_COMMANDS.
  2. Enable Flash write using programming instruction 2a.
  3. Load address high byte using programming instruction 2b.
  4. Load address low byte using programming instruction 2c.
  5. Load data using programming instructions 2d, 2e and 2f.
  6. Repeat steps 4 and 5 for all instruction words in the page.
  7. Write the page using programming instruction 2g.
  8. Poll for Flash write complete using programming instruction 2h, or wait for tWLRH (refer to table Parallel Programming Characteristics, VCC = 5V ±10% in chapter Parallel Programming Characteristics).
  9. Repeat steps 3 to 7 until all data have been programmed.

A more efficient data transfer can be achieved using the PROG_PAGELOAD instruction:

  1. Enter JTAG instruction PROG_COMMANDS.
  2. Enable Flash write using programming instruction 2a.
  3. Load the page address using programming instructions 2b and 2c. PCWORD (refer to Table 31-12 
    Command Byte Bit Coding on page 388) is used to address within one page and must be written as 0.
  4. Enter JTAG instruction PROG_PAGELOAD.
  5. Load the entire page by shifting in all instruction words in the page, starting with the LSB of the first
    instruction in the page and ending with the MSB of the last instruction in the page.
  6. Enter JTAG instruction PROG_COMMANDS.
  7. Write the page using programming instruction 2g.
  8. Poll for Flash write complete using programming instruction 2h, or wait for tWLRH (refer to table Parallel Programming Characteristics, VCC = 5V ±10% in chapter Parallel Programming Characteristics).
  9. Repeat steps 3 to 8 until all data have been programmed.

@mcuee
Copy link
Collaborator

mcuee commented Aug 24, 2022

If we based on the above datasheet, Not able to write 1s is an AVR chip JTAG limitation.

However, "Currently, jtagmkI and jtagmkII codes cannot write to the flash ROM one word at a time" is an avrdude limitation.

I will try to see if I can test using AVR Studio 4 to see if it can program Flash in two bytes a time.
Edit: I guess there is no way to test this in reality.

Again from datasheet.

29.8. Using the JTAG Programming Capabilities
Programming of AVR parts via JTAG is performed via the four-pin JTAG port, TCK, TMS, TDI, and TDO.
These are the only pins that need to be controlled/observed to perform JTAG programming (in addition to
power pins). It is not required to apply 12V externally. The JTAGEN fuse must be programmed and the
JTD bit in the MCUCSR Register must be cleared to enable the JTAG Test Access Port.
The JTAG programming capability supports:
• Flash programming and verifying
• EEPROM programming and verifying
• Fuse programming and verifying
• Lock bit programming and verifying
The Lock bit security is exactly as in Parallel Programming mode. If the Lock bits LB1 or LB2 are
programmed, the OCDEN Fuse cannot be programmed unless first doing a chip erase. This is a security
feature that ensures no back-door exists for reading out the content of a secured device.
The details on programming through the JTAG interface and programming specific JTAG instructions are
given in the section Programming Via the JTAG Interface.

Related Links
Programming Via the JTAG Interface on page 400

@mcuee
Copy link
Collaborator

mcuee commented Aug 25, 2022

Reference post from @MCUdude here.

I just borrowed the Atmel ICE, and I've just returned it. I may ask to do some more testing with it though.

I doubt it will be able to write 1s to EEPROM in terminal mode. It can't co it when writing a file without performing a chip and EEPROM erase first. I contacted a Microchip developer, and got the following answer:

Q: Is it correct that JTAG2-compatible programmers (i.e the AVR Dragon) and JTAG3/Atmel ICE only can write 0's to EEPROM and not 1's? It's like this when using Avrdude, but the EDBG documentation I've read doesn't explicitly specifies this behaviour.

A: Sounds like a bug to me – this rule applies of course to FLASH, not EEPROM. But EDBG is not “JTAG2-compatible”… and feature-set is usually a function of the silicon, not the debugger anyway…

Q: I know the JTAG3/Atmel ICE can write 1's to Xmega's and AVRs with UPDI, but only when utilizing an "Atomic write" (See issue #1009 and PR #1013). However, I can't find a similar feature on AVRs with JTAG.

A: Correct – atomic (erase-and-write) was added for XMEGA. Not sure why this split was made…

Q: Does this means that it's impossible to write 1's to the EEPROM using a JTAG interface without running a chip erase first?

A: Not convinced, but not sure. SomeoneTM would probably have to find the RTL to know for sure – there are many subtle differences between the different entry modes (ISP/HVSP/JTAG) on those old parts – only from XMEGA onwards was there proper separation between physical and logical interfaces…

@mcuee
Copy link
Collaborator

mcuee commented Aug 26, 2022

@stefanrueger has an interesting comment here. It is kind of the unltimate brutal force solution to work around the limitations of the programers. I think it is probably not worth doing though, in most cases (unless desperate).
#1071 (comment)

[Of course, in the end of the day, all bits can be written as they need be (that's the purpose of a programmer!) but writing a single bit to 1 may involve reading all flash and EEPROM, modifying the bit and then writing he whole shebang back; that in turn requires a fair bit of caching and cannot be done at the low-level writes]

The proposal in this issue is much better and feasible whenever possible.
#1020 (comment)

@stefanrueger
Copy link
Collaborator Author

Turns out that this issue is not a bug, after all. A litte-noted line in the documentation says: [Terminal write] is not implemented for bank-addressed memories such as the flash memory of ATMega devices.

@stefanrueger stefanrueger removed the bug Something isn't working label Oct 3, 2022
@stefanrueger
Copy link
Collaborator Author

So PR #1106 is a proposal for a shiny new feature ;)

@stefanrueger
Copy link
Collaborator Author

Closed with PR #1106

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants