Yet another UPDI programmer Mk II

Yet another UPDI programmer . . . but possibly the ultimate?

This simple to make UPDI programmer is a further development in a long quest (started here: ATtiny1614 / USBTTL adapter for UPDI programming and serial console access ) to have a programmer which, with one single USB adapter, could seamlessly, in a smooth workflow, handle both the UPDI programming and the serial communication with the target new series AVR devices together with the megaTiny core.

Yes, you always had the option of using a bootloader, but this is a miserable experience especially on the low pin count devices and, of course, you always do something similar with two USB/TTL adapters, one of which would be configured for UPDI, and two USB cables to achieve the same results. Then came solutions which used analog switch ICs to, with varying degrees of success, dynamically repurpose a single USB/TTL adaptor for the dual functions of programming the device via UPDI then swapping the role to that of a simple USB/TTL adaptor to handle the serial comms. Now finally the development described here, as the ultimate in both ease of use and ease of construction, using the now available CH342 module which presents itself to the PC host as USB-2 hub and additionally provides two USB/UART interfaces. All this, incidentally, without the need for any special drivers (at least not for Windows) other than those required for the ubiquitous CH340 devices found on many Arduino clones.

Some time ago, @DrAzzy, who refined serial UPDI to make it usable with AVR, wrote a prophetic piece on the direction of future developments in this area which, in retrospect, appears quite visionary from the perspective of the current state of the art, accurately predicting the emergence of devices such as the one described here. It can be read here (Ref 2 below).

Anyway, to visualise what it can do, see this simple screen shot showing two active comms channels, one for the UPDI interface and one for the USB/UART interface. IDE 1.x is used here for simpler simultaneous handling of 2 instance of the serial monitor. The target device is, incidentally, an ATtiny 1614:

This is how it appears in the Windows device manager:

Hardware build and schematic

Here is some of the detail about the device and what it looks like. It consists of a module CH342 USB-2TTL, stocked by a number of AliExpress retailers (I got mine from YourCee https://www.aliexpress.com/item/1005008001334082.html) and a small addon circuit consisting of two resistors and a diode together with a number of mainly optional connectors. Serial channel 0 (TX0/RX0) is dedicated to normal serial activities. Serial channel 1 (TX1/RX1) is dedicated to the role of UPDI programmer. Note, however, that a hardware modification, described later, has to be applied to the CH342 module to make it function as a UPDI interface. That is, the channel 1 leds have to be disabled and without this it simply will not work.

The complete schematic of the CH342 USB-2TTL module is included for reference together with that of the add-on circuit. Since I don't have a method of measuring the value of capacitors in circuit, I've left the values blank. The module design uses a common but crude method of handling the leds to signal serial activity on the RX and TX pins which affects the signal presented to the target UPDI port. In practical terms the solution is to disable the leds. The recommended way is to cut the PCB track identified in the picture. Other methods are removing the leds (or their series resistors). Any complete board (re-) design could use a transistor or similar component
to less invasively control the leds and without damaging the signal, the state of which, the leds are supposed to indicate. Note. Before you even start, verify the existing functionality of the CH342 USB-2TTL module so see the troubleshooting guide below for ideas on how to test it.

Schematic for both the CH342 USB-TTL module and the prototype board:
CH342F_V0_01.pdf (170.0 KB)

CH342 USB-2TTL module front with components labelled to match the schematic:

CH342 USB-2TTL module rear showing track to cut (red circle)

Prototype board front:

Prototype board rear (bus wires highlighted)

Performance tests

  • only tested with the MegaTinyCore [ref 2 below] and Arduino IDE 1.8.19 / Windows 10

  • The device appears to retain the same allocated com ports across sessions. I tried alternatively with the two devices I purchased and this behaviour was consistent.

  • Seems to work at 230400 baud (and of course 57600 baud) for UPDI at 5v.

  • 460800 baud worked with the "delay" option and failed, producing a screen load of error messages, without the delay. Again at 5v.

  • Attempts to use 921600 baud rates showed these were not actually attainable and the operation quietly fell back to 115200 baud proceeding to a successful result, albeit at a lower speed.

Troubleshooting

There is really not so much to go wrong assuming the basic testing shows the CH342 USM-2TTL is OK. However, if Window (or your OS) does not even recognise the device then look here first:

  • Ensure that you are using a USB "data" cable and not a simple "charging" cable.

  • If you are using Windows and have never previously used a device with a CH340 USB chip then, in this unlikely case, you have to find instructions to load the necessary drivers. See Ref 4 below.

If you get that far and still have problems:

  • You should previously have tested that the CH342 USB-2TTL device is capable of performing as a normal USB/UART device on both channels. This can be achieved by doing a loop back test using the 2 supplied jumpers and checking that what is typed in the serial monitor is echoed back. Do this for both COM ports.

  • You must also have successfully disabled the TX1/RX1 leds using either the suggested track cut or some other method. Don't even dream of getting it to work properly without this necessary step.

  • You have correctly assigned the two COM ports, that the device presents, to the respective functions UPDI and standard serial. Look in the device manager under Ports. The COM port for UPDI (TX1/RX1) will be labelled something like USB-Enhanced-SERIAL-B CH342. The "A" side is used for the normal serial function (TX0/RX0) [at least that is what my limited testing here has shown but I suppose the enumeration could be inverted]

  • Check that the jumper selectable voltage matches the selected voltage delivered to the target device. If the target device is also powered separately, disconnect the power output from the programmer.

  • If you are still having trouble, and have not already done so as a pre-build activity, then do a breadboard build of the 3 resistor / 1 diode circuit and check that out.

Alternatives and further improvements.

There is a similar chip to the CH340F as used in the USB-2TTL module, that is the CH340K. It has less pins broken out but would also function in this role and may be easier to hand solder. However, since it does not break out the RTS pin it cannot easily be used in addition as an FTDI type adaptor for programming the original series AVR or similar chips.

The addition of a 12v circuit could also be desirable to handle cases where the target's UPDI pin has been reassigned to another purpose and a high voltage programmer function is required to restore the device to its factory condition.

References:

  1. Spence Kondo megatiny core (UPDI stuff) AVR-Guidance/UPDI/jtag2updi.md at master · SpenceKonde/AVR-Guidance · GitHub
  2. Spence Kondo (general stuff including some visions of superior serial adapters) GitHub - SpenceKonde/megaTinyCore: Arduino core for the tinyAVR 0/1/2-series - Ones's digit 2,4,5,7 (pincount, 8,14,20,24), tens digit 0, 1, or 2 (featureset), preceded by flash in kb. Library maintainers: porting help available!
  3. CH342 datasheet (english) https://cdn.sparkfun.com/assets/8/e/f/5/1/CH342_Datasheet.pdf
  4. CH340 driver installation How to Install CH340 Drivers - SparkFun Learn
1 Like

Nicely done.

Your programmer actually made me think if it is possible to upload via UPDI and print with the same Arduino IDE window. Like we are used to when having a bootloader on e.g. a Arduino Uno.

You can, and it's simple.

After some experimenting on my breadboard I let the DTR pin from the serial adapter disconnect the Attiny TX pin from UPDI. After programming is done TX reconnects and you can resume printing.

Here is the schematic.

Instead of a PNP transistor you could use a P-channel mosfet, bus driver, logic gate or whatever. As long as you can disconnect the TX pin when sensing a HIGH level on the DTR pin.

1 Like

I've just tried it and of course it worked. I never considered that possibility. Excellent work!

This is how I configured it and tested with a CH342 USB/UART adaptor which breaks out the DTR signal:

I think I will make a plug-in board, like the one you have made, but then with just the 3 parts from my design. Then you can turn a regular serial adapter into a UPDI/TX-RX adapter without having to modify the serial adapter.

BTW, below is the weirdest of serial adapters I have. It works very well as UPDI adapter despite it violates all design rules stated in the UPDI documentation for Megatinycore. More info here

That is an interesting discussion about your particular serial adapter. It seems less like science and more like witchcraft. In fact, being able to conjure a usable signal out of the conjunction of a TX and RX signal (albeit with an intervening diode/resistor) seems odd to me to start with. Add in some modem control signals such as DTR and/or RTS which are open to all sorts of interpretation and it is indeed a wonder that the whole idea of being able to use a USB/UART adapter works. But it surely does.

I can't see enough detail on that miniature adapter that you published on the megaTiny github discussion forum, and couldn't find one exactly the same via Google images, to see whether you are duplicating the leds or it simply didn't have any to begin with. The leds on the CH342 adapter I used above definitely had to be disabled otherwise its performance in this role as UPDI programmer was, for all practical purposes, useless although I could get some sporadic and barely repeatable successes out of it at 3 volts and at low speed.

MCUdude / @hansibull published a design of a UPDI programmer here: https://www.tindie.com/products/mcudude/serialupdi-programmer/ where he used the RTS signal as the basis for the role swapping but mentioned some possible caveats for some edge cases. I wanted to avoid that complexity although I guess in practice, apart from under some exotic circumstances, it would work fine.

I see also some UPDI programmer designs which have a 12v high voltage function for complete device resets. I suppose that would complete the picture although I never would require this since I don't repurpose the UPDI pin.

I have two of those as I bumped my nose first when I built a serial adapter based HV UPDI programmer that did not do a powercycle. It could only revive a few of the first generation UPDI Attinies, but failed to revive a 2-series Attiny. That's when I found out a bout the required Powerycle. More info here, but you have seen that post.

The serial adapter based HV programmer should be possible to add the disconnecting TX pin, if I can make the DTR line also turn off the 12V when the TX line is connected, to prevent blowing up the TX pin with 12V. Oh I now see I protected the serial adapter RX pin with just a resistor against the 12V. Like what you have done with your design with the 1K resistors.

This is the adapter I bought. It has the leds onboard already. My schematic depicts everything that is between the CH340G chip and the Attiny chip. I only added the small signal diode myself.

That adapter is tiny and quite sparsely populated. Interestingly, it uses the CH340G chip (or clone) which needs an external crystal and its two load capacitors. They could have spared even those three components by using the CH340C.

The chip must anyway be quite robust if it can function reliably without any of the expected current limiting resistors. Anyway, regarding the price, these things are so cheap that the user can afford to dedicate them to a specific role.

I hadn't looked too deeply at the high voltage programmer because I would tend to use higher pin count part than start reassigning the UPDI pin. For hobby usage that is OK. For large volume commercial products clearly that is a different matter and every cent counts.

More out of curiosity, I had a quick look at this Microchip document regarding the high voltage programmer: Unified Program and Debug Interface (UPDI) High-Voltage Activation Information - Developer Help. It doesn't seem to distinguish between the TinyAVR series 0, 1 or 2 so I guess that the special reported problems related to the series 2 devices are only that an existing specification is being more rigidly adhered to rather than something new has been introduced. As far as I can understand from it a chip, which is having its UPDI pin functionality restored, has to go through the following phases:

  1. A reset
  2. A 12v pulse must be delivered no later than 10ms following the reset. During that 10ms, even if the UPDI pin is currently configured as an output GPIO pin, this output configuration is inhibited to prevent a potentially damaging conflict.
  3. Within 65ms, a valid either "chip erase" or "NWM enable" instruction has to be presented on the UPDI pin.
    If that doesn't all work, the previous configuration is restored.

I guess 2) above could explain some reported "bricked" chips and 3) could explain why a high voltage programmer needs a comprehensive firmware.

However, I won't be looking at this in too much detail since I should hopefully not need this function for my own activities.

That's done now and I tested all my serial adapters that break out the DTR pin (the adapters you can use for a Arduino Promini). Two of them work on all upload speeds and 4 of them don't work at all.

The red one on the left is the FTDI adapter with the fake FTDI chip that pops up in every search when you look for "FT232RL adapter".

The ones that don't work, probably need their leds desoldered or some resistor removed, but I did not look at that any further. For me it works easy.

You have an impressive collection of adapters there with quite a variety of USB connectors. I'll be retiring my non USB-C adapters to minimise the cable salad I maintain as these are so cheap now.

Is that series of tests you've just completed with a Schottky diode or a normal small silicon signal type ?
I guess that some of those adapters would never work with a normal silicon diode.

Also did you look carefully through the log output of the Turbo attempt to check it had not fallen back (quietly) to 11500 baud ?

The maximum I can get is 460800 baud at 5v and that only if I select the option with the write delay. I even shorted out the additional resistors but it made no difference.

Turbo terminates OK for me but only after falling back to 115200.

OSINTOT

I used a Schottky diode on the perfboard, as that's what I also used on the breadboard.

Here are the logfiles of the upload. It seems to switch back and forth between baudrates, but I can't make heads or tails out of it what now is the actual baudrate it's uploading with. When looking in the log at the "action took x.xx s" there is quite a difference. The green one is faster.

This is the output of the red fake FTDI adapter.

SerialUPDI
UPDI programming for Arduino using a serial adapter
Based on pymcuprog, with significant modifications
By Quentin Bolsee and Spence Konde
Version 1.2.3 - Jan 2022
Using serial port COM8 at 921600 baud.
Target: attiny412
Set fuses: ['0:0b00000000', '2:0x01', '6:0x04', '7:0x00', '8:0x00']
Action: write
File: C:\Users\Hans\AppData\Local\Temp\arduino_build_968113/Attiny1626_reading_SBUS_to_servo_and_or_serial_V4.ino.hex
pymcuprog.programmer - INFO - Setting up programming session for 'attiny412'
pymcuprog.deviceinfo.deviceinfo - INFO - Looking for device attiny412
pymcuprog.serialupdi.physical - INFO - Opening port 'COM8' at '115200' baud
pymcuprog.serialupdi.link - INFO - STCS 08 to 0x03
pymcuprog.serialupdi.link - INFO - STCS 06 to 0x02
pymcuprog.serialupdi.link - INFO - LDCS from 0x00
pymcuprog.serialupdi.link - INFO - UPDI init OK
pymcuprog.serialupdi.link - INFO - STCS 06 to 0x02
pymcuprog.serialupdi.link - INFO - Setting UPDI clock to 16 MHz
pymcuprog.serialupdi.link - INFO - STCS 01 to 0x09
pymcuprog.serialupdi.physical - INFO - Switching to '921600' baud
pymcuprog.serialupdi.application - INFO - SIB: 'tinyAVR P:0D:0-3M2 (01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Device family ID: 'tinyAVR'
pymcuprog.serialupdi.application - INFO - NVM interface: 'P:0'
pymcuprog.serialupdi.application - INFO - Debug interface: 'D:0'
pymcuprog.serialupdi.application - INFO - PDI oscillator: '3M2'
pymcuprog.serialupdi.application - INFO - Extra info: '(01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Using 16-bit UPDI
pymcuprog.serialupdi.link - INFO - LDCS from 0x00
pymcuprog.serialupdi.application - INFO - PDI revision = 0x02
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.application - INFO - Entering NVM programming mode
pymcuprog.serialupdi.link - INFO - LDCS from 0x07
pymcuprog.serialupdi.application - INFO - Apply reset
pymcuprog.serialupdi.link - INFO - STCS 59 to 0x08
pymcuprog.serialupdi.application - INFO - Release reset
pymcuprog.serialupdi.link - INFO - STCS 00 to 0x08
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.nvm - INFO - No specific initializer for this provider
Pinging device...
pymcuprog.programmer - INFO - Reading device ID...
pymcuprog.serialupdi.application - INFO - SIB: 'tinyAVR P:0D:0-3M2 (01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Device family ID: 'tinyAVR'
pymcuprog.serialupdi.application - INFO - NVM interface: 'P:0'
pymcuprog.serialupdi.application - INFO - Debug interface: 'D:0'
pymcuprog.serialupdi.application - INFO - PDI oscillator: '3M2'
pymcuprog.serialupdi.application - INFO - Extra info: '(01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Using 16-bit UPDI
pymcuprog.serialupdi.link - INFO - LDCS from 0x00
pymcuprog.serialupdi.application - INFO - PDI revision = 0x02
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.application - INFO - Device ID from pyupdi = '1E9223' rev 'B'
pymcuprog.nvm - INFO - Device ID: '1E9223'
pymcuprog.nvm - INFO - Device revision: 'B'
pymcuprog.nvm - INFO - Device serial number: 'b'51525251312061981c2e''
Ping response: 1E9223
Setting fuse 0x0=0x0
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.19s
Setting fuse 0x2=0x1
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.20s
Setting fuse 0x6=0x4
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.19s
Setting fuse 0x7=0x0
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.19s
Setting fuse 0x8=0x0
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.19s
Finished writing fuses.
Chip/Bulk erase,
Memory type eeprom is conditionally erased (depending upon EESAVE fuse setting)
Memory type flash is always erased
Memory type lockbits is always erased
...
pymcuprog.programmer - INFO - Erase...
pymcuprog.serialupdi.nvm - INFO - Chip erase using NVM CTRL
Erased.
Action took 0.06s
Writing from hex file...
Writing flash...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1902 bytes of data to flash...
[==================================================] 30/30
pymcuprog.programmer - INFO - Write complete.
Action took 2.04s
Verifying...
pymcuprog.programmer - INFO - Reading 1902 bytes from flash...
[==================================================] 4/4
pymcuprog.programmer - INFO - Verifying...
Verify successful. Data in flash matches data in specified hex-file
Action took 0.16s
pymcuprog.serialupdi.application - INFO - Leaving NVM programming mode
pymcuprog.serialupdi.application - INFO - Apply reset
pymcuprog.serialupdi.link - INFO - STCS 59 to 0x08
pymcuprog.serialupdi.application - INFO - Release reset
pymcuprog.serialupdi.link - INFO - STCS 00 to 0x08
pymcuprog.serialupdi.link - INFO - STCS 0C to 0x03
pymcuprog.serialupdi.physical - INFO - Closing port 'COM8'

The green CH340G adapter

SerialUPDI
UPDI programming for Arduino using a serial adapter
Based on pymcuprog, with significant modifications
By Quentin Bolsee and Spence Konde
Version 1.2.3 - Jan 2022
Using serial port COM4 at 921600 baud.
Target: attiny412
Set fuses: ['0:0b00000000', '2:0x01', '6:0x04', '7:0x00', '8:0x00']
Action: write
File: C:\Users\Hans\AppData\Local\Temp\arduino_build_968113/Attiny1626_reading_SBUS_to_servo_and_or_serial_V4.ino.hex
pymcuprog.programmer - INFO - Setting up programming session for 'attiny412'
pymcuprog.deviceinfo.deviceinfo - INFO - Looking for device attiny412
pymcuprog.serialupdi.physical - INFO - Opening port 'COM4' at '115200' baud
pymcuprog.serialupdi.link - INFO - STCS 08 to 0x03
pymcuprog.serialupdi.link - INFO - STCS 06 to 0x02
pymcuprog.serialupdi.link - INFO - LDCS from 0x00
pymcuprog.serialupdi.link - INFO - UPDI init OK
pymcuprog.serialupdi.link - INFO - STCS 06 to 0x02
pymcuprog.serialupdi.link - INFO - Setting UPDI clock to 16 MHz
pymcuprog.serialupdi.link - INFO - STCS 01 to 0x09
pymcuprog.serialupdi.physical - INFO - Switching to '921600' baud
pymcuprog.serialupdi.application - INFO - SIB: 'tinyAVR P:0D:0-3M2 (01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Device family ID: 'tinyAVR'
pymcuprog.serialupdi.application - INFO - NVM interface: 'P:0'
pymcuprog.serialupdi.application - INFO - Debug interface: 'D:0'
pymcuprog.serialupdi.application - INFO - PDI oscillator: '3M2'
pymcuprog.serialupdi.application - INFO - Extra info: '(01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Using 16-bit UPDI
pymcuprog.serialupdi.link - INFO - LDCS from 0x00
pymcuprog.serialupdi.application - INFO - PDI revision = 0x02
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.application - INFO - Entering NVM programming mode
pymcuprog.serialupdi.link - INFO - LDCS from 0x07
pymcuprog.serialupdi.application - INFO - Apply reset
pymcuprog.serialupdi.link - INFO - STCS 59 to 0x08
pymcuprog.serialupdi.application - INFO - Release reset
pymcuprog.serialupdi.link - INFO - STCS 00 to 0x08
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.nvm - INFO - No specific initializer for this provider
Pinging device...
pymcuprog.programmer - INFO - Reading device ID...
pymcuprog.serialupdi.application - INFO - SIB: 'tinyAVR P:0D:0-3M2 (01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Device family ID: 'tinyAVR'
pymcuprog.serialupdi.application - INFO - NVM interface: 'P:0'
pymcuprog.serialupdi.application - INFO - Debug interface: 'D:0'
pymcuprog.serialupdi.application - INFO - PDI oscillator: '3M2'
pymcuprog.serialupdi.application - INFO - Extra info: '(01.59B14.0)'
pymcuprog.serialupdi.application - INFO - Using 16-bit UPDI
pymcuprog.serialupdi.link - INFO - LDCS from 0x00
pymcuprog.serialupdi.application - INFO - PDI revision = 0x02
pymcuprog.serialupdi.link - INFO - LDCS from 0x0B
pymcuprog.serialupdi.application - INFO - Device ID from pyupdi = '1E9223' rev 'B'
pymcuprog.nvm - INFO - Device ID: '1E9223'
pymcuprog.nvm - INFO - Device revision: 'B'
pymcuprog.nvm - INFO - Device serial number: 'b'51525251312061981c2e''
Ping response: 1E9223
Setting fuse 0x0=0x0
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.03s
Setting fuse 0x2=0x1
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.03s
Setting fuse 0x6=0x4
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.03s
Setting fuse 0x7=0x0
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.03s
Setting fuse 0x8=0x0
Writing literal values...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1 bytes of data to fuses...
pymcuprog.programmer - INFO - Write complete.
Verifying literal values...
pymcuprog.programmer - INFO - Reading 1 bytes from fuses...
pymcuprog.programmer - INFO - Verifying...
Action took 0.03s
Finished writing fuses.
Chip/Bulk erase,
Memory type eeprom is conditionally erased (depending upon EESAVE fuse setting)
Memory type flash is always erased
Memory type lockbits is always erased
...
pymcuprog.programmer - INFO - Erase...
pymcuprog.serialupdi.nvm - INFO - Chip erase using NVM CTRL
Erased.
Action took 0.02s
Writing from hex file...
Writing flash...
pymcuprog.programmer - INFO - Write...
pymcuprog.programmer - INFO - Writing 1902 bytes of data to flash...
[==================================================] 30/30
pymcuprog.programmer - INFO - Write complete.
Action took 0.24s
Verifying...
pymcuprog.programmer - INFO - Reading 1902 bytes from flash...
[==================================================] 4/4
pymcuprog.programmer - INFO - Verifying...
Verify successful. Data in flash matches data in specified hex-file
Action took 0.05s
pymcuprog.serialupdi.application - INFO - Leaving NVM programming mode
pymcuprog.serialupdi.application - INFO - Apply reset
pymcuprog.serialupdi.link - INFO - STCS 59 to 0x08
pymcuprog.serialupdi.application - INFO - Release reset
pymcuprog.serialupdi.link - INFO - STCS 00 to 0x08
pymcuprog.serialupdi.link - INFO - STCS 0C to 0x03
pymcuprog.serialupdi.physical - INFO - Closing port 'COM4'

OSINTOT - "Oh Shit, I Never Thought Of That"

Yours looks OK, or at least you don't appear to have had a specific warning.

This is what I get with Turbo:

pymcuprog.serialupdi.physical - INFO - Switching to '921600' baud
pymcuprog.serialupdi.application - WARNING - Cannot read SIB, hard reset...
pymcuprog.serialupdi.physical - INFO - Sending double break
pymcuprog.serialupdi.physical - INFO - Double-break sent. Retrying.
pymcuprog.serialupdi.physical - INFO - Opening port 'COM10' at '115200' baud

But then it goes on to a successful termination.

Thanks for explaining. Then something else than baudrate must be causing the green adapter to complete writing in 0.24s vs the red one that needs 10 times longer with 2.04s.

Here: GitHub - SpenceKonde/megaTinyCore: Arduino core for the tinyAVR 0/1/2-series - Ones's digit 2,4,5,7 (pincount, 8,14,20,24), tens digit 0, 1, or 2 (featureset), preceded by flash in kb. Library maintainers: porting help available! under the title UPDI programming, there is a mention of "long latencies" with those FTDI type adapters. Maybe that is the explanation.

It was.
Setting that from 16 to 1 changed the upload time to 0.17s on the FTDI