Closed askn37 closed 10 months ago
@stefanrueger
Just wondering if this is related to #1249. Thanks.
Since I'm an AVR chip collector, I've been experimenting with about 20 models of UPDI AVR bare chips from different family and revisions, along with several different SerialUPDI implementations. Unfortunately, I don't have the recalled chip.
One implementation that showed interesting behavior was using DTR to toggle UART passthrough and a combination of RTS and capacitors to perform a hard reset. This circuit is used in conjunction with the Arduino IDE's serial plotter.
This type cannot use SerialUPDI without the "-xrtsdtr=high" option. Also, the target AVR wakes up more slowly than circuits that don't use it.
When used on the latest main branch (NVMCTRL improved), it stops with "error: Reading chip silicon revision failed". However, disconnecting the RTS reset fixes it without any problems. So it's clear that the capacitor in the reset circuit was interfering. Either the design is wrong or avrdude is impatient.
Therefore, I created a build with "Silicon Check" commented out and experimented with RTS reset, and this time it proceeded normally even though "error: key was not accepted" was displayed. What did you say?
+./avrdude_test/build_darwin/src/avrdude -xrtsdtr=high -p avr64ea32 -c serialupdi -P /dev/cu.usbserial-230 -U userrow:r:avr64ea32/USERROW.hex:i -v
avrdude: Version 7.2-20231024 (d6c61f5f)
Copyright the AVRDUDE authors;
see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is /Users/askn/Arduino/UPDI_TEST/avrdude_test/build_darwin/src/avrdude.conf
User configuration file is /Users/askn/.avrduderc
Using Port : /dev/cu.usbserial-230
Using Programmer : serialupdi
AVR Part : AVR64EA32
RESET disposition : dedicated
RETRY pulse : SCK
Serial program mode : yes
Parallel program mode : yes
Memory Detail :
Block Poll Page Polled
Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
fuse0 wdtcfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00
fuse1 bodcfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00
fuse2 osccfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00
fuse5 syscfg0 0 0 0 0 no 1 1 0 0 0 0x00 0x00
fuse6 syscfg1 0 0 0 0 no 1 1 0 0 0 0x00 0x00
fuse7 codesize 0 0 0 0 no 1 1 0 0 0 0x00 0x00
fuse8 bootsize 0 0 0 0 no 1 1 0 0 0 0x00 0x00
fuses 0 0 0 0 no 16 16 0 0 0 0x00 0x00
lock 0 0 0 0 no 4 1 0 0 0 0x00 0x00
prodsig sigrow 0 0 0 0 no 128 128 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 1 0 0 0 0x00 0x00
tempsense 0 0 0 0 no 4 1 0 0 0 0x00 0x00
sernum 0 0 0 0 no 16 1 0 0 0 0x00 0x00
userrow usersig 0 0 0 0 no 64 64 0 0 0 0x00 0x00
data 0 0 0 0 no 0 1 0 0 0 0x00 0x00
io 0 0 0 0 no 4160 1 0 0 0 0x00 0x00
sib 0 0 0 0 no 32 1 0 0 0 0x00 0x00
eeprom 0 0 0 0 no 512 8 0 0 0 0x00 0x00
flash 0 0 0 0 no 65536 128 0 0 0 0x00 0x00
Programmer Type : serialupdi
Description : SerialUPDI
avrdude: forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 3: 24-bit, page oriented
avrdude: entering NVM programming mode
avrdude serialupdi_enter_progmode() error: key was not accepted
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e961f (probably avr64ea32)
avrdude: processing -U userrow:r:avr64ea32/USERROW.hex:i
avrdude: reading userrow/usersig memory ...
Reading | ################################################## | 100% 0.02s
avrdude: writing output file avr64ea32/USERROW.hex
avrdude: leaving NVM programming mode
avrdude: releasing DTR/RTS handshake lines
avrdude done. Thank you.
This indicates that the UPDI layer has not yet fully woken up when reading "UPDI_CS_ASI_KEY_STATUS" after sending "UPDI_SIB_128", or that key activation took longer than usual. I'm sure avrdude is impatient. There probably aren't any other concerns. thank you.
@askn37
Thanks a lot for sharing your insight. Nice AVR boards!
Please help to post the full debug log with -vvvv
and maybe that can help @dbuchwald and maybe @stefanrueger to debug the issue to make avrdude more robust.
@askn37
BTW, I see that you have alternative Arduino Core in your repos (in Japanese) https://github.com/askn37 https://github.com/askn37/multix-zinnia-sdk-modernAVR https://github.com/askn37/multix-zinnia-sdk-megaAVR
Just wondering if you compare your Cores with MegaCoreX, megaTinyCore and DxCore. Thanks. https://github.com/MCUdude/MegaCoreX https://github.com/SpenceKonde/megaTinyCore https://github.com/SpenceKonde/DxCore
@stefanrueger and @dbuchwald
Looks like there is a regression under Windows in git main from avrdude 7.2 release, under Windows.
You can see I have no issues with avrdude 7.2 release. git main has issues.
Edit: looks like a MSVC build vs MinGW build issue. Please refer to later post. Usually I use MinGW build and that is why I see issues.
Looking at the histories, there are not many changes. I will try to find the commit which causes the regression. https://github.com/avrdudes/avrdude/commits/main/src/serialupdi.c
The following commit is already causing problems: Added support for chip silicon revision number https://github.com/avrdudes/avrdude/commit/ac760ff49064c5de53abed709057341ec4a78b64
PS>.\avrdude_ac760ff -C .\avrdude_ac760ff.conf -c serialupdi -P COM16 -p avr64dd32 -v
avrdude_ac760ff: Version 7.2-20230725 (ac760ff4)
...
avrdude_ac760ff serialupdi_initialize() error: UPDI link initialization failed
avrdude_ac760ff main() error: initialization failed, rc=-1
- double check the connections and try again
- use -b to set lower baud rate, e.g. -b 57600
- use -F to override this check
avrdude_ac760ff: leaving NVM programming mode
avrdude_ac760ff done. Thank you.
Hmm, no, it seems to be a MinGW vs MSVC issue.
Official MSVC build is okay but not my MinGW build, even for avrdude 7.2 release version. I will check out git main later.
PS>.\avrdude72_mingw64 -C .\avrdude72.conf -c serialupdi -P COM16 -p avr64dd32 -v
avrdude72_mingw64: Version 7.2
...
avrdude72_mingw64 serialupdi_initialize() error: UPDI link initialization failed
avrdude72_mingw64 main() error: initialization failed, rc=-1
- double check the connections and try again
- use -b to set lower baud rate, e.g. -b 57600
- use -F to override this check
avrdude72_mingw64: leaving NVM programming mode
avrdude72_mingw64 done. Thank you.
PS>.\avrdude72_msvc -C .\avrdude72.conf -c serialupdi -P COM16 -p avr64dd32 -v
avrdude72_msvc: Version 7.2
...
avrdude72_msvc: device is in SLEEP mode
avrdude72_msvc: NVM type 2: 24-bit, word oriented write
avrdude72_msvc: entering NVM programming mode
avrdude72_msvc: AVR device initialized and ready to accept instructions
avrdude72_msvc: device signature = 0x1e961a (probably avr64dd32)
avrdude72_msvc: leaving NVM programming mode
avrdude72_msvc done. Thank you.
Same for git main, using the github action binary of git main (not my build).
MSVC build is okay, but not MinGW build.
PS>pwd
Path
----
C:\work\avr\avrdude_test\avrdude_bin\github\avrdude-mingw-x86_64
PS>.\avrdude -c serialupdi -P COM16 -p avr64dd32 -v
avrdude: Version 7.2-20231024 (d6c61f5)
...
avrdude serialupdi_initialize() error: UPDI link initialization failed
avrdude main() error: initialization failed, rc=-1
- double check the connections and try again
- use -b to set lower baud rate, e.g. -b 57600
- use -F to override this check
avrdude: leaving NVM programming mode
avrdude done. Thank you.
PS>cd .\avrdude-msvc-x64\
PS>pwd
Path
----
C:\work\avr\avrdude_test\avrdude_bin\github\avrdude-msvc-x64
PS>.\avrdude -c serialupdi -P COM16 -p avr64dd32 -v
avrdude: Version 7.2-20231024 (d6c61f5)
...
avrdude: device is in SLEEP mode
avrdude: NVM type 2: 24-bit, word oriented write
avrdude: Chip silicon revision: 1.3
avrdude: entering NVM programming mode
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e961a (probably avr64dd32)
avrdude: leaving NVM programming mode
avrdude done. Thank you.
Then I checked MSVC build:
1) avrdude 7.1 and avrdude 7.2 official MSVC binary work with both -v
and -vvvv
.
2) avrdude git main MSVC github action binary works with with both -v
and -vvvv
.
3) avrdude 7.0 official MSVC binary works with -v
, -vv
and -vvv
but not -vvvv
.
MinGW build.
1) avrdude 7.1 and avrdude 7.2 mingw64 binary does not work with either -v
or -vvvv
. Without -v
it works.
2) avrdude git main mingw64 github action binary does not work with either -v
or -vvvv
. Without -v
it works.
3) avrdude 7.0 mingw64 binary does not work with either -v
or -vvvv
. Without -v
it works.
So this is not a regression, The issue has been there since avrdude 7.0 release (first official release to support serialupdi).
@mcuee
BTW, I see that you have alternative Arduino Core in your repos (in Japanese) https://github.com/askn37 https://github.com/askn37/multix-zinnia-sdk-modernAVR https://github.com/askn37/multix-zinnia-sdk-megaAVR
Just wondering if you compare your Cores with MegaCoreX, megaTinyCore and DxCore. Thanks. https://github.com/MCUdude/MegaCoreX https://github.com/SpenceKonde/megaTinyCore https://github.com/SpenceKonde/DxCore
Of course, the cross-check has been completed. The avrdude used when each project is set up with Arduino IDE can be obtained from the link below.
My project (multix-zinnia-sdk) is the only one that has 7.2 deployed as of today. This is because we are dealing with AVR_EA (NVMCTRLv3 chip). MCUdude supports all NVMCTRLv0 chips, so there is nothing to worry about. SpenceKonde (Dr.Azzy) uses "prog.py" and does not use avrdude's built-in SerialUPDI, so it is avrdude 6.3.
That's why it was my duty to launch this issue.
http://downloads.arduino.cc/tools/avrdude_7.2-arduino.1_Linux_ARMv6.tar.gz http://downloads.arduino.cc/tools/avrdude_7.2-arduino.1_Linux_ARM64.tar.gz http://downloads.arduino.cc/tools/avrdude_7.2-arduino.1_macOS_64bit.tar.gz http://downloads.arduino.cc/tools/avrdude_7.2-arduino.1_Linux_64bit.tar.gz http://downloads.arduino.cc/tools/avrdude_7.2-arduino.1_Linux_32bit.tar.gz http://downloads.arduino.cc/tools/avrdude_7.2-arduino.1_Windows_32bit.tar.gz
http://downloads.arduino.cc/tools/avrdude_7.1-arduino.1_Linux_ARMv6.tar.gz http://downloads.arduino.cc/tools/avrdude_7.1-arduino.1_Linux_ARM64.tar.gz http://downloads.arduino.cc/tools/avrdude_7.1-arduino.1_macOS_64bit.tar.gz http://downloads.arduino.cc/tools/avrdude_7.1-arduino.1_Linux_64bit.tar.gz http://downloads.arduino.cc/tools/avrdude_7.1-arduino.1_Linux_32bit.tar.gz http://downloads.arduino.cc/tools/avrdude_7.1-arduino.1_Windows_32bit.tar.gz
http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino18-armhf-pc-linux-gnu.tar.bz2 http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino18-aarch64-pc-linux-gnu.tar.bz2 http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino18-x86_64-apple-darwin12.tar.bz2 http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino18-x86_64-pc-linux-gnu.tar.bz2 http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino18-i686-w64-mingw32.zip
@askn37
Thanks for adopting avrdude 7.2 release!
@MCUdude will for sure adopt avrdude 7.2 for his MegaCoreX for the next release (or maybe 7.3 release depends on the timing). The current 1.1.2 release was on 2023-05-01 so it was before avrdude 7.2 release.
As for DxCore and megaTinyCore, there are issues created to adopt avrdude 7.2. I think @SpenceKonde will adopt avrdude 7.2 release in the near future. He actually wanted to adopt earlier but there were no suitable binaries at that time.
@mcuee
The following commit is already causing problems: Added support for chip silicon revision number https://github.com/avrdudes/avrdude/commit/ac760ff49064c5de53abed709057341ec4a78b64
I believe the code in question is placed in "static int serialupdi_initialize" because it requires "const AVRPART p". But in reality, if you could just "enter NVM programming mode" and run it, you would have been fine. However, the "static int serialupdi_enter_progmode" that does this does not take "const AVRPART p" as an argument. Therefore, this change still requires consideration.
The current AVR64EA32-I/PT (TQFP Revision B1) may have unknown errata. After writing the ERASE/NVMPROG/USERROW key, the UPDI_CS_ASI_KEY_STATUS register may be unreadable or unchanged. This is especially true in high voltage mode. Is there a problem with UPDI clock synchronization? But I don't have an oscilloscope that can decode his UPDI communications, so I can't find any evidence yet. There has been no response from Microchip either.
Errata for AVR EA family Rev B1. Indeed there are issues related to UPDI and NVM programming. https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/Errata/AVR64EA-28-32-48-SilConErrataClarif-DS80001048.pdf
Device 2.2.1. NVM Programming Does Not Work Below 2.7V 2.2.2. Reduced Flash Endurance for VDD Below BODLEVEL3 2.2.3. Write Operation Lost if Consecutive Writes to Specific Address Spaces
CRCSCAN 2.3.1. Running CRC Scan on Part of The Flash is Non-Functional
NVMCTRL 2.4.1. Flash Multi Page Erase Non-Functional from UPDI 2.4.2. Flash-Self Programming Failing When Flash Read During Programming
USART 2.5.1. Receiver Non-Functional after Detection of Inconsistent Synchronization Field
Further debug under Windows: -b 57600
works with MinGW build.
or avrdude is impatient
@askn37 Is there a good place in serialupdi_initialize()
to put an usleep()
to solve this problem and how long for?
Also, I wonder whether some OS open() calls twiddle RTS while other OS don't touch RTS when opening a serial connection.
@stefanrueger I would be very careful with changes like this. I remember that one of the main challenges in SerialUPDI implementation was making sure it "sort-of-works" for all the platforms, because, as you noticed, actual support for "standard" "POSIX" operations on serial ports varies wildly between seemingly similar systems, depending on drivers, hardware and such. As far as I recall, the original pymcuprog implementation for the "break" signal was to change baud rate to 300 and transmit then:
https://github.com/microchip-pic-avr-tools/pymcuprog/blob/main/pymcuprog/serialupdi/physical.py#L89
If you are interested, I have some notes on why it was not possible to use "standard" "POSIX" feature of tcsendbreak()
which would make much more sense. Yeah, tread carefully, this stuff is slippery slope.
And if you decide to add this usleep
thing in serialupdi_initialize
, then please, make sure to gate it with build-specific #ifdef
so it doesn't pollute and break other implementations.
@dbuchwald and @stefanrueger
I can actually live with the current git as it suggests to use -b 57600
which does sort out the issue, if the fix is not simple.
PS>.\avrdude_git -c serialupdi -P COM11 -p avr64dd32 -v
avrdude_git: Version 7.2-20231024 (d6c61f5f)
...
avrdude_git serialupdi_initialize() error: UPDI link initialization failed
avrdude_git main() error: initialization failed, rc=-1
- double check the connections and try again
- use -b to set lower baud rate, e.g. -b 57600
- use -F to override this check
avrdude_git: leaving NVM programming mode
avrdude_git done. Thank you.
PS>.\avrdude_git -c serialupdi -P COM11 -p avr64dd32 -v -b 57600
avrdude_git: Version 7.2-20231024 (d6c61f5f)
...
avrdude_git: device is in SLEEP mode
avrdude_git: NVM type 2: 24-bit, word oriented write
avrdude_git: Chip silicon revision: 1.3
avrdude_git: entering NVM programming mode
avrdude_git: AVR device initialized and ready to accept instructions
avrdude_git: device signature = 0x1e961a (probably avr64dd32)
avrdude_git: leaving NVM programming mode
avrdude_git done. Thank you.
BTW, pymcuprog does work.
(py310x64venv) PS>pymcuprog ping -d avr64dd32 -t uart -u com11
Connecting to SerialUPDI
Pinging device...
Ping response: 1E961A
Done.
(py310x64venv) PS>pymcuprog ping -d avr64dd32 -t uart -u com11 -v debug
Connecting to SerialUPDI
pymcuprog.programmer - INFO - Setting up programming session for 'avr64dd32'
pymcuprog.deviceinfo.deviceinfo - INFO - Looking for device avr64dd32
pymcuprog.serialupdi.physical - INFO - Opening port 'com11' at 115200 baud (timeout 1.0s)
pymcuprog.serialupdi.physical - DEBUG - send : [0x00]
pymcuprog.serialupdi.link - DEBUG - STCS to 0x03
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC3, 0x08]
pymcuprog.serialupdi.link - DEBUG - STCS to 0x02
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC2, 0x80]
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x00
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x80]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x30]
pymcuprog.serialupdi.link - INFO - UPDI init OK
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xE6]
pymcuprog.serialupdi.application - INFO - SIB: 'AVR P:2D:1-3M2 (A3.KV00K.0)'
pymcuprog.serialupdi.application - INFO - Device family ID: 'AVR'
pymcuprog.serialupdi.application - INFO - NVM interface: 'P:2'
pymcuprog.serialupdi.application - INFO - Debug interface: 'D:1'
pymcuprog.serialupdi.application - INFO - PDI oscillator: '3M2'
pymcuprog.serialupdi.application - INFO - Extra info: '(A3.KV00K.0)'
pymcuprog.serialupdi.application - INFO - NVM type 2: 24-bit, word oriented write
pymcuprog.serialupdi.link - DEBUG - STCS to 0x03
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC3, 0x08]
pymcuprog.serialupdi.link - DEBUG - STCS to 0x02
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC2, 0x80]
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x00
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x80]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x30]
pymcuprog.serialupdi.link - INFO - UPDI init OK
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x00
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x80]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x30]
pymcuprog.serialupdi.application - INFO - PDI revision = 0x03
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x0B
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x8B]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x92]
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x0B
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x8B]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x92]
pymcuprog.serialupdi.application - INFO - Entering NVM programming mode
pymcuprog.serialupdi.link - DEBUG - Writing key
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xE0]
pymcuprog.serialupdi.physical - DEBUG - send : [0x20, 0x67, 0x6F, 0x72, 0x50, 0x4D, 0x56, 0x4E]
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x07
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x87]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x10]
pymcuprog.serialupdi.application - DEBUG - Key status = 0x10
pymcuprog.serialupdi.application - INFO - Apply reset
pymcuprog.serialupdi.link - DEBUG - STCS to 0x08
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC8, 0x59]
pymcuprog.serialupdi.application - INFO - Release reset
pymcuprog.serialupdi.link - DEBUG - STCS to 0x08
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC8, 0x00]
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x0B
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x8B]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x38]
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x0B
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x8B]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x08]
pymcuprog.serialupdi.application - DEBUG - Now in NVM programming mode
Pinging device...
pymcuprog.programmer - INFO - Reading device ID...
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xE6]
pymcuprog.serialupdi.application - INFO - SIB: 'AVR P:2D:1-3M2 (A3.KV00K.0)'
pymcuprog.serialupdi.application - INFO - Device family ID: 'AVR'
pymcuprog.serialupdi.application - INFO - NVM interface: 'P:2'
pymcuprog.serialupdi.application - INFO - Debug interface: 'D:1'
pymcuprog.serialupdi.application - INFO - PDI oscillator: '3M2'
pymcuprog.serialupdi.application - INFO - Extra info: '(A3.KV00K.0)'
pymcuprog.serialupdi.application - INFO - NVM type 2: 24-bit, word oriented write
pymcuprog.serialupdi.link - DEBUG - STCS to 0x03
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC3, 0x08]
pymcuprog.serialupdi.link - DEBUG - STCS to 0x02
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC2, 0x80]
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x00
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x80]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x30]
pymcuprog.serialupdi.link - INFO - UPDI init OK
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x00
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x80]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x30]
pymcuprog.serialupdi.application - INFO - PDI revision = 0x03
pymcuprog.serialupdi.link - DEBUG - LDCS from 0x0B
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x8B]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x08]
pymcuprog.serialupdi.readwrite - DEBUG - Reading 3 bytes from 0x1100
pymcuprog.serialupdi.link - INFO - ST to ptr
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x6A, 0x00, 0x11, 0x00]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x40]
pymcuprog.serialupdi.link - DEBUG - Repeat 3
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xA0, 0x02]
pymcuprog.serialupdi.link - DEBUG - LD8 from ptr++
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x24]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x1E, 0x96, 0x1A]
pymcuprog.serialupdi.readwrite - DEBUG - Reading 1 bytes from 0x0F01
pymcuprog.serialupdi.link - INFO - ST to ptr
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x6A, 0x01, 0x0F, 0x00]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x40]
pymcuprog.serialupdi.link - DEBUG - LD8 from ptr++
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x24]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x13]
pymcuprog.serialupdi.application - INFO - Device ID from serialupdi = '1E961A' rev 'T'
pymcuprog.nvm - INFO - Device family: 'AVR'
pymcuprog.serialupdi.readwrite - DEBUG - Reading 3 bytes from 0x1100
pymcuprog.serialupdi.link - INFO - ST to ptr
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x6A, 0x00, 0x11, 0x00]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x40]
pymcuprog.serialupdi.link - DEBUG - Repeat 3
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xA0, 0x02]
pymcuprog.serialupdi.link - DEBUG - LD8 from ptr++
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x24]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x1E, 0x96, 0x1A]
pymcuprog.nvm - INFO - Device ID: '1E961A'
pymcuprog.serialupdi.readwrite - DEBUG - Reading 1 bytes from 0x0F01
pymcuprog.serialupdi.link - INFO - ST to ptr
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x6A, 0x01, 0x0F, 0x00]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x40]
pymcuprog.serialupdi.link - DEBUG - LD8 from ptr++
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x24]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x13]
pymcuprog.nvm - DEBUG - Device revision: 0x13
pymcuprog.nvm - INFO - Device revision: '1.3'
pymcuprog.serialupdi.readwrite - DEBUG - Reading 10 bytes from 0x1103
pymcuprog.serialupdi.link - INFO - ST to ptr
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x6A, 0x03, 0x11, 0x00]
pymcuprog.serialupdi.physical - DEBUG - receive : [0x40]
pymcuprog.serialupdi.link - DEBUG - Repeat 10
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xA0, 0x09]
pymcuprog.serialupdi.link - DEBUG - LD8 from ptr++
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0x24]
pymcuprog.serialupdi.physical - DEBUG - receive : [0xFF, 0x7E, 0x03, 0xA4, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
pymcuprog.nvm - INFO - Device serial number: 'b'ff7e03a40dffffffffff''
Ping response: 1E961A
pymcuprog.serialupdi.application - INFO - Leaving NVM programming mode
pymcuprog.serialupdi.application - INFO - Apply reset
pymcuprog.serialupdi.link - DEBUG - STCS to 0x08
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC8, 0x59]
pymcuprog.serialupdi.application - INFO - Release reset
pymcuprog.serialupdi.link - DEBUG - STCS to 0x08
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC8, 0x00]
pymcuprog.serialupdi.link - DEBUG - STCS to 0x03
pymcuprog.serialupdi.physical - DEBUG - send : [0x55, 0xC3, 0x0C]
Done.
pymcuprog.serialupdi.physical - INFO - Closing port 'com11'
As far as I recall, the original pymcuprog implementation for the "break" signal was to change baud rate to 300 and transmit
This is correct. serialupdi in pymcuprog is tested using the nano's cdc, and BREAK support in the nano's cdc was only implemented quite recently, to the 300baud workaround was used. Edit: and I think the lower-bound for the nano's cdc was reduced to support this...
BTW, pymcuprog does work.
I'm not entirely sure what libraries for serial communication are used by MinGW build of AVRDUDE, but it's actually possible that there is some difference compared to Python interpreter build, and this might explain why it behaves differently (as in: works with higher baud rate, because this is the discrepancy we are looking at, right?).
@stefanrueger
@askn37 Is there a good place in serialupdi_initialize() to put an usleep() to solve this problem and how long for? Also, I wonder whether some OS open() calls twiddle RTS while other OS don't touch RTS when opening a serial connection.
I discovered this problem in a prototype circuit using a CH340X (board on the right in the photo above). This is very special and can be targeted to UPDI_AVR, ATSAM, ESP32, or STM32 by toggling a jumper. Except for AVR, DTR and RTS are independent and independently control his BOOT and RESET pins on ARM chips etc.
However, AVR (using the "-xrtsdtr" option) does not differentiate between DTR and RTS. Both can be HIGH or LOW at the same time. Therefore, use a capacitor to control the AVR's RESET LOW for a few milliseconds to tens of seconds after DTR/RTS goes HIGH. If "-c arduino" knows that on startup he will generate a 100ms HIGH pulse to DTR/RTS, otherwise he will generate a LOW level, this is usually , I understand that it is a ritual to start the bootloader. ('-c arduino' starts after another 100ms)
In this interesting circuit, the problem was that the reset pulse was not completed when SerialUPDI started. So I tried adding a delay at the end of "updi_set_rtsdtr_mode" and it started working correctly. I needed at least 95ms, so depending on individual differences you may want 150ms. However, this is limited to this circuit.
static void updi_set_rtsdtr_mode(const PROGRAMMER *pgm) {
updi_rts_mode rts_mode = updi_get_rts_mode(pgm);
if (rts_mode == RTS_MODE_DEFAULT) {
return;
}
serial_set_dtr_rts(&pgm->fd, 0);
serial_set_dtr_rts(&pgm->fd, rts_mode == RTS_MODE_LOW ? 1 : 0);
/* TEST : startup UART circuit delay */
usleep(150 * 1000);
}
FTDI typically has both DTR and RTS. However, CH340N and CH340E are RTS only. These allow you to reset the AVR or use only RTS if you want to switch to UART passthrough. On the other hand, ESP32 and STM32 circuits have a habit of using DTR for boot control and RTS for reset. This circuit is made accordingly.
BTW, pymcuprog does work.
I'm not entirely sure what libraries for serial communication are used by MinGW build of AVRDUDE, but it's actually possible that there is some difference compared to Python interpreter build, and this might explain why it behaves differently (as in: works with higher baud rate, because this is the discrepancy we are looking at, right?).
MinGW build of avrdude should use the same native Windows serial API as MSVC build. Here we should ignore the libserialport stuff in git main which is only available in MinGW build since avrdude 7.2 release does not have libserialport). However, I think there are some code path differences (ifdefs) between MinGW build and MSVC build. Just an example of different code paths -- I am not saying the following causing this issue though.
BTW, I just checked pymcuprog under MSYS2 mingw64 Python and it works fine there. Previous Python environment is MSVC build of Python. But I am not so sure if this findings help at all or not. And pymcuprog uses pyserial, which may behave a bit different from the native Windows serial API used by avrdude, even though pyserial is based on native Windows API. https://github.com/microchip-pic-avr-tools/pymcuprog/blob/main/requirements.txt https://github.com/pyserial/pyserial/blob/master/serial/win32.py
All in all, I think we have a timing issue somewhere due to platform specifc codes for MinGW.
FTDI typically has both DTR and RTS. However, CH340N and CH340E are RTS only. These allow you to reset the AVR or use only RTS if you want to switch to UART passthrough.
This is a bit tricky to deal with as different design may use different lines. I did some research earlier this year as well.
BTW, I have looked into the cheap USB-TTL converters sold in Taobao/AliExpress, using CH340x series, FT232BL/RL series, CP2102 and PL2303 series. There are others like CH341x, CP2104, FT232H/FT2232H/FT4232H, etc.
1) Quite some of them do not have any other signal pins other than TXD/RXD. Then they may have 5V or 3V3 or both, then GND.
2) Some of them have DTR pin
3) Some of them have RTS/CTS pins, usually come in a pair
4) Some FT232 based adapter may have more pins available, including one with the 6-pin AVRISP connectors and DTR/CTS.
@askn37 Impressive hardware
combination of RTS and capacitors to perform a hard reset
Is this a standard reset circuit similar to the recommended AVR reset circuit?
If so then I recommend the following lines to carry out a reset:
// This code assumes a negative-logic USB to TTL serial adapter
// Set RTS/DTR high to discharge the series-capacitor, if present
serial_set_dtr_rts(&pgm->fd, 0);
usleep(20*1000);
// Pull the RTS/DTR line low to reset AVR
serial_set_dtr_rts(&pgm->fd, 1);
// Max 100 us: charging a cap longer creates a high reset spike above Vcc
usleep(100);
// Set the RTS/DTR line back to high, so direct connection to reset works
serial_set_dtr_rts(&pgm->fd, 0);
if((120+xdelay) > 0)
usleep((120+xdelay)*1000); // Wait until board comes out of reset
Here xdelay
is a parameter for additional sleep [ms] after reset that can be set by the user with -xdelay=...
; it can be negative. This code works when RTS is directly connected to RESET or when RTS is decoupled via an in-line capacitor from RESET.
Above approach is different to the current lines https://github.com/avrdudes/avrdude/blob/d6c61f5fab4d0d061fb85233acee6ecaa85dd9c0/src/updi_link.c#L49-L50
I get the impression that updi_set_rtsdtr_mode()
is meant for communication via DTR and for reset via RTS. If this is the case, I think we should separate rts and dtr handling into two functions serial_set_rts()
and serial_set_dtr()
to manage the signals independently. We should have some code similar to above for explicitly resetting the board and deploy a typical wait of 120 ms (user changable) after reset. Even we do not give explicit reset to the board, we should be aware that the OS open()
statement can twiddle RTS and thus create a reset if we want this or not. So there should always be a sleep after open()/explicit reset.
And yes, @dbuchwald, you are absolutely right about being careful about changes we do...
Haha, looks like we are talking multiple issues here with serialupdi. 1) NVM v3 for AVR EA and EB bug-- fixed by PR #1531 2) General sleep issue with moder UPDI parts (at least AVR DA/DB/DD and EA/EB) -- seems to be fixed as well, even though there is a warning as per @askn37 under his macOS testing 3) Sleep issue specific to MinGW build under Windows with AVR DD (and maybe others) -- this shows some sort of timing issues at higher baud rate like 115200 and (57600 is okay). 4) DTR/RTS reset handling
@stefanrueger
Just want to mention that I tried your reset patch and it does not help. I tried different xdelay
value of -50, 0, 100 and 1000
and they do not help.
I believe for my testing the reset code does not matter since I only use three pins (Vcc, GND and UPDI) pins to connect a CH340 based serialupdi programmer to the target.
PS>git diff
diff --git a/src/updi_link.c b/src/updi_link.c
index dba4a67e..80054e61 100644
--- a/src/updi_link.c
+++ b/src/updi_link.c
@@ -42,12 +42,25 @@
static void updi_set_rtsdtr_mode(const PROGRAMMER *pgm) {
updi_rts_mode rts_mode = updi_get_rts_mode(pgm);
+ int xdelay=100;
+
if (rts_mode == RTS_MODE_DEFAULT) {
return;
}
+ // This code assumes a negative-logic USB to TTL serial adapter
+ // Set RTS/DTR high to discharge the series-capacitor, if present
+ serial_set_dtr_rts(&pgm->fd, 0);
+ usleep(20*1000);
+ // Pull the RTS/DTR line low to reset AVR
+ serial_set_dtr_rts(&pgm->fd, 1);
+ // Max 100 us: charging a cap longer creates a high reset spike above Vcc
+ usleep(100);
+ // Set the RTS/DTR line back to high, so direct connection to reset works
serial_set_dtr_rts(&pgm->fd, 0);
- serial_set_dtr_rts(&pgm->fd, rts_mode == RTS_MODE_LOW ? 1 : 0);
+
+ if((120+xdelay) > 0)
+ usleep((120+xdelay)*1000); // Wait until board comes out of reset
}
static int updi_physical_open(PROGRAMMER* pgm, int baudrate, unsigned long cflags)
One of the better designed serialupdi programmer comes from @MCUdude, which has dual functionality -- UPDI or Serial UART mode (and can be used in Auto mode which automatically switch between the two modes). https://www.tindie.com/products/mcudude/serialupdi-programmer/
You can see that it has only RTS pin and no DTR pin. And if the RTS pin is not connected, UPDI programming will still work.
Simple UPDI programmers will only have three pins -- VCC, GND and UPDI pin. https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md
@mcuee At first, I didn't expect it to become such a wide-ranging discussion! It might be better to close this and separate it into another topic.
@stefanrueger
This is the schematic for the CH340X prototype board. The CH340X is an improved version of the CH340E and also includes the features of the CH340K. CH340K had problems in the past due to VID differences, but CH340X has high compatibility. By adding additional resistors to TNOW, DTR can be extended in two ways during POR.
The latest hardware design guide for modernAVR can be found in their respective datasheets. UPDI and RESET have built-in 30kΩ pull-ups that activate on POR, unlike older AVRs. Therefore, only a stabilizing capacitor is required externally. If you add a reset switch, also add a filter resistor.
His RESET prototype board for AVR follows the latest design guidelines. The difference is that instead of being connected to GND, it is connected to his RTS, which is Low by default. Therefore, the stabilization capacitor is charged by the internal pull-up. When the RTS changes, it discharges with opposite polarity and the potential drops for a short time. It will stay below 0.2VDD until RESET is charged again.
Old AVR design guides recommended a 10kΩ RESET pullup. The reason this is no longer mentioned is probably because the internal high frequency RC oscillator is slow and you want to have enough time for POR. Additionally, the UPDI circuit (sub-CPU) operates using a dedicated internal RC oscillator that is separate from the main clock. In the worst case, it may boot slower than the main CPU. To avoid this (preventing abnormalities due to inrush current), FUSE has a startup timer setting. The adjustment range is up to 64ms, so it is best to keep this delay phenomenon in mind.
@mcuee At first, I didn't expect it to become such a wide-ranging discussion! It might be better to close this and separate it into another topic.
No issues, It is probably my fault. :-)
I think we can continue here as the topics are all related to serialupdi.
I tried to debug the MinGW 115200bps issue and adding usleep here and there does not help.
I think the issue is that ir can not communicate at 115200 bps at all, at least initially with the MinGW build. Adding usleep will not help.
PS>git diff
diff --git a/src/serialupdi.c b/src/serialupdi.c
index f93eb5de..7e34709d 100644
--- a/src/serialupdi.c
+++ b/src/serialupdi.c
@@ -566,7 +566,7 @@ static int serialupdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
uint8_t reset_link_required=0;
if (updi_link_init(pgm) < 0) {
- pmsg_error("UPDI link initialization failed\n");
+ pmsg_error("UPDI link initialization failed main\n");
return -1;
}
pmsg_notice2("UPDI link initialization OK\n");
diff --git a/src/updi_link.c b/src/updi_link.c
index dba4a67e..18a92108 100644
--- a/src/updi_link.c
+++ b/src/updi_link.c
@@ -42,12 +42,25 @@
static void updi_set_rtsdtr_mode(const PROGRAMMER *pgm) {
updi_rts_mode rts_mode = updi_get_rts_mode(pgm);
+ int xdelay=-50;
+
if (rts_mode == RTS_MODE_DEFAULT) {
return;
}
+ // This code assumes a negative-logic USB to TTL serial adapter
+ // Set RTS/DTR high to discharge the series-capacitor, if present
+ serial_set_dtr_rts(&pgm->fd, 0);
+ usleep(20*1000);
+ // Pull the RTS/DTR line low to reset AVR
+ serial_set_dtr_rts(&pgm->fd, 1);
+ // Max 100 us: charging a cap longer creates a high reset spike above Vcc
+ usleep(100);
+ // Set the RTS/DTR line back to high, so direct connection to reset works
serial_set_dtr_rts(&pgm->fd, 0);
- serial_set_dtr_rts(&pgm->fd, rts_mode == RTS_MODE_LOW ? 1 : 0);
+
+ if((120+xdelay) > 0)
+ usleep((120+xdelay)*1000); // Wait until board comes out of reset
}
static int updi_physical_open(PROGRAMMER* pgm, int baudrate, unsigned long cflags)
@@ -213,12 +226,16 @@ static int updi_link_init_session_parameters(const PROGRAMMER *pgm) {
self.stcs(constants.UPDI_CS_CTRLB, 1 << constants.UPDI_CTRLB_CCDETDIS_BIT)
self.stcs(constants.UPDI_CS_CTRLA, 1 << constants.UPDI_CTRLA_IBDLY_BIT)
*/
+ usleep(100);
if (updi_link_stcs(pgm, UPDI_CS_CTRLB, 1 << UPDI_CTRLB_CCDETDIS_BIT) < 0) {
- return -1;
+ pmsg_debug("session orameters initialisation failed B\n");
+ return -1;
}
-
+
+ usleep(100);
if (updi_link_stcs(pgm, UPDI_CS_CTRLA, 1 << UPDI_CTRLA_IBDLY_BIT) < 0) {
- return -1;
+ pmsg_debug("session orameters initialisation failed A\n");
+ return -1;
}
return 0;
@@ -274,25 +291,30 @@ int updi_link_init(const PROGRAMMER *pgm) {
raise PymcuprogError("UPDI initialisation failed")
*/
if (updi_link_init_session_parameters(pgm) < 0) {
- pmsg_debug("session initialisation failed\n");
+ pmsg_debug("session initialisation failed 1\n");
return -1;
}
+
+ usleep(100);
if (updi_link_check(pgm) < 0) {
pmsg_debug("datalink not active, resetting ...\n");
if (updi_physical_send_double_break(pgm) < 0) {
- pmsg_debug("datalink initialisation failed\n");
+ pmsg_debug("datalink initialisation failed 2\n");
return -1;
}
+ usleep(100);
if (updi_link_init_session_parameters(pgm) < 0) {
- pmsg_debug("session initialisation failed\n");
+ pmsg_debug("session initialisation failed 3\n");
return -1;
}
+ usleep(100);
if (updi_link_check(pgm) < 0) {
- pmsg_debug("restoring datalink failed\n");
+ pmsg_debug("restoring datalink failed 4\n");
return -1;
}
}
+
return 0;
}
PS>cd ..\avrdude_bin
PS>.\avrdude_mod -C .\avrdude_pr1538.conf -c serialupdi -P COM11 -p avr64dd32 -vvvv
avrdude_mod: Version 7.2-20231024 (d6c61f5f)
Copyright the AVRDUDE authors;
see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is C:\work\avr\avrdude_test\avrdude_bin\avrdude_pr1538.conf
Using Port : COM11
Using Programmer : serialupdi
avrdude_mod: opening serial port ...
avrdude_mod: sending 1 bytes [0x00]
avrdude_mod: send: . [00]
avrdude_mod: recv: . [00]
AVR Part : AVR64DD32
RESET disposition : dedicated
RETRY pulse : SCK
Serial program mode : yes
Parallel program mode : yes
...
avrdude_mod: STCS 0x08 to address 0x03
avrdude_mod: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_mod: send: U [55] . [c3] . [08]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: STCS 0x80 to address 0x02
avrdude_mod: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_mod: send: U [55] . [c2] . [80]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: LDCS from 0x00
avrdude_mod: sending 2 bytes [0x55, 0x80]
avrdude_mod: send: U [55] . [80]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: serialupdi_recv(): programmer is not responding
avrdude_mod: check failed
avrdude_mod: datalink not active, resetting ...
avrdude_mod: sending double break
avrdude_mod: send: . [00]
avrdude_mod: recv: . [00]
avrdude_mod: send: . [00]
avrdude_mod: recv: . [00]
avrdude_mod: STCS 0x08 to address 0x03
avrdude_mod: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_mod: send: U [55] . [c3] . [08]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: STCS 0x80 to address 0x02
avrdude_mod: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_mod: send: U [55] . [c2] . [80]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: LDCS from 0x00
avrdude_mod: sending 2 bytes [0x55, 0x80]
avrdude_mod: send: U [55] . [80]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: serialupdi_recv(): programmer is not responding
avrdude_mod: check failed
avrdude_mod: restoring datalink failed 4
avrdude_mod serialupdi_initialize() [serialupdi.c:569] error: UPDI link initialization failed main
avrdude_mod main() [main.c:1399] error: initialization failed, rc=-1
- double check the connections and try again
- use -b to set lower baud rate, e.g. -b 57600
- use -F to override this check
avrdude_mod: leaving NVM programming mode
avrdude_mod: sending reset request
avrdude_mod: STCS 0x59 to address 0x08
avrdude_mod: sending 3 bytes [0x55, 0xc8, 0x59]
avrdude_mod: send: U [55] . [c8] Y [59]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: sending release reset request
avrdude_mod: STCS 0x00 to address 0x08
avrdude_mod: sending 3 bytes [0x55, 0xc8, 0x00]
avrdude_mod: send: U [55] . [c8] . [00]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: STCS 0x0C to address 0x03
avrdude_mod: sending 3 bytes [0x55, 0xc3, 0x0c]
avrdude_mod: send: U [55] . [c3] . [0c]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod done. Thank you.
Even at baud rate of 57600 it failed initially but luckily it can recover.
...
...
avrdude_mod: STCS 0x08 to address 0x03
avrdude_mod: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_mod: send: U [55] . [c3] . [08]
avrdude_mod: recv: . [00] . [d8] . [f8]
avrdude_mod: STCS 0x80 to address 0x02
avrdude_mod: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_mod: send: U [55] . [c2] . [80]
avrdude_mod: recv: U [55] . [c2] . [80]
avrdude_mod: LDCS from 0x00
avrdude_mod: sending 2 bytes [0x55, 0x80]
avrdude_mod: send: U [55] . [80]
avrdude_mod: recv: U [55] . [80]
avrdude_mod: ser_recv(): programmer is not responding
avrdude_mod: serialupdi_recv(): programmer is not responding
avrdude_mod: check failed
avrdude_mod: datalink not active, resetting ...
avrdude_mod: sending double break
avrdude_mod: send: . [00]
avrdude_mod: recv: . [00]
avrdude_mod: send: . [00]
avrdude_mod: recv: . [00]
avrdude_mod: STCS 0x08 to address 0x03
avrdude_mod: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_mod: send: U [55] . [c3] . [08]
avrdude_mod: recv: U [55] . [c3] . [08]
avrdude_mod: STCS 0x80 to address 0x02
avrdude_mod: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_mod: send: U [55] . [c2] . [80]
avrdude_mod: recv: U [55] . [c2] . [80]
avrdude_mod: LDCS from 0x00
avrdude_mod: sending 2 bytes [0x55, 0x80]
avrdude_mod: send: U [55] . [80]
avrdude_mod: recv: U [55] . [80]
avrdude_mod: recv: 0 [30]
avrdude_mod: received 1 bytes [0x30]
avrdude_mod: UDPI init OK
avrdude_mod: UPDI link initialization OK
avrdude_mod: LDCS from 0x0B
avrdude_mod: sending 2 bytes [0x55, 0x8b]
avrdude_mod: send: U [55] . [8b]
avrdude_mod: recv: U [55] . [8b]
avrdude_mod: recv: . [92]
avrdude_mod: received 1 bytes [0x92]
avrdude_mod: device is in SLEEP mode
avrdude_mod: sending 2 bytes [0x55, 0xe6]
avrdude_mod: send: U [55] . [e6]
avrdude_mod: recv: U [55] . [e6]
avrdude_mod: recv: A [41] V [56] R [52] [20] [20] [20] [20] [20] P [50] : [3a] 2 [32] D [44] : [3a] 1 [31] - [2d] 3 [33] M [4d] 2 [32] [20] ( [28] A [41] 3 [33] . [2e] K [4b] V [56] 0 [30] 0 [30] K [4b] . [2e] 0 [30] ) [29] . [00]
avrdude_mod: received 32 bytes [0x41, 0x56, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x3a, 0x32, 0x44, 0x3a, 0x31, 0x2d, 0x33, 0x4d, 0x32, 0x20, 0x28, 0x41, 0x33, 0x2e, 0x4b, 0x56, 0x30, 0x30, 0x4b, 0x2e, 0x30, 0x29, 0x00]
avrdude_mod: received SIB: [AVR P:2D:1-3M2 (A3.KV00K.0)]
avrdude_mod: Device family ID: AVR
avrdude_mod: NVM interface: P:2
avrdude_mod: Debug interface: D:1
avrdude_mod: PDI oscillator: 3M2
avrdude_mod: Extra information: (A3.KV00K.0)
avrdude_mod: NVM type 2: 24-bit, word oriented write
avrdude_mod: reading 1 bytes from 0x000F01
avrdude_mod: ST_PTR to 0x000F01
avrdude_mod: sending 5 bytes [0x55, 0x6a, 0x01, 0x0f, 0x00]
avrdude_mod: send: U [55] j [6a] . [01] . [0f] . [00]
avrdude_mod: recv: U [55] j [6a] . [01] . [0f] . [00]
avrdude_mod: recv: @ [40]
avrdude_mod: received 1 bytes [0x40]
avrdude_mod: LD8 from ptr++
avrdude_mod: sending 2 bytes [0x55, 0x24]
avrdude_mod: send: U [55] $ [24]
avrdude_mod: recv: U [55] $ [24]
avrdude_mod: recv: . [13]
avrdude_mod: received 1 bytes [0x13]
avrdude_mod: Received chip silicon revision 0x13
avrdude_mod: Chip silicon revision: 1.3
avrdude_mod: STCS 0x08 to address 0x03
avrdude_mod: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_mod: send: U [55] . [c3] . [08]
avrdude_mod: recv: U [55] . [c3] . [08]
avrdude_mod: STCS 0x80 to address 0x02
avrdude_mod: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_mod: send: U [55] . [c2] . [80]
avrdude_mod: recv: U [55] . [c2] . [80]
avrdude_mod: LDCS from 0x00
avrdude_mod: sending 2 bytes [0x55, 0x80]
avrdude_mod: send: U [55] . [80]
avrdude_mod: recv: U [55] . [80]
avrdude_mod: recv: 0 [30]
avrdude_mod: received 1 bytes [0x30]
avrdude_mod: UDPI init OK
avrdude_mod: entering NVM programming mode
avrdude_mod: LDCS from 0x0B
avrdude_mod: sending 2 bytes [0x55, 0x8b]
avrdude_mod: send: U [55] . [8b]
avrdude_mod: recv: U [55] . [8b]
avrdude_mod: recv: . [92]
avrdude_mod: received 1 bytes [0x92]
avrdude_mod: UPDI writing key
avrdude_mod: sending 2 bytes [0x55, 0xe0]
avrdude_mod: send: U [55] . [e0]
avrdude_mod: recv: U [55] . [e0]
avrdude_mod: sending 8 bytes [0x20, 0x67, 0x6f, 0x72, 0x50, 0x4d, 0x56, 0x4e]
avrdude_mod: send: [20] g [67] o [6f] r [72] P [50] M [4d] V [56] N [4e]
avrdude_mod: recv: [20] g [67] o [6f] r [72] P [50] M [4d] V [56] N [4e]
avrdude_mod: LDCS from 0x07
avrdude_mod: sending 2 bytes [0x55, 0x87]
avrdude_mod: send: U [55] . [87]
avrdude_mod: recv: U [55] . [87]
avrdude_mod: recv: . [10]
avrdude_mod: received 1 bytes [0x10]
avrdude_mod: key status: 0x10
avrdude_mod: sending reset request
avrdude_mod: STCS 0x59 to address 0x08
avrdude_mod: sending 3 bytes [0x55, 0xc8, 0x59]
avrdude_mod: send: U [55] . [c8] Y [59]
avrdude_mod: recv: U [55] . [c8] Y [59]
avrdude_mod: sending release reset request
avrdude_mod: STCS 0x00 to address 0x08
avrdude_mod: sending 3 bytes [0x55, 0xc8, 0x00]
avrdude_mod: send: U [55] . [c8] . [00]
avrdude_mod: recv: U [55] . [c8] . [00]
avrdude_mod: LDCS from 0x0B
avrdude_mod: sending 2 bytes [0x55, 0x8b]
avrdude_mod: send: U [55] . [8b]
avrdude_mod: recv: U [55] . [8b]
avrdude_mod: recv: 8 [38]
avrdude_mod: received 1 bytes [0x38]
avrdude_mod: LDCS from 0x0B
avrdude_mod: sending 2 bytes [0x55, 0x8b]
avrdude_mod: send: U [55] . [8b]
avrdude_mod: recv: U [55] . [8b]
avrdude_mod: recv: . [08]
avrdude_mod: received 1 bytes [0x08]
avrdude_mod: entered NVM programming mode
avrdude_mod: AVR device initialized and ready to accept instructions
Reading | | 0% 0.00 s
avrdude_mod: LDCS from 0x0B
avrdude_mod: sending 2 bytes [0x55, 0x8b]
avrdude_mod: send: U [55] . [8b]
avrdude_mod: recv: U [55] . [8b]
avrdude_mod: recv: . [08]
avrdude_mod: received 1 bytes [0x08]
avrdude_mod: LD from 0x001100
avrdude_mod: sending 5 bytes [0x55, 0x08, 0x00, 0x11, 0x00]
avrdude_mod: send: U [55] . [08] . [00] . [11] . [00]
avrdude_mod: recv: U [55] . [08] . [00] . [11] . [00]
avrdude_mod: recv: . [1e]
avrdude_mod: received 1 bytes [0x1e]
avrdude_mod: LD from 0x001101
avrdude_mod: sending 5 bytes [0x55, 0x08, 0x01, 0x11, 0x00]
avrdude_mod: send: U [55] . [08] . [01] . [11] . [00]
avrdude_mod: recv: U [55] . [08] . [01] . [11] . [00]
avrdude_mod: recv: . [96]
avrdude_mod: received 1 bytes [0x96]
avrdude_mod: LD from 0x001102
avrdude_mod: sending 5 bytes [0x55, 0x08, 0x02, 0x11, 0x00]
avrdude_mod: send: U [55] . [08] . [02] . [11] . [00]
avrdude_mod: recv: U [55] . [08] . [02] . [11] . [00]
avrdude_mod: recv: . [1a]
avrdude_mod: received 1 bytes [0x1a]
Reading | ################################################## | 100% 0.05 s
avrdude_mod: device signature = 0x1e961a (probably avr64dd32)
avrdude_mod: leaving NVM programming mode
avrdude_mod: sending reset request
avrdude_mod: STCS 0x59 to address 0x08
avrdude_mod: sending 3 bytes [0x55, 0xc8, 0x59]
avrdude_mod: send: U [55] . [c8] Y [59]
avrdude_mod: recv: U [55] . [c8] Y [59]
avrdude_mod: sending release reset request
avrdude_mod: STCS 0x00 to address 0x08
avrdude_mod: sending 3 bytes [0x55, 0xc8, 0x00]
avrdude_mod: send: U [55] . [c8] . [00]
avrdude_mod: recv: U [55] . [c8] . [00]
avrdude_mod: STCS 0x0C to address 0x03
avrdude_mod: sending 3 bytes [0x55, 0xc3, 0x0c]
avrdude_mod: send: U [55] . [c3] . [0c]
avrdude_mod: recv: U [55] . [c3] . [0c]
avrdude_mod done. Thank you.
As there is no issue with -c
, I think I will just leave this paticular MinGW build issue for now.
WIthout -c
, both the mingw64 binary and VS2022 x64 (MSVC64) binary of git main works until 230400 baud. I can check the LED blinking to see if the erase (LED OFF) or programming (LED blinking) is really working or not. And it is working.
PS>.\avrdude_git -c serialupdi -P COM41 -p avr64dd32 -b 230400 -e
avrdude_git: AVR device initialized and ready to accept instructions
avrdude_git: device signature = 0x1e961a (probably avr64dd32)
avrdude_git: erasing chip
avrdude_git done. Thank you.
PS>.\avrdude_git -c serialupdi -P COM41 -p avr64dd32 -b 230400 -U .\sleep.hex
avrdude_git: AVR device initialized and ready to accept instructions
avrdude_git: device signature = 0x1e961a (probably avr64dd32)
avrdude_git: Note: flash memory has been specified, an erase cycle will be performed.
To disable this feature, specify the -D option.
avrdude_git: erasing chip
avrdude_git: processing -U flash:w:.\sleep.hex:i
avrdude_git: reading input file .\sleep.hex for flash
with 276 bytes in 1 section within [0, 0x113]
using 1 page and 236 pad bytes
avrdude_git: writing 276 bytes flash ...
Writing | ################################################## | 100% 0.09 s
avrdude_git: 276 bytes of flash written
avrdude_git: verifying flash memory against .\sleep.hex
Reading | ################################################## | 100% 0.04 s
avrdude_git: 276 bytes of flash verified
avrdude_git done. Thank you.
PS>.\avrdude_git -c serialupdi -P COM41 -p avr64dd32 -b 230400
avrdude_git: AVR device initialized and ready to accept instructions
avrdude_git: device signature = 0x1e961a (probably avr64dd32)
avrdude_git done. Thank you.
As per the following documentation from @SpenceKonde, for DxCore, 57600bps works across different adapters. https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md
57600 baud maximizes compatibility with suboptimal adapters and/or wiring.
230400 baud is the "standard" speed for uploading, and is supported by all serial adapters I am aware of.
345600 baud (1.5x 230400) works out to be about the maximum baud rate for continuous writing, but not all serial adapters support it.
460800 baud for HT42B435 - this is a special workaround for the HT42B435
As there is no issue with -c, I think I will just leave this paticular MinGW build issue for now.
Looks like this is very specific to MSYS2 mingw compiler. I just tested Arduino-packing build of avrdude 7.2 mingw32 release and my own git main build using cross-compiling, there are no issues with -v
or -vvvv
. So I think I will not debug further.
Arduino-packing official build of avrdude 7.2 release https://github.com/arduino/avrdude-packing/releases/tag/7.2-arduino.1
My own git main build https://github.com/mcuee/avrdude-packing/releases/tag/snapshot_2023-10-24
PS>.\avrdude_git_arduino -c serialupdi -P COM41 -p avr64dd32 -b 230400 -vvvv
avrdude_git_arduino: Version 7.2-20231024 (d6c61f5)
Copyright the AVRDUDE authors;
see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is C:\work\avr\avrdude_test\avrdude_bin\avrdude.conf
Using Port : COM41
Using Programmer : serialupdi
Overriding Baud Rate : 230400
avrdude_git_arduino: opening serial port ...
avrdude_git_arduino: serial_baud_lookup(): using non-standard baud rate: 230400
avrdude_git_arduino: sending 1 bytes [0x00]
avrdude_git_arduino: send: . [00]
avrdude_git_arduino: recv: . [00]
AVR Part : AVR64DD32
RESET disposition : dedicated
RETRY pulse : SCK
Serial program mode : yes
Parallel program mode : yes
Memory Detail :
...
Programmer Type : serialupdi
Description : SerialUPDI
avrdude_git_arduino: STCS 0x08 to address 0x03
avrdude_git_arduino: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_git_arduino: send: U [55] . [c3] . [08]
avrdude_git_arduino: recv: U [55] . [c3] . [08]
avrdude_git_arduino: STCS 0x80 to address 0x02
avrdude_git_arduino: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_git_arduino: send: U [55] . [c2] . [80]
avrdude_git_arduino: recv: U [55] . [c2] . [80]
avrdude_git_arduino: LDCS from 0x00
avrdude_git_arduino: sending 2 bytes [0x55, 0x80]
avrdude_git_arduino: send: U [55] . [80]
avrdude_git_arduino: recv: U [55] . [80]
avrdude_git_arduino: recv: 0 [30]
avrdude_git_arduino: received 1 bytes [0x30]
avrdude_git_arduino: UDPI init OK
avrdude_git_arduino: UPDI link initialization OK
avrdude_git_arduino: LDCS from 0x0B
avrdude_git_arduino: sending 2 bytes [0x55, 0x8b]
avrdude_git_arduino: send: U [55] . [8b]
avrdude_git_arduino: recv: U [55] . [8b]
avrdude_git_arduino: recv: . [92]
avrdude_git_arduino: received 1 bytes [0x92]
avrdude_git_arduino: device is in SLEEP mode
avrdude_git_arduino: sending 2 bytes [0x55, 0xe6]
avrdude_git_arduino: send: U [55] . [e6]
avrdude_git_arduino: recv: U [55] . [e6]
avrdude_git_arduino: recv: A [41] V [56] R [52] [20] [20] [20] [20] [20] P [50] : [3a] 2 [32] D [44] : [3a] 1 [31] - [2d] 3 [33] M [4d] 2 [32] [20] ( [28] A [41] 3 [33] . [2e] K [4b] V [56] 0 [30] 0 [30] K [4b] . [2e] 0 [30] ) [29] . [00]
avrdude_git_arduino: received 32 bytes [0x41, 0x56, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x3a, 0x32, 0x44, 0x3a, 0x31, 0x2d, 0x33, 0x4d, 0x32, 0x20, 0x28, 0x41, 0x33, 0x2e, 0x4b, 0x56, 0x30, 0x30, 0x4b, 0x2e, 0x30, 0x29, 0x00]
avrdude_git_arduino: received SIB: [AVR P:2D:1-3M2 (A3.KV00K.0)]
avrdude_git_arduino: Device family ID: AVR
avrdude_git_arduino: NVM interface: P:2
avrdude_git_arduino: Debug interface: D:1
avrdude_git_arduino: PDI oscillator: 3M2
avrdude_git_arduino: Extra information: (A3.KV00K.0)
avrdude_git_arduino: NVM type 2: 24-bit, word oriented write
avrdude_git_arduino: reading 1 bytes from 0x000F01
avrdude_git_arduino: ST_PTR to 0x000F01
avrdude_git_arduino: sending 5 bytes [0x55, 0x6a, 0x01, 0x0f, 0x00]
avrdude_git_arduino: send: U [55] j [6a] . [01] . [0f] . [00]
avrdude_git_arduino: recv: U [55] j [6a] . [01] . [0f] . [00]
avrdude_git_arduino: recv: @ [40]
avrdude_git_arduino: received 1 bytes [0x40]
avrdude_git_arduino: LD8 from ptr++
avrdude_git_arduino: sending 2 bytes [0x55, 0x24]
avrdude_git_arduino: send: U [55] $ [24]
avrdude_git_arduino: recv: U [55] $ [24]
avrdude_git_arduino: recv: . [13]
avrdude_git_arduino: received 1 bytes [0x13]
avrdude_git_arduino: Received chip silicon revision 0x13
avrdude_git_arduino: Chip silicon revision: 1.3
avrdude_git_arduino: STCS 0x08 to address 0x03
avrdude_git_arduino: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_git_arduino: send: U [55] . [c3] . [08]
avrdude_git_arduino: recv: U [55] . [c3] . [08]
avrdude_git_arduino: STCS 0x80 to address 0x02
avrdude_git_arduino: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_git_arduino: send: U [55] . [c2] . [80]
avrdude_git_arduino: recv: U [55] . [c2] . [80]
avrdude_git_arduino: LDCS from 0x00
avrdude_git_arduino: sending 2 bytes [0x55, 0x80]
avrdude_git_arduino: send: U [55] . [80]
avrdude_git_arduino: recv: U [55] . [80]
avrdude_git_arduino: recv: 0 [30]
avrdude_git_arduino: received 1 bytes [0x30]
avrdude_git_arduino: UDPI init OK
avrdude_git_arduino: entering NVM programming mode
avrdude_git_arduino: LDCS from 0x0B
avrdude_git_arduino: sending 2 bytes [0x55, 0x8b]
avrdude_git_arduino: send: U [55] . [8b]
avrdude_git_arduino: recv: U [55] . [8b]
avrdude_git_arduino: recv: . [92]
avrdude_git_arduino: received 1 bytes [0x92]
avrdude_git_arduino: UPDI writing key
avrdude_git_arduino: sending 2 bytes [0x55, 0xe0]
avrdude_git_arduino: send: U [55] . [e0]
avrdude_git_arduino: recv: U [55] . [e0]
avrdude_git_arduino: sending 8 bytes [0x20, 0x67, 0x6f, 0x72, 0x50, 0x4d, 0x56, 0x4e]
avrdude_git_arduino: send: [20] g [67] o [6f] r [72] P [50] M [4d] V [56] N [4e]
avrdude_git_arduino: recv: [20] g [67] o [6f] r [72] P [50] M [4d] V [56] N [4e]
avrdude_git_arduino: LDCS from 0x07
avrdude_git_arduino: sending 2 bytes [0x55, 0x87]
avrdude_git_arduino: send: U [55] . [87]
avrdude_git_arduino: recv: U [55] . [87]
avrdude_git_arduino: recv: . [10]
avrdude_git_arduino: received 1 bytes [0x10]
avrdude_git_arduino: key status: 0x10
avrdude_git_arduino: sending reset request
avrdude_git_arduino: STCS 0x59 to address 0x08
avrdude_git_arduino: sending 3 bytes [0x55, 0xc8, 0x59]
avrdude_git_arduino: send: U [55] . [c8] Y [59]
avrdude_git_arduino: recv: U [55] . [c8] Y [59]
avrdude_git_arduino: sending release reset request
avrdude_git_arduino: STCS 0x00 to address 0x08
avrdude_git_arduino: sending 3 bytes [0x55, 0xc8, 0x00]
avrdude_git_arduino: send: U [55] . [c8] . [00]
avrdude_git_arduino: recv: U [55] . [c8] . [00]
avrdude_git_arduino: LDCS from 0x0B
avrdude_git_arduino: sending 2 bytes [0x55, 0x8b]
avrdude_git_arduino: send: U [55] . [8b]
avrdude_git_arduino: recv: U [55] . [8b]
avrdude_git_arduino: recv: 8 [38]
avrdude_git_arduino: received 1 bytes [0x38]
avrdude_git_arduino: LDCS from 0x0B
avrdude_git_arduino: sending 2 bytes [0x55, 0x8b]
avrdude_git_arduino: send: U [55] . [8b]
avrdude_git_arduino: recv: U [55] . [8b]
avrdude_git_arduino: recv: . [08]
avrdude_git_arduino: received 1 bytes [0x08]
avrdude_git_arduino: entered NVM programming mode
avrdude_git_arduino: AVR device initialized and ready to accept instructions
Reading | | 0% 0.00 s
avrdude_git_arduino: LDCS from 0x0B
avrdude_git_arduino: sending 2 bytes [0x55, 0x8b]
avrdude_git_arduino: send: U [55] . [8b]
avrdude_git_arduino: recv: U [55] . [8b]
avrdude_git_arduino: recv: . [08]
avrdude_git_arduino: received 1 bytes [0x08]
avrdude_git_arduino: LD from 0x001100
avrdude_git_arduino: sending 5 bytes [0x55, 0x08, 0x00, 0x11, 0x00]
avrdude_git_arduino: send: U [55] . [08] . [00] . [11] . [00]
avrdude_git_arduino: recv: U [55] . [08] . [00] . [11] . [00]
avrdude_git_arduino: recv: . [1e]
avrdude_git_arduino: received 1 bytes [0x1e]
avrdude_git_arduino: LD from 0x001101
avrdude_git_arduino: sending 5 bytes [0x55, 0x08, 0x01, 0x11, 0x00]
avrdude_git_arduino: send: U [55] . [08] . [01] . [11] . [00]
avrdude_git_arduino: recv: U [55] . [08] . [01] . [11] . [00]
avrdude_git_arduino: recv: . [96]
avrdude_git_arduino: received 1 bytes [0x96]
avrdude_git_arduino: LD from 0x001102
avrdude_git_arduino: sending 5 bytes [0x55, 0x08, 0x02, 0x11, 0x00]
avrdude_git_arduino: send: U [55] . [08] . [02] . [11] . [00]
avrdude_git_arduino: recv: U [55] . [08] . [02] . [11] . [00]
avrdude_git_arduino: recv: . [1a]
avrdude_git_arduino: received 1 bytes [0x1a]
Reading | ################################################## | 100% 0.01 s
avrdude_git_arduino: device signature = 0x1e961a (probably avr64dd32)
avrdude_git_arduino: leaving NVM programming mode
avrdude_git_arduino: sending reset request
avrdude_git_arduino: STCS 0x59 to address 0x08
avrdude_git_arduino: sending 3 bytes [0x55, 0xc8, 0x59]
avrdude_git_arduino: send: U [55] . [c8] Y [59]
avrdude_git_arduino: recv: U [55] . [c8] Y [59]
avrdude_git_arduino: sending release reset request
avrdude_git_arduino: STCS 0x00 to address 0x08
avrdude_git_arduino: sending 3 bytes [0x55, 0xc8, 0x00]
avrdude_git_arduino: send: U [55] . [c8] . [00]
avrdude_git_arduino: recv: U [55] . [c8] . [00]
avrdude_git_arduino: STCS 0x0C to address 0x03
avrdude_git_arduino: sending 3 bytes [0x55, 0xc3, 0x0c]
avrdude_git_arduino: send: U [55] . [c3] . [0c]
avrdude_git_arduino: recv: U [55] . [c3] . [0c]
avrdude_git_arduino done. Thank you.
Thoughts on silicon revision checking
Revision checking is currently implemented in four types: jtag3.c, jtagmkII.c, serialupdi.c, and stk500v2.c. Among these, jtag is called with optional functions such as "pgm->read_chip_rev". STK500/600 is also referenced after "program_enable". Before that, only serialupdi.c is referenced.
If you think about it, the revision information should be a clue to identifying the errata, which is her 4th byte in the 3-byte signature extension. Therefore, it stands to reason that there is a close relationship between signatures and amendments. It would be even more useful if they were displayed side by side in the console log.
I think it would be better and more consistent to implement serialupdi.c, similar to jtag*.c. I think that's the case based on main.c, what do you think?
@askn37
Reading chip revision is already done in PR #1474 by @MCUdude, for jtag3.c, jtagmkII.c, serialupdi.c, and stk500v2.c
. So you are saying the implementation for serialupdi.c
is different from the other three and you want to make it consistent, right?
@mcuee
Yes, that's right.
By the way, I have often read REVID by writing it as below.
memory "revid"
size = 1;
offset = 0x0f01;
readsize = 1;
;
echo dump revid | avrdude -qt ...
There is a reason why I got into the habit of checking REVID. The SIB of AVR32DA32 rev.A3 that I obtained in the past is
AVR_____P:2D:1-3
This is the same as AVR_DB and later, "AVR" + 5 spaces.
However, the SIB of AVR128DA28 rev.A7 that I ordered after that was
____AVR_P:2D:1-3
Same style as tinyAVR/megaAVR, 4 blank spaces + "AVR"? ? ? (In addition, it was an error product that was not normally shipped because it had a large scratch caused by a failure to cut it with a diamond saw)
Apparently AVR128DA28/32/48/64 (DS40002183C) is this old style. AVR64DA28/32/48/64 (DS40002233B) and AVR32DA28/32/48 (DS40002228B) are different in some strange ways.
Guys, I'm sorry, but I feel a bit lost in these discussions, and I find them harder and harder to follow. Apologies if you expect my input on some of the topics brought up here, but at this point I can only react on certain trigger words :)
I noticed discussion about RTS/DTR and using it for resetting AVR - sounds like a good idea, but before you make changes to the code that handles it in SerialUPDI, please note that this additional setting (-x rtsdtr=[low|high]
) was implemented specifically to enable aforementioned SerialUPDI programmer by MCUDude to toggle between UPDI and Serial mode. I'm talking about this device (which I'm also using, but only in SerialUPDI mode):
So, my point is that whatever you decide about using RTS/DTR lines, please keep in mind that there is at least one device in the wild that makes strong assumption as to what these signals are for, and compatibility, if possible, should be maintained.
Otherwise, if you need me to look at some code or test something - please tag me in the post, otherwise I might miss it.
@dbuchwald
I think the only thing for you now is to take a look at the log from @askn37 here to see if you have any concerns or not.
There is a warning in his log.
avrdude: forcing serial DTR/RTS handshake lines HIGH
avrdude: NVM type 3: 24-bit, page oriented
avrdude: entering NVM programming mode
avrdude serialupdi_enter_progmode() error: key was not accepted
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e961f (probably avr64ea32)
@askn37 mentions the following which may or may not be an issue.
This indicates that the UPDI layer has not yet fully woken up when reading "UPDI_CS_ASI_KEY_STATUS" after sending "UPDI_SIB_128", or that key activation took longer than usual. I'm sure avrdude is impatient. There probably aren't any other concerns. thank you.
Thoughts on silicon revision checking
Revision checking is currently implemented in four types: jtag3.c, jtagmkII.c, serialupdi.c, and stk500v2.c. Among these, jtag is called with optional functions such as "pgm->read_chip_rev". STK500/600 is also referenced after "program_enable". Before that, only serialupdi.c is referenced.
If you think about it, the revision information should be a clue to identifying the errata, which is her 4th byte in the 3-byte signature extension. Therefore, it stands to reason that there is a close relationship between signatures and amendments. It would be even more useful if they were displayed side by side in the console log.
I think it would be better and more consistent to implement serialupdi.c, similar to jtag*.c. I think that's the case based on main.c, what do you think?
@askn37
You are welcome to come out with a PR to make serialupdi.c
handling of chip revision ID to be more consistent with the others. Thanks.
So, my point is that whatever you decide about using RTS/DTR lines, please keep in mind that there is at least one device in the wild that makes strong assumption as to what these signals are for, and compatibility, if possible, should be maintained.
So there will be three cases.
1) typical serialupdi programmer which has only three lines --> VCC, GND and UPDI.
2) @MCUdude's specific SerialUPDI programmer which has dual mode (UPDI and UART mode). The code currently supports this with -x rtsdtr=[low|high
.
3) Other UPDI programmers which may provide DTR/RTS pins to reset the MCU.
@dbuchwald and @stefanrueger
One possibilty is to use a different -x generic_rts
and -x generic_dtr
for the 3rd type, if we want to support the 3rd type.
@stefanrueger
I get the impression that updi_set_rtsdtr_mode() is meant for communication via DTR and for reset via RTS. If this is the case, I think we should separate rts and dtr handling into two functions serial_set_rts() and serial_set_dtr() to manage the signals independently.
The only reason this was implemented was to support the dual-mode operation of MCUdude's programmer. I don't remember why it was both RTS and DTR at the same time, but maybe it could be separated.
I'm currently going over the very long e-mail discussion between myself and MCUdude about the quirks of serial interfaces, and I found some small things that might help you anticipate potential issues:
The reason why I asked you to implement "pull DTR/RTS low" during the Avrdude session was that I could use this signal on the programmer to automatically switch between UPDI and serial mode. I think we both agree that this is a nice feature. This would work because DTR/RTS signal is high when a serial monitor is open. Now we have a signal that switches between high and low, indicating what "mode" we are in.
Or so I thought...
It turns out that the statement above is correct if you're using a Mac as I do. On Windows and Linux (I've tested with Ubuntu), the DTR/RTS signal is actually pulled low when a serial connection is open. This is the opposite of what's happening on my mac! There are even people asking about this on Stack Overflow: https://stackoverflow.com/questions/17601142/os-x-serial-port-open-with-dtr-low
After more research, I discovered that this is probably a bug in the Apple CH340 driver that ships with MacOS. After upgrading the driver to the one from WCH (the manufacturer of CH340 chips), this problem is solved, and DTR/RTS stays low when a serial session is active.
Also another thing is that the 300-baud workaround I borrowed from pymcuprog
(and the reason for it was that tcsendbreak
not being portable) can cause pulses on these DTR/RTS lines in some cases:
The reason you were seeing these pulses during AVRDUDE session (usually only at the beginning), is that there is somewhat weird code in the serialupdi driver. I took it directly from pymcuprog, and I must say I didn’t like it a lot, but assumed it necessary. See, NVM programming interface works as very simple and limited state machine. Should something go wrong it simply clams up and stops responding to any requests at all. The only way to get it to work again is to force NVM controller reset by sending two consecutive serial break messages around 24ms each. The way it is implemented in pymcuprog (and this is the part I didn’t like) is that connection mode is changed to 300 baud 8E1 and 0x00 value is sent out. 0x00 encoded in 8E1 at 300 baud translates to approx. 24ms low signal and does the job. I copied this functionality hoping to look into it some day and possibly fix it in my implementation. Now, what happens is in AVRDUDE is that the code responsible for changing connection speed actually disconnects serial and connects it again, changing some internal OS driver structures. These disconnect/connect events were causing strange pulses you saw.
Again, I'm not trying to say that my implementation is perfect and should not be changed. Feel free to change it any way you want, and if you need my help, I will provide it.
What I am saying is that when I worked on it almost two years ago I went through a lot of testing in different environments, and some discrepancies between them were deal-breakers for some pretty good ideas. That being said, context might have changed during these two years, some of these issues might have been fixed. Maybe the MacOS bug has been fixed in the meantime.
HEADS UP
Using DTR/RTS instead of GPIO will definitely have side effects as it is not compliant with regulations such as RS232C. Don't expect 100% compatibility. . . . But it's convenient, isn't it?
This would be a good standard to use. DTR/RTS is not asserted. The behavior when opened varies depending on the OS and driver. In most cases, RTS=LOW and DTR=LOW when open and RTS=HIGH and DTR=HIGH when closed. So if your target has an auto-reset circuit (series capacitor), it will reset every time you open it again.
The CH330/CH340 series was well received, so the manufacturer improved the driver so that RTS=LOW when opened.
When opened, asserts DTR/RTS. The UART switching implementation for "microUPDI adapter" will not work properly because DTR = HIGH and RTS = HIGH. Workarounds include turning off "hardware flow", temporarily setting it to 0bps, and running stty. (I'm not good at it so I don't know the details)
DTR/RTS is normally not asserted. You can turn DTR/RTS on and off individually as needed using the "hardware flow" or using a macro file.
HEADS UP
Using DTR/RTS instead of GPIO will definitely have side effects as it is not compliant with regulations such as RS232C. Don't expect 100% compatibility. . . . But it's convenient, isn't it?
To be honest, I think we (avrdude project) do not really need to take care of the serial monitor function. Rather we need to take care of the programming function which may invovle chip reset.
There are special cases for serialupdi which takes care of @MCUdude's paticular design.
For jtag2updi, it is the same siutation, only certain type of cictuits will work with -xrtsdtr
. My Uno clones do not work.
If we really want to be more generic, I think we need generic dtr
, rts
and at least cts
handling to give the user more freedoms. But then we can only cater for typical circuits and probably not for all cases.
So far the following PR seems to work fine for different platforms. The focus is the bootloaders (urclock, optiboot and wiring) programming where proper chip reset is important. The focus is not the UART monitor.
OK, I learned a few things about the way different OS assert DTR/RTS during the low-level open()
call of the serial port; I also learned about the behaviour of several terminal programs and how it affects some auto-reset circuits. My take-away is that we should improve the documentation of this aspect in doc/avrdude.texi
, for example by providing a section 5.5 Auto-reset boards with information from https://github.com/avrdudes/avrdude/issues/1529#issuecomment-1783764457. I'd like to invite @askn37 to start a PR on this. I would be happy to contribute to it. And don't worry about language @askn37: your English is crisp and clear.
By the way, I have often read REVID by writing it as below.
memory "revid" size = 1; offset = 0x0f01; readsize = 1; ; echo dump revid | avrdude -qt ...
@askn37 Pro Tip: try using avrdude -qT "read io 0xf01 1"
instead. See this discussion why we implemented the general io
memory rather than (many) memories like revid
. I plan a future PR that adds a new terminal command register
and the symbolic layout of the register file for each part, so you can query register syscfg.revid
instead of read io 0xf01
.
Other than this, we probably might want to close the issue as the main problem that NVMCTRL v3 should use 24 bit is solved.
@dbuchwald Thanks for explaining the motivation and history of the rtsdts handling. That is really helpful!
@mcuee
To be honest, I think we (avrdude project) do not really need to take care of the serial monitor function. Rather we need to take care of the programming function which may invovle chip reset.
Ok, I agree with that policy. (However, since the main purpose of UART passthrough is to allow "programming writer" and "serial monitor" to coexist, you should keep in mind that there are some combinations that will not work as expected. In that case, "programming writer" must be given priority.)
Other than this, we probably might want to close the issue as the main problem that NVMCTRL v3 should use 24 bit is solved.
I agree.
@mcuee
To be honest, I think we (avrdude project) do not really need to take care of the serial monitor function. Rather we need to take care of the programming function which may invovle chip reset.
Ok, I agree with that policy. (However, since the main purpose of UART passthrough is to allow "programming writer" and "serial monitor" to coexist, you should keep in mind that there are some combinations that will not work as expected. In that case, "programming writer" must be given priority.)
Yes, I agree with you here.
Just want to mention the sleep MinGW issue is indeed specific to MSYS2 mingw compiler. I just built avrdude using MSYS2 clang64 and it works fine.
PS> .\avrdude_git_clang64.exe -c serialupdi -P COM41 -p avr64dd32 -vvvv
avrdude_git_clang64: Version 7.2-20231024 (d6c61f5f)
Copyright the AVRDUDE authors;
see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is C:\work\avr\avrdude_test\avrdude_bin\avrdude.conf
Using Port : COM41
Using Programmer : serialupdi
avrdude_git_clang64: opening serial port ...
avrdude_git_clang64: sending 1 bytes [0x00]
avrdude_git_clang64: send: . [00]
avrdude_git_clang64: recv: . [00]
AVR Part : AVR64DD32
RESET disposition : dedicated
RETRY pulse : SCK
Serial program mode : yes
Parallel program mode : yes
Memory Detail :
...
avrdude_git_clang64: STCS 0x08 to address 0x03
avrdude_git_clang64: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_git_clang64: send: U [55] . [c3] . [08]
avrdude_git_clang64: recv: U [55] . [c3] . [08]
avrdude_git_clang64: STCS 0x80 to address 0x02
avrdude_git_clang64: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_git_clang64: send: U [55] . [c2] . [80]
avrdude_git_clang64: recv: U [55] . [c2] . [80]
avrdude_git_clang64: LDCS from 0x00
avrdude_git_clang64: sending 2 bytes [0x55, 0x80]
avrdude_git_clang64: send: U [55] . [80]
avrdude_git_clang64: recv: U [55] . [80]
avrdude_git_clang64: recv: 0 [30]
avrdude_git_clang64: received 1 bytes [0x30]
avrdude_git_clang64: UDPI init OK
avrdude_git_clang64: UPDI link initialization OK
avrdude_git_clang64: LDCS from 0x0B
avrdude_git_clang64: sending 2 bytes [0x55, 0x8b]
avrdude_git_clang64: send: U [55] . [8b]
avrdude_git_clang64: recv: U [55] . [8b]
avrdude_git_clang64: recv: . [92]
avrdude_git_clang64: received 1 bytes [0x92]
avrdude_git_clang64: device is in SLEEP mode
avrdude_git_clang64: sending 2 bytes [0x55, 0xe6]
avrdude_git_clang64: send: U [55] . [e6]
avrdude_git_clang64: recv: U [55] . [e6]
avrdude_git_clang64: recv: A [41] V [56] R [52] [20] [20] [20] [20] [20] P [50] : [3a] 2 [32] D [44] : [3a] 1 [31] - [2d] 3 [33] M [4d] 2 [32] [20] ( [28] A [41] 3 [33] . [2e] K [4b] V [56] 0 [30] 0 [30] K [4b] . [2e] 0 [30] ) [29] . [00]
avrdude_git_clang64: received 32 bytes [0x41, 0x56, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x3a, 0x32, 0x44, 0x3a, 0x31, 0x2d, 0x33, 0x4d, 0x32, 0x20, 0x28, 0x41, 0x33, 0x2e, 0x4b, 0x56, 0x30, 0x30, 0x4b, 0x2e, 0x30, 0x29, 0x00]
avrdude_git_clang64: received SIB: [AVR P:2D:1-3M2 (A3.KV00K.0)]
avrdude_git_clang64: Device family ID: AVR
avrdude_git_clang64: NVM interface: P:2
avrdude_git_clang64: Debug interface: D:1
avrdude_git_clang64: PDI oscillator: 3M2
avrdude_git_clang64: Extra information: (A3.KV00K.0)
avrdude_git_clang64: NVM type 2: 24-bit, word oriented write
avrdude_git_clang64: reading 1 bytes from 0x000F01
avrdude_git_clang64: ST_PTR to 0x000F01
avrdude_git_clang64: sending 5 bytes [0x55, 0x6a, 0x01, 0x0f, 0x00]
avrdude_git_clang64: send: U [55] j [6a] . [01] . [0f] . [00]
avrdude_git_clang64: recv: U [55] j [6a] . [01] . [0f] . [00]
avrdude_git_clang64: recv: @ [40]
avrdude_git_clang64: received 1 bytes [0x40]
avrdude_git_clang64: LD8 from ptr++
avrdude_git_clang64: sending 2 bytes [0x55, 0x24]
avrdude_git_clang64: send: U [55] $ [24]
avrdude_git_clang64: recv: U [55] $ [24]
avrdude_git_clang64: recv: . [13]
avrdude_git_clang64: received 1 bytes [0x13]
avrdude_git_clang64: Received chip silicon revision 0x13
avrdude_git_clang64: Chip silicon revision: 1.3
avrdude_git_clang64: STCS 0x08 to address 0x03
avrdude_git_clang64: sending 3 bytes [0x55, 0xc3, 0x08]
avrdude_git_clang64: send: U [55] . [c3] . [08]
avrdude_git_clang64: recv: U [55] . [c3] . [08]
avrdude_git_clang64: STCS 0x80 to address 0x02
avrdude_git_clang64: sending 3 bytes [0x55, 0xc2, 0x80]
avrdude_git_clang64: send: U [55] . [c2] . [80]
avrdude_git_clang64: recv: U [55] . [c2] . [80]
avrdude_git_clang64: LDCS from 0x00
avrdude_git_clang64: sending 2 bytes [0x55, 0x80]
avrdude_git_clang64: send: U [55] . [80]
avrdude_git_clang64: recv: U [55] . [80]
avrdude_git_clang64: recv: 0 [30]
avrdude_git_clang64: received 1 bytes [0x30]
avrdude_git_clang64: UDPI init OK
avrdude_git_clang64: entering NVM programming mode
avrdude_git_clang64: LDCS from 0x0B
avrdude_git_clang64: sending 2 bytes [0x55, 0x8b]
avrdude_git_clang64: send: U [55] . [8b]
avrdude_git_clang64: recv: U [55] . [8b]
avrdude_git_clang64: recv: . [92]
avrdude_git_clang64: received 1 bytes [0x92]
avrdude_git_clang64: UPDI writing key
avrdude_git_clang64: sending 2 bytes [0x55, 0xe0]
avrdude_git_clang64: send: U [55] . [e0]
avrdude_git_clang64: recv: U [55] . [e0]
avrdude_git_clang64: sending 8 bytes [0x20, 0x67, 0x6f, 0x72, 0x50, 0x4d, 0x56, 0x4e]
avrdude_git_clang64: send: [20] g [67] o [6f] r [72] P [50] M [4d] V [56] N [4e]
avrdude_git_clang64: recv: [20] g [67] o [6f] r [72] P [50] M [4d] V [56] N [4e]
avrdude_git_clang64: LDCS from 0x07
avrdude_git_clang64: sending 2 bytes [0x55, 0x87]
avrdude_git_clang64: send: U [55] . [87]
avrdude_git_clang64: recv: U [55] . [87]
avrdude_git_clang64: recv: . [10]
avrdude_git_clang64: received 1 bytes [0x10]
avrdude_git_clang64: key status: 0x10
avrdude_git_clang64: sending reset request
avrdude_git_clang64: STCS 0x59 to address 0x08
avrdude_git_clang64: sending 3 bytes [0x55, 0xc8, 0x59]
avrdude_git_clang64: send: U [55] . [c8] Y [59]
avrdude_git_clang64: recv: U [55] . [c8] Y [59]
avrdude_git_clang64: sending release reset request
avrdude_git_clang64: STCS 0x00 to address 0x08
avrdude_git_clang64: sending 3 bytes [0x55, 0xc8, 0x00]
avrdude_git_clang64: send: U [55] . [c8] . [00]
avrdude_git_clang64: recv: U [55] . [c8] . [00]
avrdude_git_clang64: LDCS from 0x0B
avrdude_git_clang64: sending 2 bytes [0x55, 0x8b]
avrdude_git_clang64: send: U [55] . [8b]
avrdude_git_clang64: recv: U [55] . [8b]
avrdude_git_clang64: recv: 8 [38]
avrdude_git_clang64: received 1 bytes [0x38]
avrdude_git_clang64: LDCS from 0x0B
avrdude_git_clang64: sending 2 bytes [0x55, 0x8b]
avrdude_git_clang64: send: U [55] . [8b]
avrdude_git_clang64: recv: U [55] . [8b]
avrdude_git_clang64: recv: . [08]
avrdude_git_clang64: received 1 bytes [0x08]
avrdude_git_clang64: entered NVM programming mode
avrdude_git_clang64: AVR device initialized and ready to accept instructions
Reading | | 0% 0.00 s
avrdude_git_clang64: LDCS from 0x0B
avrdude_git_clang64: sending 2 bytes [0x55, 0x8b]
avrdude_git_clang64: send: U [55] . [8b]
avrdude_git_clang64: recv: U [55] . [8b]
avrdude_git_clang64: recv: . [08]
avrdude_git_clang64: received 1 bytes [0x08]
avrdude_git_clang64: LD from 0x001100
avrdude_git_clang64: sending 5 bytes [0x55, 0x08, 0x00, 0x11, 0x00]
avrdude_git_clang64: send: U [55] . [08] . [00] . [11] . [00]
avrdude_git_clang64: recv: U [55] . [08] . [00] . [11] . [00]
avrdude_git_clang64: recv: . [1e]
avrdude_git_clang64: received 1 bytes [0x1e]
avrdude_git_clang64: LD from 0x001101
avrdude_git_clang64: sending 5 bytes [0x55, 0x08, 0x01, 0x11, 0x00]
avrdude_git_clang64: send: U [55] . [08] . [01] . [11] . [00]
avrdude_git_clang64: recv: U [55] . [08] . [01] . [11] . [00]
avrdude_git_clang64: recv: . [96]
avrdude_git_clang64: received 1 bytes [0x96]
avrdude_git_clang64: LD from 0x001102
avrdude_git_clang64: sending 5 bytes [0x55, 0x08, 0x02, 0x11, 0x00]
avrdude_git_clang64: send: U [55] . [08] . [02] . [11] . [00]
avrdude_git_clang64: recv: U [55] . [08] . [02] . [11] . [00]
avrdude_git_clang64: recv: . [1a]
avrdude_git_clang64: received 1 bytes [0x1a]
Reading | ################################################## | 100% 0.02 s
avrdude_git_clang64: device signature = 0x1e961a (probably avr64dd32)
avrdude_git_clang64: leaving NVM programming mode
avrdude_git_clang64: sending reset request
avrdude_git_clang64: STCS 0x59 to address 0x08
avrdude_git_clang64: sending 3 bytes [0x55, 0xc8, 0x59]
avrdude_git_clang64: send: U [55] . [c8] Y [59]
avrdude_git_clang64: recv: U [55] . [c8] Y [59]
avrdude_git_clang64: sending release reset request
avrdude_git_clang64: STCS 0x00 to address 0x08
avrdude_git_clang64: sending 3 bytes [0x55, 0xc8, 0x00]
avrdude_git_clang64: send: U [55] . [c8] . [00]
avrdude_git_clang64: recv: U [55] . [c8] . [00]
avrdude_git_clang64: STCS 0x0C to address 0x03
avrdude_git_clang64: sending 3 bytes [0x55, 0xc3, 0x0c]
avrdude_git_clang64: send: U [55] . [c3] . [0c]
avrdude_git_clang64: recv: U [55] . [c3] . [0c]
avrdude_git_clang64 done. Thank you.
I'm looking into "serialupdi_initialize".
Things I can do right away:
The "read chip silicon revision" process that inspired this investigation can be improved by simply moving it to the end of the function. Since "serialupdi_enter_progmode" is called before that, "UPDI_ASI_SYS_STATUS_NVMPROG" will be true and will not be affected. (However, if "LOCKSTATUS=1", NVMPROG will fail, so you should not investigate)
Strange part:
"updi_read_sib" is called after checking "UPDI_ASI_SYS_STATUS". This is strange. This is because "UPDI_ASI_SYS_STATUS" expands with each version of his NVMCTRL. v0 has meaning on 5 bits, v2 has meaning on 6 bits, and v3 has meaning on all 8 bits. Therefore, you need to check the version of NVMCTRL by calling 'updi_read_sib' and reading 'UPDI_ASI_SYS_STATUS'. There are no particular problems with v2. However, v3 added an important "BOOTDONE" bit. Set to 1 when the CPU completes the "power-on reset" boot process. Otherwise, you are not ready to run "serialupdi_enter_progmode". So you have to read "UPDI_ASI_SYS_STATUS" again and wait until it becomes 1, or try a few times and abort on timeout. And that should be done before any other investigation.
What I know:
For NVMCTRLv0/2, it is safe to run "serialupdi_enter_progmode" when "RSTSYS=0", "INSLEEP=any", "NVMPROG=any", "UROWPROG=0", "LOCKSTATUS=0". v3 also requires "BOOTDONE=1". (At the same time, for v3, this may make it less susceptible to the negative effects of DTR/RTS control.) ('INSLEEP=1' can be ignored as 'ASI_RESET' is used to enable 'NVMPROG_KEY'. However, at this stage if 'NVMPROG=1' use 'RSTSYS =0') is needed.)
Things I can do right away:
The "read chip silicon revision" process that inspired this investigation can be improved by simply moving it to the end of the function. Since "serialupdi_enter_progmode" is called before that, "UPDI_ASI_SYS_STATUS_NVMPROG" will be true and will not be affected. (However, if "LOCKSTATUS=1", NVMPROG will fail, so you should not investigate)
@askn37
I think this is safe to do. PR is welcome.
Report: Incorrect SerialUPDI control of AVR64EA32
This is a known bug as of commit 481a91d.
case.1 Debug log
case.2 Debug log
Need additional information?
I design my own program writer and create firmware that meets various practical needs. This time, we also acquired control including HV programming using AVR64EA32. I noticed this problem when I was doing comparison testing with other programmers.
NVMCTRL version 3 can correctly interpret 24-bit extended addresses. Although this is clearly stated in the datasheet, NVMCTRL_ADDRESS is a 24-bit register. This allows 16-bit address commands for UPDI access to correspond to LD/ST instructions, and 24-bit address commands to correspond to ELPM/SPM instructions. To treat the flash memory area linearly, you need to set his MSB of this address. In other words, the setting value is 0x800000 or higher. This behavior is equivalent to the AVR_Dx series (NVMCTRL version 2).
This series has a maximum flash capacity of 64KiB, so there is no RAMPZ register. The FLMAP field, which switches the latter bank of data space, also uses only one bit. However, there is no need to manipulate these from UPDI.
REVID register 0xF01 is a register in the IO memory space, so it can only be read when the CPU is active or in his NVMPROG mode. The current implementation of SerialUPDI probably does not take into account the existence of power-saving devices that regularly use CPU sleep.
(Supplement) Use PF6 (RESET pad) to enable high voltage mode. The datasheet states the absolute rating is 9V. Therefore, a suitable high voltage here is 8.2 V when using a Zener diode. However, PICkit4 can exceed this voltage and violate ESD protection.
Further additional information
There are two execution result logs here. Both are displayed when -vvvvq is specified. One result is the target device is asleep, and the other result is the target device is running.
test_run.log test_sleep.log