stefanrueger / urboot

Small AVR bootloader using urprotocol
GNU General Public License v3.0
57 stars 9 forks source link

Autobaud does not work on one ATmega328P board under Windows #5

Closed mcuee closed 1 year ago

mcuee commented 1 year ago

Interestingly I have a Arduino Nano clone with CH340 and Atmega328P (5V, 16MHz). It works well with 115200bps and even 1000000bps urboot hex file (tested with the variant (tested with ee_led+b5_fr_ce_ur_vbl) but not working with the autobaud firmware (no matter which baud rate I try). Kind of strange.

The autobaud FW works fine with my Uno Clone (ATmega328P, 5V, 16MHz) and Mega2560 Clone (ATmega2560, 5V, 16MHz).

Maybe this is not a real issue but rather board specific.

mcuee commented 1 year ago

Only difference is -DWDTO=8S.

So timing? Well, I don't get this. The bootloaders were compiled with -DWDTO=1S. Plenty'o time for the host to send the first command (and can delay, too, with -xdelay=...). Baud rate "negotiation" takes as long as it takes to send one byte (< 1ms).

Are you sure you set the fuses correct? And deleted flash before burning the bootloader? Note, you cannot put a program and a vector bootloader onto the chip at the same time. The vector bootloader must be burned onto an erased chip first. Then you can upload with the vector bootloader (remember -c urclock patches the application - you miss this when you burn the unpatched application plus vector bootloader at the same time).

If you look at my runlog, I use usbasp to burn the FW, so an erase will happen. I tested again under Linux, it actually works under Linux using stock urboot FW.

So Windows is the issue here. It does not work with the stock urboot FW, no matter which -xdelay= value I use. It works with the -DWDTO=8S FW.

Windows runlog: you can see the 8s urboot FW works but stock urboot FW does not work.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v7 -C .\avrdude_pr1171v7.conf -c usbasp
 -p m328p -U .\atmega328p_autobaud_ee_led+b5_fr_ce_ur_vbl_wdt8s.hex -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v7 -C .\avrdude_pr1171v7.conf -c urclock
 -P COM10 -b 115200 -p m328p -xshowall

avrdude_pr1171v7: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 384 u7.7 weu-jPrac vector 25 
(SPM_Ready) ATmega328P

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v7 -C .\avrdude_pr1171v7.conf -c usbasp
 -p m328p -U .\atmega328p_autobaud_ee_led+b5_fr_ce_ur_vbl.hex -qq && echo OK
OK
PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v7 -C .\avrdude_pr1171v7.conf -c urclock
 -P COM10 -b 115200 -p m328p -xshowall
avrdude_pr1171v7 warning: attempt 1 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 2 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 3 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 4 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 5 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 6 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 7 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 8 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 9 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 10 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 11 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 12 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 13 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 14 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 15 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 16 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 17 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 18 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 19 of 20: not in sync
avrdude_pr1171v7 warning: programmer is not responding; try, eg, -xdelay=200
avrdude_pr1171v7 warning: attempt 20 of 20: not in sync
avrdude_pr1171v7 error: unable to open programmer urclock on port COM10

avrdude_pr1171v7 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v7 -C .\avrdude_pr1171v7.conf -c usbasp
 -p m328p -U .\atmega328p_autobaud_ee_led+b5_fr_ce_ur_vbl_wdt8s.hex -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v7 -C .\avrdude_pr1171v7.conf -c urclock
 -P COM10 -b 115200 -p m328p -U .\hex\Blink.ino.standard.hex

avrdude_pr1171v7: AVR device initialized and ready to accept instructions
avrdude_pr1171v7: device signature = 0x1e950f (probably m328p)
avrdude_pr1171v7: Note: flash memory has been specified, an erase cycle will be performed.
                  To disable this feature, specify the -D option.
avrdude_pr1171v7: erasing chip
avrdude_pr1171v7: reading input file .\hex\Blink.ino.standard.hex for flash
                  with 924 bytes in 1 section within [0, 0x39b]
                  using 8 pages and 100 pad bytes
avrdude_pr1171v7: preparing flash input for device bootloader
avrdude_pr1171v7: writing 924 bytes flash ...

Writing | ################################################## | 100% 0.23 s

avrdude_pr1171v7: 924 bytes of flash written
avrdude_pr1171v7: verifying flash memory against .\hex\Blink.ino.standard.hex

Reading | ################################################## | 100% 0.14 s

avrdude_pr1171v7: 924 bytes of flash verified

avrdude_pr1171v7 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v7 -C .\avrdude_pr1171v7.conf -c urclock
 -P COM10 -b 115200 -p m328p -xshowall

avrdude_pr1171v7: AVR device initialized and ready to accept instructions
0000ffffffff 2022-06-10 21.21 Blink.ino.standard.hex 924 store 31426 meta 34 boot 384 u7.7 
weu-jPrac vector 25 (SPM_Ready) ATmega328P
stefanrueger commented 1 year ago

So Windows is the issue here.

I wonder whether excluding Windows from reducing the drain timeout is to blame here: https://github.com/avrdudes/avrdude/blob/7f4474f0497099f9ad048948a53383b4cd729327/src/urclock.c#L2046-L2048 Maybe windows need slightly different values than the 250 ms default?

Other than that, it could be peculiarities on the rx line when opening the serial port. An oscilloscope might show what happens with the rx line in Windows and what in Linuz.

mcuee commented 1 year ago

@stefanrueger I will give the time out value a try later under Windows. As for using scope, that may not be feasible any time soon.

mcuee commented 1 year ago

Re-open to continue the discussion.

mcuee commented 1 year ago

@stefanrueger

I tried the following and it does not help. --> Sorry wrong one. Ignore this one.

$ git diff
diff --git a/src/urclock.c b/src/urclock.c
index c66c616..bfb1990 100644
--- a/src/urclock.c
+++ b/src/urclock.c
@@ -2043,9 +2043,9 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) {
     usleep((80+ur.delay)*1000); // Wait until board comes out of reset

   // Drain any extraneous input
-#ifndef WIN32
-  serial_drain_timeout = 80;    // ms
-#endif
+//#ifndef WIN32
+//  serial_drain_timeout = 80;    // ms
+//#endif
   serial_drain(&pgm->fd, 0);

   if(urclock_getsync(pgm) < 0)
mcuee commented 1 year ago

@stefanrueger

This works for me.

$ git diff
diff --git a/src/urclock.c b/src/urclock.c
index c66c616..28673f2 100644
--- a/src/urclock.c
+++ b/src/urclock.c
@@ -2045,6 +2045,8 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) {
   // Drain any extraneous input
 #ifndef WIN32
   serial_drain_timeout = 80;    // ms
+#else
+  serial_drain_timeout = 150;    // ms
 #endif
   serial_drain(&pgm->fd, 0);
mcuee commented 1 year ago

So Windows is the issue here.

I wonder whether excluding Windows from reducing the drain timeout is to blame here: https://github.com/avrdudes/avrdude/blob/7f4474f0497099f9ad048948a53383b4cd729327/src/urclock.c#L2046-L2048 Maybe windows need slightly different values than the 250 ms default?

You are absolutely right, 80ms works for Windows as well. So the following simple fix should work. I've tested 150ms and 200ms as well -- they work as well but 250ms failed for the Nano Clone.

$ git diff
diff --git a/src/urclock.c b/src/urclock.c
index c66c616..ba081d4 100644
--- a/src/urclock.c
+++ b/src/urclock.c
@@ -2043,9 +2043,7 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) {
     usleep((80+ur.delay)*1000); // Wait until board comes out of reset

   // Drain any extraneous input
-#ifndef WIN32
   serial_drain_timeout = 80;    // ms
-#endif
   serial_drain(&pgm->fd, 0);

   if(urclock_getsync(pgm) < 0)

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM6 -p m328p -xshowall

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 384 u7.7 weu-jPrac vector 25 (SPM_Ready) ATmega328P

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM6 -b 7800 -p m328p -xshowall

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 384 u7.7 weu-jPrac vector 25 (SPM_Ready) ATmega328P
C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM6 -b 3000000 -p m328p -xshowall

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 384 u7.7 weu-jPrac vector 25 (SPM_Ready) ATmega328P

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM6 -b 3000000 -p m328p -U .\Blink_Uno.ino.hex -qq && echo OK
OK

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM6 -b 3000000 -p m328p -xshowall

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
0000ffffffff 2022-10-17 09.23 Blink_Uno.ino.hex 924 store 31431 meta 29 boot 384 u7.7 weu-jPrac vector 25 
(SPM_Ready) ATmega328P
mcuee commented 1 year ago

This change is also good for my Uno clone (ATmega16U2 USB to Serial FW). It is just that very high baud rate does not work well for sketch upload (only works up to 1,300,000bps) during the verification stage. -xshowall works up to 3,000,000bps.

That is probably the limitation of ATmega16U2 USB to Serial FW. I checked the default 250ms version and it has the same results.

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM5 -b 1300000 -p m328p -U .\Blink_Uno.ino.hex

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
avrdude_pr1171v8mod_80ms: device signature = 0x1e950f (probably m328p)
avrdude_pr1171v8mod_80ms: Note: flash memory has been specified, an erase cycle will be performed.
                          To disable this feature, specify the -D option.
avrdude_pr1171v8mod_80ms: erasing chip
                          delaying chip erase until first -U upload to flash
avrdude_pr1171v8mod_80ms: reading input file .\Blink_Uno.ino.hex for flash
                          with 924 bytes in 1 section within [0, 0x39b]
                          using 8 pages and 100 pad bytes
avrdude_pr1171v8mod_80ms: preparing flash input for device bootloader
avrdude_pr1171v8mod_80ms: writing 924 bytes flash ...

Writing | ################################################## | 100% 3.63 s

avrdude_pr1171v8mod_80ms: 924 bytes of flash written
avrdude_pr1171v8mod_80ms: verifying flash memory against .\Blink_Uno.ino.hex

Reading | ################################################## | 100% 1.45 s

avrdude_pr1171v8mod_80ms: 924 bytes of flash verified

avrdude_pr1171v8mod_80ms done.  Thank you.

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM5 -b 1400000 -p m328p -U .\Blink_Uno.ino.hex

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
avrdude_pr1171v8mod_80ms: device signature = 0x1e950f (probably m328p)
avrdude_pr1171v8mod_80ms: Note: flash memory has been specified, an erase cycle will be performed.
                          To disable this feature, specify the -D option.
avrdude_pr1171v8mod_80ms: erasing chip
                          delaying chip erase until first -U upload to flash
avrdude_pr1171v8mod_80ms: reading input file .\Blink_Uno.ino.hex for flash
                          with 924 bytes in 1 section within [0, 0x39b]
                          using 8 pages and 100 pad bytes
avrdude_pr1171v8mod_80ms: preparing flash input for device bootloader
avrdude_pr1171v8mod_80ms: writing 924 bytes flash ...

Writing | ################################################## | 100% 3.66 s

avrdude_pr1171v8mod_80ms: 924 bytes of flash written
avrdude_pr1171v8mod_80ms: verifying flash memory against .\Blink_Uno.ino.hex

Reading | -------------------------------------------------- | 0% 0.00 s

avrdude_pr1171v8mod_80ms error: protocol expects sync byte 0x20 but got 0x04 in urclock_paged_load()
avrdude_pr1171v8mod_80ms error: protocol expects sync byte 0x20 but got 0x78 in ur_readEF()
avrdude_pr1171v8mod_80ms error: unable to read byte at address 0x0000
avrdude_pr1171v8mod_80ms error: read operation not supported for memory flash
avrdude_pr1171v8mod_80ms error: unable to read all of flash memory, rc=-2
avrdude_pr1171v8mod_80ms error: protocol expects sync byte 0x20 but got 0xcf

avrdude_pr1171v8mod_80ms done.  Thank you.

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM5 -b 1400000 -p m328p -xshowall

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
0 2022-10-17 09.23 Blink_Uno.ino.hex 924 store 31559 meta 29 boot 256 u7.7 w-u-jpra- vector 25 
(SPM_Ready) ATmega328P

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf
 -c urclock -P COM5 -b 2000000 -p m328p -xshowall

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
0 2022-10-17 09.23 Blink_Uno.ino.hex 924 store 31559 meta 29 boot 256 u7.7 w-u-jpra- vector 25 
(SPM_Ready) ATmega328P

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_pr1171v8mod_80ms -C .\avrdude_pr1171v8.conf -c urclock
 -P COM5 -b 3000000 -p m328p -xshowall

avrdude_pr1171v8mod_80ms: AVR device initialized and ready to accept instructions
0 2022-10-17 09.23 Blink_Uno.ino.hex 924 store 31559 meta 29 boot 256 u7.7 w-u-jpra- vector 25 
(SPM_Ready) ATmega328P

-c arduino has the same limitation anyway (tested using atmega328p_autobaud_ee_led+b5_fr_ce.hex). So this is okay.

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c arduino -P COM5 -b 1400000 -p m328p
 -D -U .\Blink_Uno.ino.hex

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e950f (probably m328p)
avrdude: reading input file .\Blink_Uno.ino.hex for flash
         with 924 bytes in 1 section within [0, 0x39b]
         using 8 pages and 100 pad bytes
avrdude: writing 924 bytes flash ...

Writing | ################################################## | 100% 0.14 s

avrdude: 924 bytes of flash written
avrdude: verifying flash memory against .\Blink_Uno.ino.hex

Reading | -------------------------------------------------- | 0% 0.01 s

avrdude error: protocol expects sync byte 0x14 but got 0x04
avrdude error: programmer is out of sync
avrdude error: unable to read byte at address 0x0000
avrdude error: read operation not supported for memory flash
avrdude error: unable to read all of flash memory, rc=-2
avrdude error: protocol expects sync byte 0x14 but got 0x94

avrdude done.  Thank you.

C:\work\avr\avrdude_test\avrdude_bin> .\avrdude -c arduino -P COM5 -b 1300000 -p m328p
 -D -U .\Blink_Uno.ino.hex

avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e950f (probably m328p)
avrdude: reading input file .\Blink_Uno.ino.hex for flash
         with 924 bytes in 1 section within [0, 0x39b]
         using 8 pages and 100 pad bytes
avrdude: writing 924 bytes flash ...

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

avrdude: 924 bytes of flash written
avrdude: verifying flash memory against .\Blink_Uno.ino.hex

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

avrdude: 924 bytes of flash verified

avrdude done.  Thank you.
mcuee commented 1 year ago

Since this is avrdude -c urclock issue and not urboot issue now, I will close again.

stefanrueger commented 1 year ago

but 250ms failed for the Nano Clone.

So, I am guessing that a 250 ms drain timeout setting in windows can translate to around 1000 ms wait and borderline a timeout for boards that come out of reset slower than others. I think (speculate!) that's because in windows the drain timeout is applied between characters as well as a final wait for characters after the last one was read; in Linux it's only the latter as far as I know.

So, with 80 ms for Windows, all is OK? autobaud? fixed baud? different boards?

BTW, I would be surprised if the LGT8F328P worked with the autobaud detection: The reason is that the loop that measures the baud rate must be 5 clock cycles to work, but according to this document the number of clock cycles is different for all three instructions in the loop at https://github.com/stefanrueger/urboot/blob/0adff89272870681b1d9145acce0a57dda267cb6/src/urboot.c#L2323-L2325 are shorter, so the loop consumes 3 cycles, not 5. This also means that SWIO (software I/O) does not work for the LGT8F328P with the bootloader.

stefanrueger commented 1 year ago

works up to 3,000,000bps.

If it's a 16 MHz board this cannot be. Max is F_CPU/8, ie 2 MHz baud rate. So really important to establish what baud rate is actually used. Ralph recommends studying the kernel source to figure out what the actual generated baud rate is: https://github.com/avrdudes/avrdude/pull/1171#issuecomment-1317656886

mcuee commented 1 year ago

If it's a 16 MHz board this cannot be. Max is F_CPU/8, ie 2 MHz baud rate. So really important to establish what baud rate is actually used. Ralph recommends studying the kernel source to figure out what the actual generated baud rate is: avrdudes/avrdude#1171 (comment)

Yes I believe Linux only selects the nearby baud rate. Anyway, this is not a real isse -- we can dig out the kernel source code later.

mcuee commented 1 year ago

So, I am guessing that a 250 ms drain timeout setting in windows can translate to around 1000 ms wait and borderline a timeout for boards that come out of reset slower than others. I think (speculate!) that's because in windows the drain timeout is applied between characters as well as a final wait for characters after the last one was read; in Linux it's only the latter as far as I know.

So, with 80 ms for Windows, all is OK? autobaud? fixed baud? different boards?

Yes 80ms for Windows is good for my boards tested -- Uno ATmgea16U2 clone, Uno CH340 Clone, Nano CH340 Clone {all three using ATmega328P at 16MHz) and Mega2560 CH340 clone.

The Uno ATmgea16U2 clone, Uno CH340 Clone and Mega2560 CH340 clone work well with the default 250ms drain timeout value. Only the Nano Clone does not work.

But if you are really concerned about this parameter, you may want to get a new extension parameter like -xdrain= (default 80ms) for the user to specify in case they encounter issues.

BTW, I would be surprised if the LGT8F328P worked with the autobaud detection: The reason is that the loop that measures the baud rate must be 5 clock cycles to work, but according to this document the number of clock cycles is different for all three instructions in the loop at.

I do not have the programmer setting up for the LGT8F328P so I can not burn the bootloader . I was using the factory bootloader (-c arduino compatible, only 57600bps) for the testing.

mcuee commented 1 year ago

If it's a 16 MHz board this cannot be. Max is F_CPU/8, ie 2 MHz baud rate. So really important to establish what baud rate is actually used. Ralph recommends studying the kernel source to figure out what the actual generated baud rate is: avrdudes/avrdude#1171 (comment)

I think the real test is to flash a hex file. -xshowall somehow works to rediculosly high baud rate due to Linux baud rate behaviors.

The Uno clone with ATmega16U2 USB to Serial FW is using kernel CDC-ACM driver. It only works to 1,000,000bps.

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ ./avrdude_pr1171v8 -C ./avrdude_pr1171v8.conf -c urclock
 -P /dev/ttyACM0 -b 1100000 -p m328p -U ./blink_m328p.hex 

avrdude_pr1171v8: AVR device initialized and ready to accept instructions
avrdude_pr1171v8: device signature = 0x1e950f (probably m328p)
avrdude_pr1171v8: Note: flash memory has been specified, an erase cycle will be performed.
                  To disable this feature, specify the -D option.
avrdude_pr1171v8: erasing chip
avrdude_pr1171v8: reading input file ./blink_m328p.hex for flash
                  with 1030 bytes in 1 section within [0, 0x405]
                  using 9 pages and 122 pad bytes
avrdude_pr1171v8: preparing flash input for device bootloader
avrdude_pr1171v8: writing 1030 bytes flash ...

Writing | ################################################## | 100% 0.11 s 

avrdude_pr1171v8: 1030 bytes of flash written
avrdude_pr1171v8: verifying flash memory against ./blink_m328p.hex

Reading | -------------------------------------------------- | 0% 0.00 s 

avrdude_pr1171v8 error: protocol expects sync byte 0xa0 but got 0x01 in urclock_paged_load()
avrdude_pr1171v8 error: protocol expects sync byte 0xa0 but got 0x77 in ur_readEF()
avrdude_pr1171v8 error: unable to read byte at address 0x0000
avrdude_pr1171v8 error: read operation not supported for memory flash
avrdude_pr1171v8 error: unable to read all of flash memory, rc=-2
avrdude_pr1171v8 error: protocol expects sync byte 0xa0 but got 0xcf

avrdude_pr1171v8 done.  Thank you.

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ ./avrdude_pr1171v8 -C ./avrdude_pr1171v8.conf -c urclock
 -P /dev/ttyACM0 -b 1000000 -p m328p -U ./blink_m328p.hex 

avrdude_pr1171v8: AVR device initialized and ready to accept instructions
avrdude_pr1171v8: device signature = 0x1e950f (probably m328p)
avrdude_pr1171v8: Note: flash memory has been specified, an erase cycle will be performed.
                  To disable this feature, specify the -D option.
avrdude_pr1171v8: erasing chip
avrdude_pr1171v8: reading input file ./blink_m328p.hex for flash
                  with 1030 bytes in 1 section within [0, 0x405]
                  using 9 pages and 122 pad bytes
avrdude_pr1171v8: preparing flash input for device bootloader
avrdude_pr1171v8: writing 1030 bytes flash ...

Writing | ################################################## | 100% 0.11 s 

avrdude_pr1171v8: 1030 bytes of flash written
avrdude_pr1171v8: verifying flash memory against ./blink_m328p.hex

Reading | ################################################## | 100% 0.04 s 

avrdude_pr1171v8: 1030 bytes of flash verified

avrdude_pr1171v8 done.  Thank you.

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ ./avrdude_pr1171v8 -C ./avrdude_pr1171v8.conf -c urclock
 -P /dev/ttyACM0 -b 1000000 -p m328p -xshowall 

avrdude_pr1171v8: AVR device initialized and ready to accept instructions
ffffffffffff 2022-11-20 12.58 blink_m328p.hex 1030 store 31327 meta 27 boot 384 u7.7 
weu-jPrac vector 25 (SPM_Ready) ATmega328P

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ ./avrdude_pr1171v8 -C ./avrdude_pr1171v8.conf -c urclock
 -P /dev/ttyACM0 -b 100000000 -p m328p -xshowall 

avrdude_pr1171v8: AVR device initialized and ready to accept instructions
ffffffffffff 2022-11-20 12.58 blink_m328p.hex 1030 store 31327 meta 27 boot 384 u7.7 
weu-jPrac vector 25 (SPM_Ready) ATmega328P
mcuee commented 1 year ago

I think the real test is to flash a hex file.

This is not valid for CH340. It claims to work to baud rate above the crystal frequency, which can not be true.

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ ./avrdude_pr1171v8 -C ./avrdude_pr1171v8.conf -c urclock
 -P /dev/ttyUSB0 -b 24000000 -p m328p -U blink_m328p.hex 

avrdude_pr1171v8: AVR device initialized and ready to accept instructions
avrdude_pr1171v8: device signature = 0x1e950f (probably m328p)
avrdude_pr1171v8: Note: flash memory has been specified, an erase cycle will be performed.
                  To disable this feature, specify the -D option.
avrdude_pr1171v8: erasing chip
avrdude_pr1171v8: reading input file blink_m328p.hex for flash
                  with 1030 bytes in 1 section within [0, 0x405]
                  using 9 pages and 122 pad bytes
avrdude_pr1171v8: preparing flash input for device bootloader
avrdude_pr1171v8: writing 1030 bytes flash ...

Writing | ################################################## | 100% 1.36 s 

avrdude_pr1171v8: 1030 bytes of flash written
avrdude_pr1171v8: verifying flash memory against blink_m328p.hex

Reading | ################################################## | 100% 1.30 s 

avrdude_pr1171v8: 1030 bytes of flash verified

avrdude_pr1171v8 done.  Thank you.

Kernel drivver source code is here. https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c#L168

 * The device line speed is given by the following equation:
 *
 *  baudrate = 48000000 / (2^(12 - 3 * ps - fact) * div), where
 *
 *      0 <= ps <= 3,
 *      0 <= fact <= 1,
 *      2 <= div <= 256 if fact = 0, or
 *      9 <= div <= 256 if fact = 1
 */
mcuee commented 1 year ago

From https://superuser.com/questions/488449/is-there-any-way-to-check-which-baud-rates-are-supported-on-a-serial-device

The max baud rate for the CH340 under my Ubuntu 20.04 is 4,000,000 bps. Same for PL2303.

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ hfile=/usr/include/asm-generic/termbits.h ans=(yes no);column < <(
    while read -r bauds;do
        stty -F /dev/ttyUSB0 $bauds &>/dev/null
        printf '%8d %-3s\n' $bauds ${ans[$?]}
    done < <(
  sed -r 's/^#define\s+B([0-9]{2,})\s+.*/\1/p;d' <$hfile ))
      50 yes         134 yes         300 yes        1800 yes        9600 yes       57600 yes      460800 yes      921600 yes     1500000 yes     3000000 yes
      75 yes         150 yes         600 yes        2400 yes       19200 yes      115200 yes      500000 yes     1000000 yes     2000000 yes     3500000 yes
     110 yes         200 yes        1200 yes        4800 yes       38400 yes      230400 yes      576000 yes     1152000 yes     2500000 yes     4000000 yes

Same results for the CDC-ACM ATmega16U2.

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ hfile=/usr/include/asm-generic/termbits.h ans=(yes no);column < <(
    while read -r bauds;do
        stty -F /dev/ttyACM0 $bauds &>/dev/null
        printf '%8d %-3s\n' $bauds ${ans[$?]}
    done < <(
  sed -r 's/^#define\s+B([0-9]{2,})\s+.*/\1/p;d' <$hfile ))
      50 yes         134 yes         300 yes        1800 yes        9600 yes       57600 yes      460800 yes      921600 yes     1500000 yes     3000000 yes
      75 yes         150 yes         600 yes        2400 yes       19200 yes      115200 yes      500000 yes     1000000 yes     2000000 yes     3500000 yes
     110 yes         200 yes        1200 yes        4800 yes       38400 yes      230400 yes      576000 yes     1152000 yes     2500000 yes     4000000 yes

CP2102 has less number and also lower baud rate.

mcuee@UbuntuSwift3:~/build/avr/avrdude_bin$ hfile=/usr/include/asm-generic/termbits.h ans=(yes no);column < <(
    while read -r bauds;do
        stty -F /dev/ttyUSB0 $bauds &>/dev/null
        printf '%8d %-3s\n' $bauds ${ans[$?]}
    done < <(
  sed -r 's/^#define\s+B([0-9]{2,})\s+.*/\1/p;d' <$hfile ))
      50 no          134 no          300 yes        1800 yes        9600 yes       57600 yes      460800 yes      921600 yes     1500000 no      3000000 no 
      75 no          150 no          600 yes        2400 yes       19200 yes      115200 yes      500000 yes     1000000 yes     2000000 no      3500000 no 
     110 no          200 no         1200 yes        4800 yes       38400 yes      230400 yes      576000 yes     1152000 no      2500000 no      4000000 no 

I am not so sure if it is avrdude ser_posix.c is doing something or not to the baud rate.

mcuee commented 1 year ago

A good info about USB to TTL converter is here. It only caters for UPDI parts though. But practically speaking anything above 500,000bps may not help much (avrdude speed is similar using 1,000,000 bps and 500,000 bps) https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md

mcuee commented 1 year ago

So, I am guessing that a 250 ms drain timeout setting in windows can translate to around 1000 ms wait and borderline a timeout for boards that come out of reset slower than others. I think (speculate!) that's because in windows the drain timeout is applied between characters as well as a final wait for characters after the last one was read; in Linux it's only the latter as far as I know.

So, with 80 ms for Windows, all is OK? autobaud? fixed baud? different boards?

Yes 80ms for Windows is good for my boards tested -- Uno ATmgea16U2 clone, Uno CH340 Clone, Nano CH340 Clone {all three using ATmega328P at 16MHz) and Mega2560 CH340 clone.

The Uno ATmgea16U2 clone, Uno CH340 Clone and Mega2560 CH340 clone work well with the default 250ms drain timeout value. Only the Nano Clone does not work.

But if you are really concerned about this parameter, you may want to get a new extension parameter like -xdrain= (default 80ms) for the user to specify in case they encounter issues.

Oops, I find another issue now. If I use the Optiboot bootloader (optiboot_atmega328.hex from Arduino), the Nano Clone does not work well with 80ms, rather I need to add -xdelay=at least 20 to get it work with -c urclock. I also checked that it has no issue if I change the drain timeout to 150ms, 200ms or 250ms.

So the urboot autobaud FW works with 80ms but not 250ms. Optiboot FW works with 250ms but not 80ms. It seems to me 150ms may be a good compromise for Windows.

Sorry for the late findings.