avrdudes / avrdude

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

SerialUPDI programmer can't write to usersig/userrow in terminal mode #889

Closed MCUdude closed 2 years ago

MCUdude commented 2 years ago

This is perhaps something for @dbuchwald to investigate. Basically, it's possible to read USERROW, but not possible to write to it. However, JTAG3 programmers such as Pickit4 supports writing to USERROW.

avrdude> read usersig
>>> read usersig 
0000  55 04 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |U...............|
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 usersig 0x00 0x00
>>> write usersig 0x00 0x00 
avrdude (write): error writing 0x00 at 0x00000 cell=0x55
dbuchwald commented 2 years ago

Will look into it. I remember playing around with USERROW, and there was something special about the process, but I just can't recall the details at the moment. Will check that and come back.

dbuchwald commented 2 years ago

As promised, I looked into it and this is the outcome: you are right, it's not possible to write USERROW from within terminal session, but you can do it the normal "batch" way:

./avrdude -C ./avrdude.conf -c serialupdi -P /dev/ttyUSB0 -p avr128db64 -U userrow:r:-:h -x rtsdtr=high

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 2: 24-bit, word oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e970b (probably avr128db64)
avrdude: reading userrow memory:

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

avrdude: writing output file "<stdout>"
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.

./avrdude -C ./avrdude.conf -c serialupdi -P /dev/ttyUSB0 -p avr128db64 -U userrow:w:userrow_test.bin:r -x rtsdtr=high

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 2: 24-bit, word oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e970b (probably avr128db64)
avrdude: reading input file "userrow_test.bin"
avrdude: writing userrow (32 bytes):

Writing | ################################################## | 100% 0.20s

avrdude: 32 bytes of userrow written
avrdude: verifying userrow memory against userrow_test.bin:

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

avrdude: 32 bytes of userrow verified
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.

./avrdude -C ./avrdude.conf -c serialupdi -P /dev/ttyUSB0 -p avr128db64 -U userrow:r:-:h -x rtsdtr=high

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 2: 24-bit, word oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e970b (probably avr128db64)
avrdude: reading userrow memory:

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

avrdude: writing output file "<stdout>"
0x54,0x45,0x53,0x54,0x20,0x75,0x73,0x65,0x72,0x72,0x6f,0x77,0x20,0x77,0x72,0x69,0x74,0x65,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.

Now, the reason for terminal session being unable to write correctly to USERROW is pretty complicated. Unlike other types of memory, USERROW requires special "commit" operation at the end of write. I tried implementing some fix, but it doesn't work yet, as in "works by writing the data, but accidentally overwrites other regions".

Bottom line: it is doable, I just need a bit more time to implement it.

dbuchwald commented 2 years ago

OK, I think I have explanation for the weird behavior and a fix that provides the functionality you requested. Please grab the latest version from userrow_fix branch in my repo ( https://github.com/dbuchwald/avrdude/tree/userrow_fix ).

I hope it works for you as well as it does for me:

./avrdude -C ./avrdude.conf -c serialupdi -P /dev/ttyUSB0 -p avr128db64 -U userrow:r:-:h -x rtsdtr=high

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 2: 24-bit, word oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e970b (probably avr128db64)
avrdude: reading userrow memory:

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

avrdude: writing output file "<stdout>"
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.

./avrdude -C ./avrdude.conf -c serialupdi -P /dev/ttyUSB0 -p avr128db64 -t -x rtsdtr=high

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 2: 24-bit, word oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e970b (probably avr128db64)
avrdude> r userrow
>>> r userrow 
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> w userrow 0x08 0xaa 0x55 0xaa
>>> w userrow 0x08 0xaa 0x55 0xaa 

avrdude> r userrow
>>> r userrow 
0000  ff ff ff ff ff ff ff ff  aa 55 aa ff ff ff ff ff  |.........U......|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> w userrow 0x00 0x00
>>> w userrow 0x00 0x00 

avrdude> r userrow
>>> r userrow 
0000  00 ff ff ff ff ff ff ff  aa 55 aa ff ff ff ff ff  |.........U......|
0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude> quit
>>> quit 
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.

./avrdude -C ./avrdude.conf -c serialupdi -P /dev/ttyUSB0 -p avr128db64 -U userrow:r:-:h -x rtsdtr=high

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 2: 24-bit, word oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e970b (probably avr128db64)
avrdude: reading userrow memory:

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

avrdude: writing output file "<stdout>"
0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaa,0x55,0xaa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.
MCUdude commented 2 years ago

Sorry, but I can't get terminal mode to work...

$ ./avrdude -C avrdude.conf -c serialupdi -P /dev/cu.usbserial-1410 -p atmega4808 -t

avrdude: UPDI link initialization OK
avrdude: Device in NVM programming state, leaving programming mode
avrdude: NVM type 0: 16-bit, page oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9650 (probably m4808)
avrdude> read userrow
>>> read userrow 
0000  55 04 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |U...............|
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 userrow 0x10 0xaa
>>> write userrow 0x10 0xaa 
avrdude (write): error writing 0xaa at 0x00010 cell=0xff

avrdude> read userrow
>>> read userrow 
0000  55 04 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |U...............|
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  |................|

And I'm not able to write to it the "regular" way either, by providing a hex file either...

dbuchwald commented 2 years ago

Are you sure you are running on the correct branch? If yes, please run it again with -vvvv switch for more verbose debug information.

MCUdude commented 2 years ago

Are you sure you are running on the correct branch? If yes, please run it again with -vvvv switch for more verbose debug information.

Yes, I'm pretty sure. I even downloaded the userrow_fix branch as a zip file and build that. Still getting the exact same error as in the message above.

dbuchwald commented 2 years ago

Thanks for checking that. Can you, please, post the -vvvv output here? I would like to see what's going on...

MCUdude commented 2 years ago

Sure! I guess this is the only relevant part?

avrdude> read userrow
>>> read userrow 
avrdude: LD from 0x001300
avrdude: Sending 4 bytes [0x55, 0x04, 0x00, 0x13]
avrdude: Send: U [55] . [04] . [00] . [13] 
avrdude: Recv: U [55] . [04] . [00] . [13] 
avrdude: Recv: U [55] 
avrdude: Received 1 bytes [0x55]
avrdude: LD from 0x001301
avrdude: Sending 4 bytes [0x55, 0x04, 0x01, 0x13]
avrdude: Send: U [55] . [04] . [01] . [13] 
avrdude: Recv: U [55] . [04] . [01] . [13] 
avrdude: Recv: . [04] 
avrdude: Received 1 bytes [0x04]
avrdude: LD from 0x001302
avrdude: Sending 4 bytes [0x55, 0x04, 0x02, 0x13]
avrdude: Send: U [55] . [04] . [02] . [13] 
avrdude: Recv: U [55] . [04] . [02] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001303
avrdude: Sending 4 bytes [0x55, 0x04, 0x03, 0x13]
avrdude: Send: U [55] . [04] . [03] . [13] 
avrdude: Recv: U [55] . [04] . [03] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001304
avrdude: Sending 4 bytes [0x55, 0x04, 0x04, 0x13]
avrdude: Send: U [55] . [04] . [04] . [13] 
avrdude: Recv: U [55] . [04] . [04] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001305
avrdude: Sending 4 bytes [0x55, 0x04, 0x05, 0x13]
avrdude: Send: U [55] . [04] . [05] . [13] 
avrdude: Recv: U [55] . [04] . [05] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001306
avrdude: Sending 4 bytes [0x55, 0x04, 0x06, 0x13]
avrdude: Send: U [55] . [04] . [06] . [13] 
avrdude: Recv: U [55] . [04] . [06] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001307
avrdude: Sending 4 bytes [0x55, 0x04, 0x07, 0x13]
avrdude: Send: U [55] . [04] . [07] . [13] 
avrdude: Recv: U [55] . [04] . [07] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001308
avrdude: Sending 4 bytes [0x55, 0x04, 0x08, 0x13]
avrdude: Send: U [55] . [04] . [08] . [13] 
avrdude: Recv: U [55] . [04] . [08] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001309
avrdude: Sending 4 bytes [0x55, 0x04, 0x09, 0x13]
avrdude: Send: U [55] . [04] . [09] . [13] 
avrdude: Recv: U [55] . [04] . [09] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00130A
avrdude: Sending 4 bytes [0x55, 0x04, 0x0a, 0x13]
avrdude: Send: U [55] . [04] . [0a] . [13] 
avrdude: Recv: U [55] . [04] . [0a] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00130B
avrdude: Sending 4 bytes [0x55, 0x04, 0x0b, 0x13]
avrdude: Send: U [55] . [04] . [0b] . [13] 
avrdude: Recv: U [55] . [04] . [0b] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00130C
avrdude: Sending 4 bytes [0x55, 0x04, 0x0c, 0x13]
avrdude: Send: U [55] . [04] . [0c] . [13] 
avrdude: Recv: U [55] . [04] . [0c] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00130D
avrdude: Sending 4 bytes [0x55, 0x04, 0x0d, 0x13]
avrdude: Send: U [55] . [04] . [0d] . [13] 
avrdude: Recv: U [55] . [04] . [0d] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00130E
avrdude: Sending 4 bytes [0x55, 0x04, 0x0e, 0x13]
avrdude: Send: U [55] . [04] . [0e] . [13] 
avrdude: Recv: U [55] . [04] . [0e] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00130F
avrdude: Sending 4 bytes [0x55, 0x04, 0x0f, 0x13]
avrdude: Send: U [55] . [04] . [0f] . [13] 
avrdude: Recv: U [55] . [04] . [0f] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001310
avrdude: Sending 4 bytes [0x55, 0x04, 0x10, 0x13]
avrdude: Send: U [55] . [04] . [10] . [13] 
avrdude: Recv: U [55] . [04] . [10] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001311
avrdude: Sending 4 bytes [0x55, 0x04, 0x11, 0x13]
avrdude: Send: U [55] . [04] . [11] . [13] 
avrdude: Recv: U [55] . [04] . [11] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001312
avrdude: Sending 4 bytes [0x55, 0x04, 0x12, 0x13]
avrdude: Send: U [55] . [04] . [12] . [13] 
avrdude: Recv: U [55] . [04] . [12] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001313
avrdude: Sending 4 bytes [0x55, 0x04, 0x13, 0x13]
avrdude: Send: U [55] . [04] . [13] . [13] 
avrdude: Recv: U [55] . [04] . [13] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001314
avrdude: Sending 4 bytes [0x55, 0x04, 0x14, 0x13]
avrdude: Send: U [55] . [04] . [14] . [13] 
avrdude: Recv: U [55] . [04] . [14] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001315
avrdude: Sending 4 bytes [0x55, 0x04, 0x15, 0x13]
avrdude: Send: U [55] . [04] . [15] . [13] 
avrdude: Recv: U [55] . [04] . [15] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001316
avrdude: Sending 4 bytes [0x55, 0x04, 0x16, 0x13]
avrdude: Send: U [55] . [04] . [16] . [13] 
avrdude: Recv: U [55] . [04] . [16] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001317
avrdude: Sending 4 bytes [0x55, 0x04, 0x17, 0x13]
avrdude: Send: U [55] . [04] . [17] . [13] 
avrdude: Recv: U [55] . [04] . [17] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001318
avrdude: Sending 4 bytes [0x55, 0x04, 0x18, 0x13]
avrdude: Send: U [55] . [04] . [18] . [13] 
avrdude: Recv: U [55] . [04] . [18] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001319
avrdude: Sending 4 bytes [0x55, 0x04, 0x19, 0x13]
avrdude: Send: U [55] . [04] . [19] . [13] 
avrdude: Recv: U [55] . [04] . [19] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00131A
avrdude: Sending 4 bytes [0x55, 0x04, 0x1a, 0x13]
avrdude: Send: U [55] . [04] . [1a] . [13] 
avrdude: Recv: U [55] . [04] . [1a] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00131B
avrdude: Sending 4 bytes [0x55, 0x04, 0x1b, 0x13]
avrdude: Send: U [55] . [04] . [1b] . [13] 
avrdude: Recv: U [55] . [04] . [1b] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00131C
avrdude: Sending 4 bytes [0x55, 0x04, 0x1c, 0x13]
avrdude: Send: U [55] . [04] . [1c] . [13] 
avrdude: Recv: U [55] . [04] . [1c] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00131D
avrdude: Sending 4 bytes [0x55, 0x04, 0x1d, 0x13]
avrdude: Send: U [55] . [04] . [1d] . [13] 
avrdude: Recv: U [55] . [04] . [1d] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00131E
avrdude: Sending 4 bytes [0x55, 0x04, 0x1e, 0x13]
avrdude: Send: U [55] . [04] . [1e] . [13] 
avrdude: Recv: U [55] . [04] . [1e] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00131F
avrdude: Sending 4 bytes [0x55, 0x04, 0x1f, 0x13]
avrdude: Send: U [55] . [04] . [1f] . [13] 
avrdude: Recv: U [55] . [04] . [1f] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001320
avrdude: Sending 4 bytes [0x55, 0x04, 0x20, 0x13]
avrdude: Send: U [55] . [04]   [20] . [13] 
avrdude: Recv: U [55] . [04]   [20] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001321
avrdude: Sending 4 bytes [0x55, 0x04, 0x21, 0x13]
avrdude: Send: U [55] . [04] ! [21] . [13] 
avrdude: Recv: U [55] . [04] ! [21] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001322
avrdude: Sending 4 bytes [0x55, 0x04, 0x22, 0x13]
avrdude: Send: U [55] . [04] " [22] . [13] 
avrdude: Recv: U [55] . [04] " [22] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001323
avrdude: Sending 4 bytes [0x55, 0x04, 0x23, 0x13]
avrdude: Send: U [55] . [04] # [23] . [13] 
avrdude: Recv: U [55] . [04] # [23] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001324
avrdude: Sending 4 bytes [0x55, 0x04, 0x24, 0x13]
avrdude: Send: U [55] . [04] $ [24] . [13] 
avrdude: Recv: U [55] . [04] $ [24] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001325
avrdude: Sending 4 bytes [0x55, 0x04, 0x25, 0x13]
avrdude: Send: U [55] . [04] % [25] . [13] 
avrdude: Recv: U [55] . [04] % [25] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001326
avrdude: Sending 4 bytes [0x55, 0x04, 0x26, 0x13]
avrdude: Send: U [55] . [04] & [26] . [13] 
avrdude: Recv: U [55] . [04] & [26] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001327
avrdude: Sending 4 bytes [0x55, 0x04, 0x27, 0x13]
avrdude: Send: U [55] . [04] ' [27] . [13] 
avrdude: Recv: U [55] . [04] ' [27] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001328
avrdude: Sending 4 bytes [0x55, 0x04, 0x28, 0x13]
avrdude: Send: U [55] . [04] ( [28] . [13] 
avrdude: Recv: U [55] . [04] ( [28] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001329
avrdude: Sending 4 bytes [0x55, 0x04, 0x29, 0x13]
avrdude: Send: U [55] . [04] ) [29] . [13] 
avrdude: Recv: U [55] . [04] ) [29] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00132A
avrdude: Sending 4 bytes [0x55, 0x04, 0x2a, 0x13]
avrdude: Send: U [55] . [04] * [2a] . [13] 
avrdude: Recv: U [55] . [04] * [2a] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00132B
avrdude: Sending 4 bytes [0x55, 0x04, 0x2b, 0x13]
avrdude: Send: U [55] . [04] + [2b] . [13] 
avrdude: Recv: U [55] . [04] + [2b] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00132C
avrdude: Sending 4 bytes [0x55, 0x04, 0x2c, 0x13]
avrdude: Send: U [55] . [04] , [2c] . [13] 
avrdude: Recv: U [55] . [04] , [2c] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00132D
avrdude: Sending 4 bytes [0x55, 0x04, 0x2d, 0x13]
avrdude: Send: U [55] . [04] - [2d] . [13] 
avrdude: Recv: U [55] . [04] - [2d] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00132E
avrdude: Sending 4 bytes [0x55, 0x04, 0x2e, 0x13]
avrdude: Send: U [55] . [04] . [2e] . [13] 
avrdude: Recv: U [55] . [04] . [2e] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00132F
avrdude: Sending 4 bytes [0x55, 0x04, 0x2f, 0x13]
avrdude: Send: U [55] . [04] / [2f] . [13] 
avrdude: Recv: U [55] . [04] / [2f] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001330
avrdude: Sending 4 bytes [0x55, 0x04, 0x30, 0x13]
avrdude: Send: U [55] . [04] 0 [30] . [13] 
avrdude: Recv: U [55] . [04] 0 [30] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001331
avrdude: Sending 4 bytes [0x55, 0x04, 0x31, 0x13]
avrdude: Send: U [55] . [04] 1 [31] . [13] 
avrdude: Recv: U [55] . [04] 1 [31] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001332
avrdude: Sending 4 bytes [0x55, 0x04, 0x32, 0x13]
avrdude: Send: U [55] . [04] 2 [32] . [13] 
avrdude: Recv: U [55] . [04] 2 [32] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001333
avrdude: Sending 4 bytes [0x55, 0x04, 0x33, 0x13]
avrdude: Send: U [55] . [04] 3 [33] . [13] 
avrdude: Recv: U [55] . [04] 3 [33] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001334
avrdude: Sending 4 bytes [0x55, 0x04, 0x34, 0x13]
avrdude: Send: U [55] . [04] 4 [34] . [13] 
avrdude: Recv: U [55] . [04] 4 [34] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001335
avrdude: Sending 4 bytes [0x55, 0x04, 0x35, 0x13]
avrdude: Send: U [55] . [04] 5 [35] . [13] 
avrdude: Recv: U [55] . [04] 5 [35] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001336
avrdude: Sending 4 bytes [0x55, 0x04, 0x36, 0x13]
avrdude: Send: U [55] . [04] 6 [36] . [13] 
avrdude: Recv: U [55] . [04] 6 [36] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001337
avrdude: Sending 4 bytes [0x55, 0x04, 0x37, 0x13]
avrdude: Send: U [55] . [04] 7 [37] . [13] 
avrdude: Recv: U [55] . [04] 7 [37] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001338
avrdude: Sending 4 bytes [0x55, 0x04, 0x38, 0x13]
avrdude: Send: U [55] . [04] 8 [38] . [13] 
avrdude: Recv: U [55] . [04] 8 [38] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x001339
avrdude: Sending 4 bytes [0x55, 0x04, 0x39, 0x13]
avrdude: Send: U [55] . [04] 9 [39] . [13] 
avrdude: Recv: U [55] . [04] 9 [39] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00133A
avrdude: Sending 4 bytes [0x55, 0x04, 0x3a, 0x13]
avrdude: Send: U [55] . [04] : [3a] . [13] 
avrdude: Recv: U [55] . [04] : [3a] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00133B
avrdude: Sending 4 bytes [0x55, 0x04, 0x3b, 0x13]
avrdude: Send: U [55] . [04] ; [3b] . [13] 
avrdude: Recv: U [55] . [04] ; [3b] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00133C
avrdude: Sending 4 bytes [0x55, 0x04, 0x3c, 0x13]
avrdude: Send: U [55] . [04] < [3c] . [13] 
avrdude: Recv: U [55] . [04] < [3c] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00133D
avrdude: Sending 4 bytes [0x55, 0x04, 0x3d, 0x13]
avrdude: Send: U [55] . [04] = [3d] . [13] 
avrdude: Recv: U [55] . [04] = [3d] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00133E
avrdude: Sending 4 bytes [0x55, 0x04, 0x3e, 0x13]
avrdude: Send: U [55] . [04] > [3e] . [13] 
avrdude: Recv: U [55] . [04] > [3e] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude: LD from 0x00133F
avrdude: Sending 4 bytes [0x55, 0x04, 0x3f, 0x13]
avrdude: Send: U [55] . [04] ? [3f] . [13] 
avrdude: Recv: U [55] . [04] ? [3f] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
0000  55 04 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |U...............|
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 userrow 0x00 0x00
>>> write userrow 0x00 0x00 
avrdude: ST to 0x001300
avrdude: Sending 4 bytes [0x55, 0x44, 0x00, 0x13]
avrdude: Send: U [55] D [44] . [00] . [13] 
avrdude: Recv: U [55] D [44] . [00] . [13] 
avrdude: Recv: @ [40] 
avrdude: Received 1 bytes [0x40]
avrdude: Sending 1 bytes [0x00]
avrdude: Send: . [00] 
avrdude: Recv: . [00] 
avrdude: Recv: @ [40] 
avrdude: Received 1 bytes [0x40]
avrdude: LD from 0x001300
avrdude: Sending 4 bytes [0x55, 0x04, 0x00, 0x13]
avrdude: Send: U [55] . [04] . [00] . [13] 
avrdude: Recv: U [55] . [04] . [00] . [13] 
avrdude: Recv: U [55] 
avrdude: Received 1 bytes [0x55]
avrdude (write): error writing 0x00 at 0x00000 cell=0x55
dbuchwald commented 2 years ago

Thank you indeed. I think the problem is in your avrdude.conf file - I checked and the one that I have (coming from the main repo) doesn't specify userrow memory for m4808. Could you share how is that configured on your end?

The reason for the ask: looking at the output I can see that the memory has not been recognised as USERROW, and the comparison is made against the memory name in avrdude conf. Maybe you are using aliases for this?

Got it, sorry. Configuration now:

part parent    ".avr8x"
    id          = ".avr8x_mega";
    desc        = "AVR8X mega family common values";
    family_id   = "megaAVR";

    memory "usersig"
        size        = 0x40;
        offset      = 0x1300;
        page_size   = 0x40;
        readsize    = 0x100;
    ;

        memory "userrow"
        alias "usersig";
    ;
;

Replace by:

part parent    ".avr8x"
    id          = ".avr8x_mega";
    desc        = "AVR8X mega family common values";
    family_id   = "megaAVR";

    memory "userrow"
        size        = 0x40;
        offset      = 0x1300;
        page_size   = 0x40;
        readsize    = 0x100;
    ;

        memory "usersig"
        alias "userrow";
    ;
;
MCUdude commented 2 years ago

Sorry, but that didn't help either...

>>> write userrow 0x10 0x00 
avrdude: ST to 0x001310
avrdude: Sending 4 bytes [0x55, 0x44, 0x10, 0x13]
avrdude: Send: U [55] D [44] . [10] . [13] 
avrdude: Recv: U [55] D [44] . [10] . [13] 
avrdude: Recv: @ [40] 
avrdude: Received 1 bytes [0x40]
avrdude: Sending 1 bytes [0x00]
avrdude: Send: . [00] 
avrdude: Recv: . [00] 
avrdude: Recv: @ [40] 
avrdude: Received 1 bytes [0x40]
avrdude: LD from 0x001310
avrdude: Sending 4 bytes [0x55, 0x04, 0x10, 0x13]
avrdude: Send: U [55] . [04] . [10] . [13] 
avrdude: Recv: U [55] . [04] . [10] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude (write): error writing 0x00 at 0x00010 cell=0xff

avrdude> write usersig 0x10 0x00
>>> write usersig 0x10 0x00 
avrdude: ST to 0x001310
avrdude: Sending 4 bytes [0x55, 0x44, 0x10, 0x13]
avrdude: Send: U [55] D [44] . [10] . [13] 
avrdude: Recv: U [55] D [44] . [10] . [13] 
avrdude: Recv: @ [40] 
avrdude: Received 1 bytes [0x40]
avrdude: Sending 1 bytes [0x00]
avrdude: Send: . [00] 
avrdude: Recv: . [00] 
avrdude: Recv: @ [40] 
avrdude: Received 1 bytes [0x40]
avrdude: LD from 0x001310
avrdude: Sending 4 bytes [0x55, 0x04, 0x10, 0x13]
avrdude: Send: U [55] . [04] . [10] . [13] 
avrdude: Recv: U [55] . [04] . [10] . [13] 
avrdude: Recv: ? [ff] 
avrdude: Received 1 bytes [0xff]
avrdude (write): error writing 0x00 at 0x00010 cell=0xff
MCUdude commented 2 years ago

@dbuchwald I can confirm that it works on an AVR128DA48, but not the ATmega4808

dbuchwald commented 2 years ago

OK, I'm almost 100% positive that it is indeed the configuration file issue.

Using the default configuration file, that defines only usersig memory and userrow as an alias:

./avrdude -C ./avrdude.conf -p m4809 -b 230400 -c serialupdi -t -P /dev/tty.usbserial-1420 -x rtsdtr=high 

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 0: 16-bit, page oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9651 (probably m4809)
avrdude> r userrow
>>> r userrow 
0000  ff ff ff ff ff ff ff ff  55 ff ff ff ff ff ff ff  |........U.......|
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> w userrow 0x00 0x55
>>> w userrow 0x00 0x55 
avrdude (write): error writing 0x55 at 0x00000 cell=0xff

avrdude> quit
>>> quit 
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.

Created new version of the configuration file:

diff avrdude.conf.new avrdude.conf
16508c16508
<     memory "userrow"
---
>     memory "usersig"
16515,16516c16515,16516
<     memory "usersig"
<         alias "userrow";
---
>     memory "userrow"
>         alias "usersig";
16529c16529
<     memory "userrow"
---
>     memory "usersig"
16536,16537c16536,16537
<     memory "usersig"
<         alias "userrow";
---
>         memory "userrow"
>         alias "usersig";

Running with the new config file:

./avrdude -C ./avrdude.conf.new -p m4809 -b 230400 -c serialupdi -t -P /dev/tty.usbserial-1420 -x rtsdtr=high

avrdude: UPDI link initialization OK
avrdude: Forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 0: 16-bit, page oriented write
avrdude: Entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9651 (probably m4809)
avrdude> r userrow
>>> r userrow 
0000  ff ff ff ff ff ff ff ff  55 ff ff ff ff ff ff ff  |........U.......|
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> w userrow 0x00 0x55
>>> w userrow 0x00 0x55 

avrdude> r userrow
>>> r userrow 
0000  55 ff ff ff ff ff ff ff  55 ff ff ff ff ff ff ff  |U.......U.......|
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> quit
>>> quit 
avrdude: Leaving NVM programming mode
avrdude: Releasing DTR/RTS handshake lines

avrdude done.  Thank you.

By the way, the reason for DA version to work for you is the difference in memory definition.

MCUdude commented 2 years ago

OK, I'm almost 100% positive that it is indeed the configuration file issue.

You're absolutely right! I accidentally modified a different avrdude.conf file. After modifying the correct one, it works perfectly. But it looks like lots of other programmer implementation expect the name to be usersig and not userrow. Maybe you make make it so that it supports both names, regardless if an alias is used or not? Ideally, all programmers should be able to accept both names...

$ grep usersig *.c *.h
jtag3.c:      } else if (strcmp(m->desc, "usersig") == 0) {
jtag3.c:      else if (strcmp(m->desc, "usersig") == 0)
jtag3.c:  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
jtag3.c:  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
jtag3.c:  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
jtag3.c:  } else if (strcmp(mem->desc, "usersig") == 0) {
jtag3.c:  } else if (strcmp(mem->desc, "usersig") == 0) {
jtagmkII.c:    } else if (strcmp(m->desc, "usersig") == 0) {
jtagmkII.c:  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
jtagmkII.c:  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
jtagmkII.c:  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
jtagmkII.c:  } else if (strcmp(mem->desc, "usersig") == 0) {
jtagmkII.c:  } else if (strcmp(mem->desc, "usersig") == 0) {
stk500v2.c:    } else if (strcmp(mem->desc, "usersig") == 0) {
stk500v2.c:    } else if (strcmp(mem->desc, "usersig") == 0) {
stk500v2.c:    } else if (strcmp(mem->desc, "usersig") == 0) {
stk500v2.c:    } else if (strcmp(mem->desc, "usersig") == 0) {
stk500v2.c:    } else if (strcmp(m->desc, "usersig") == 0) {
$ grep userrow *.c *.h
serialupdi.c:static int serialupdi_write_userrow(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
serialupdi.c:  if (strcmp(mem->desc, "userrow") == 0) {
serialupdi.c:    return serialupdi_write_userrow(pgm, p, mem, mem->page_size, 0, mem->size);
serialupdi.c:      } else if (strcmp(m->desc, "userrow")==0) {
serialupdi.c:        rc = serialupdi_write_userrow(pgm, p, m, page_size, write_offset, 
serialupdi.c:    } else if (strcmp(m->desc, "userrow")==0) {
serialupdi.c:      rc = serialupdi_write_userrow(pgm, p, m, page_size, addr, n_bytes);
dbuchwald commented 2 years ago

I'm glad to hear that the issue is now resolved, and maybe I should add support for both names. Not sure though.

By the way, the reason the batch operation didn't work was exactly the same.

That all being said I think we should look into redefined memory model at some point in future. It's all based on literal strings and, as illustrated by this example, very error-prone. The reason for me to use "userrow" instead of "usersig" is that this is what it is called in AVR datasheet. There is also "SIGROW", which is neither usersig nor userrow. Seriously...

After reading briefly memory sections of two datasheets:

https://ww1.microchip.com/downloads/en/DeviceDoc/AVR128DB28-32-48-64-DataSheet-DS40002247A.pdf https://ww1.microchip.com/downloads/en/DeviceDoc/ATxmega128-64-32-16A4U-DataSheet-DS40002166A.pdf

I don't know if USERSIG is really the same thing as USERROW. USERROW exists only in context of UPDI and is writeable on locked devices, while User Signature Row is something from the other family of devices. Now I'm not convinced that the alias userrow => usersig should even exist.

What a magnificent rabbit hole it is.

I will hold on the PR for a while, I need to think a bit more and maybe read some more code for the other programmers and their support for "usersig".

@dl8dtl - I would really appreciate your input on that, maybe you could help us decide what to do with this pickle...

MCUdude commented 2 years ago

From the megaAVR family data sheet:

User Row (USERROW) In addition to the EEPROM, the ATmega808/809/1608/1609/3208/3209/4808/4809 has one extra page of EEPROM memory that can be used for firmware settings, the User Row (USERROW). This memory supports single byte read and write as the normal EEPROM. The CPU can write and read this memory as normal EEPROM and the UPDI can write and read it as a normal EEPROM memory if the part is unlocked. The User Row can also be written by the UPDI when the part is locked. USERROW is not affected by a chip erase. The USERROW can be used for final configuration without having programming or debugging capabilities enabled.

From the AVR-DB datasheet:

USERROW - User Row The AVR128DB28/32/48/64 devices have a special 32-byte memory section called the User Row (USERROW). USERROW can be used for end-production data and is not affected by chip erase. It can be written by the Unified Program and Debug Interface (UPDI) even if the part is locked, which enables storage of final configuration without having access to any other memory. When the part is locked, the UPDI is not allowed to read the content of the USERROW. The CPU can write and read this memory as a normal flash. Refer to the System Memory Address Map for further details.

From the Xmega datasheet:

User Signature Row The user signature row is a separate memory section that is fully accessible (read and write) from application software and external programmers. It is one flash page in size, and is meant for static user parameter storage, such as calibration data, custom serial number, identification numbers, random number seeds, etc. This section is not erased by chip erase commands that erase the flash, and requires a dedicated erase command. This ensures parameter storage during multiple program/erase operations and on-chip debug sessions.

In my opinion, they appear to be very similar. Neither of them are affected by a chip erase, both can be read from and written to by the application or a programmer

dbuchwald commented 2 years ago

Indeed these are similar, but there is an important difference between them: USERROW is writeable (but not readable via UPDI) while the device is locked. From what I read USERSIG doesn’t have this property.

As for programming - this is also something that is specific to UPDI devices - you need to establish special kind of “session” to write to USERROW. Again, not sure if USERSIG is the same.

What I’m most worried about is that if I change the name for megaAVR config (from USERSIG to USERROW) it might break compatibility with JTAG3 and other programmers. This supports your idea of making USERROW and USERSIG the same to AVRDUDE, at least as far as UPDI is concerned. On the other hand, the above discrepancies are important enough to keep these separate...

MCUdude commented 2 years ago

Yes, I understand what you mean.

Here's my suggestion:

If @dl8dtl approves, maybe all this could be done in a single PR?