Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Arduino auto-reset via DTR/RTS/CTS to allow direct reset connection #1262

Closed
mariusgreuel opened this issue Jan 3, 2023 · 24 comments · Fixed by #1309
Closed

Change Arduino auto-reset via DTR/RTS/CTS to allow direct reset connection #1262

mariusgreuel opened this issue Jan 3, 2023 · 24 comments · Fixed by #1309
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@mariusgreuel
Copy link
Contributor

Currently, the Arduino and urclock programmers attempt to auto-reset the board via the RTS line, to kick it into bootloader mode. On open, the do a 'RTS=0, Sleep, RTS=1', which pulls the reset line low. On close they do a 'RTS=0', which pulls the reset line high again. In other words, during the whole operation the RTS line stays at low-level.

To avoid a continuous reset, this behavior requires a special circuit that turns the low-level signal into a low pulse. For instance, the Arduino Uno has a capacitor in between the RTS line and the reset pin.

For testing with boards that do not have the integrated RTS reset circuitry, I would like to be able to simply connect the chips reset pin to the RTS pin. However, this currently requires a similar circuit, i.e. at least a cap and a diode to clamp the voltage after the cap. I find this inconvenient, unreliable, plus I am in constant fear of damaging the chips by not connecting the diode correctly.

Side story: I had some unreliable reset behavior, so I hooked up a scope to the reset pin just to find that my 100n cap was not big enough to reliably pull down the chips reset pin. Then I saw the voltage jump up close to 8.5V, and found that my diode misplaced...

How about changing the code in open to

serial_set_dtr_rts(&pgm->fd, 0); // Discharge the capacitor, if present
usleep(20*1000);
serial_set_dtr_rts(&pgm->fd, 1); // Pull the reset line low
usleep(20*1000);
serial_set_dtr_rts(&pgm->fd, 0); // Pull the reset line high
usleep(20*1000);

I think this would work for both the 'rts-capacitor-reset' boards, as well for a direct connection.

Any thoughts?

@mariusgreuel mariusgreuel added the enhancement New feature or request label Jan 3, 2023
@stefanrueger
Copy link
Collaborator

A more general method would be to have an option -r "myreset <options>" or some such that can be run through a system() call instead of the standard routine. The user can then rig up what they like, eg, a mechanical hoist for a brick that is dropped onto the reset pin (or a falling blocks chain reaction that eventually puts the board into reset and releases it). Affected programmers:

arduino.c
stk500.c
updi_link.c
urclock.c
wiring.c
xbee.c

@stefanrueger
Copy link
Collaborator

| my 100n cap was not big enough to reliably pull down

Some USB/serial boards (eg, my beloved USB-BUB-II) do not break out the signal itself, instead they insert a cap between the DTR pad and the FTDI FT232R chip, so when you connect to a uno board you get two 100 n caps in series halving capacity.

@mcuee
Copy link
Collaborator

mcuee commented Jan 5, 2023

I like this idea.

As mentioned in a few other places, I do not have good facility to test urclock/optiboot other than the Arduiuo Nano/Uno and Mega clones. For other boards I have to use manual reset. Sometimes I have to rebuild the FW with 8 seconds WDT timeout to carry out the test as I may have a slow hand.

@mcuee
Copy link
Collaborator

mcuee commented Jan 6, 2023

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.

@mcuee
Copy link
Collaborator

mcuee commented Jan 7, 2023

@stefanrueger and @mariusgreuel

There is actually an existing issue which is basically the same. I have closed #344 so that we can have single place for this discussion.

Maybe the first step is to support the following. I am thinking that an extension of the above programmers will be useful, say -xreset = option.

Affected programmers:

arduino.c
stk500.c (the original STK500v1 do not need extra reset option. Arduino as ISP also do not need extra reset option)
updi_link.c (I am not so familiar with this one)
urclock.c
wiring.c
xbee.c (I am not so familiar with this one)

Possible options:

-xreset=dtr
-xreset=cts
-xreset=rts
-xreset=manual

@mcuee
Copy link
Collaborator

mcuee commented Jan 7, 2023

From #344.

David Zanetti
Fri 09 May 2014 09:43:42 AM UTC

Currently two different programmer types (arduino and wiring) each individually implement RTS/DTS toggling for automatic reset into a bootloader on a target board.

I'd like this to be a generic option that could be applied to any serial-based programmer, either as a command-line option or programmer config feature.

It would be useful for bootloaders like xboot (
http://alexforencich.com/wiki/en/xboot/start) which implement avr109 as a protocol. Currently I've patched butterfly.c to do auto-reset, but it seems more sensible to make it a generic feature.

Thanks!

This issue was migrated from https://savannah.nongnu.org/bugs/?42324

@mariusgreuel mariusgreuel self-assigned this Jan 9, 2023
@mcuee mcuee changed the title Change Arduino auto-reset via RTS to allow direct RTS-reset connection Change Arduino auto-reset via DTR/RTS/CTS to allow direct reset connection Jan 15, 2023
@mcuee
Copy link
Collaborator

mcuee commented Feb 2, 2023

@stefanrueger

I think it is rather clear to use rts/dts/dtr to carry out the reset. @mariusgreuel has already the implementation for rts and it should be easy to extend the support to dts/dtr as aell.
mariusgreuel@35f1d33

Just wondering how it will work if we need to support "manual reset".

@mcuee
Copy link
Collaborator

mcuee commented Mar 4, 2023

Ping @mariusgreuel and @stefanrueger to see how to progress this improvement to avrdude.

It seems to be a good candidate to be included in future release of avrdude.

@stefanrueger
Copy link
Collaborator

stefanrueger commented Mar 4, 2023

Here is what I don't understand: Reset is active-low, ie pulling DTR/RTS low in direct connection to MCU reset, ie, running serial_set_dtr_rts(&pgm->fd, 0) will activate the MCU reset. The comment, though, says, set reset line high. If the code

      // Set reset line high to discharge the capacitor, if present
      serial_set_dtr_rts(&pgm->fd, 0);
      usleep(50*1000);
      // Pull the reset line low
      serial_set_dtr_rts(&pgm->fd, 1);
      usleep(50*1000);
      // Set the reset line back to high
      serial_set_dtr_rts(&pgm->fd, 0);
      usleep(50*1000);

works then it cannot be that this was a direct connection. I suspect (but don't know) that there is actually a cap in the line somewhere between RTS/DTR and the MCU's reset.

@mariusgreuel Can you double-check the resistance, please, between the actual pad of the FTDI (or equivalent) chip's RTS/DTR pin (directly at the IC, not at a solder pad on the board) and the MCU reset pin? I really don't get how the code above would work if that was a direct connection between the serial chip's signal and AVR reset, indeed. The comments (and expected behaviour) don't match up with the code and how I think this works.

@stefanrueger
Copy link
Collaborator

diode to clamp the voltage after the cap

That is good practice but will prevent HVPP programming. I've never put a clamp diode in my reset circuits and actually never had a problem with that. Also, I never put a 300 Ω or similar resistor between reset buttons and MCU reset, and that has worked OK in practice. For reference the reset circuits on my (and a lot of other!) AVR boards look like

@stefanrueger
Copy link
Collaborator

stefanrueger commented Mar 4, 2023

Slightly off-topic: @mariusgreuel Your 50 ms wait here has changed from a 250 ms wait

usleep(250*1000);

in the current AVRDUDE codebase. I commend that because this quarter-second wait is waaaay too much. I never saw the utility of that loooong sleep in arduino_open().

Until a couple of months ago, that is. If you reduce the 250 ms in arduino.c to 50 ms (even 5 ms), everything seems to work just fine. Everything? No, just a small, little use case with optiboot does not: running AVRDUDE (changing above sleep to 50 ms) twice in succession spells problems for the second run:

$ avrdude50ms -qqp m328p -D -c arduino -P /dev/ttyUSB0 -U flash:w:blink.hex:i && echo OK.1; \
  avrdude50ms -qqp m328p -D -c arduino -P /dev/ttyUSB0 -U flash:w:blink.hex:i && echo OK.2
OK.1
[5 s wait]
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
OK.2

Synchronisation problems that last 5 s.

Now if you sleep 200 ms between the two AVRDUDE calls then all is back to normal

$ avrdude50ms -qqp m328p -D -c arduino -P /dev/ttyUSB0 -U flash:w:blink.hex:i && echo OK.1; \
  sleep 0.2; \
  avrdude50ms -qqp m328p -D -c arduino -P /dev/ttyUSB0 -U flash:w:blink.hex:i && echo OK.2
OK.1
OK.2

No sync problems. Both programming sessions finish in under 1.5 seconds.

This effect is special to optiboot. Other bootloaders don't exhibit the need for a sleep between AVRDUDE runs .

I believe this is to do optiboots's ambition to preserve the reset causes in the MCUSR as much as possible. Now, I still haven't got my head completely around this optiboot-specific effect, but that's what I suspect that happens: the issue is that an external reset while the MCU is still in the bootloader will make optiboot not enter the bootloader but the application instead. The watchdog is still set and will trigger later in the application, upon which optiboot then decides to run the bootloader, by which time the (impatient) second AVRDUDE run will have sent its first handshake and tries to receive a character. Now the AVRDUDE timeout for reading a char is per default 5 s (see serial_recv_timeout). It can be

  • Longer than the bootloader WDT timeout: the bootloader times out (typical case with default 1 s WDTO)
  • Shorter than the bootloader WDT-timeout, and AVRDUDE synchronises and programs OK (but only after 5 s)

Three timings are relevant here:

  • The time optiboot hangs around when exiting (not all exit modes reduce WDT timeout)
  • The normal bootloader WDT timeout (typ 1-8 s)
  • serial_recv_timeout at the point of trying to synchronise

OK, this is all analysis by reading the code and trying not to get a headache while attempting to figure out what happens.

TLDR; this is why I have left the 250 ms wait in the arduino_open() routine, and why I reduced the urclock_open() wait to 20 ms and inserted a 200 ms wait in urclock.c's urclock_close() routine if optiboot was served

avrdude/src/urclock.c

Lines 2262 to 2263 in 4019edf

if(ur.bloptiversion) // Optiboot needs a pause between two successive avrdude calls
usleep(200*1000);

(It's OK to wait before AVRDUDE exits should it have served optiboot, but it's not OK to have every programming action delayed by 200 ms at the beginning and make all these avrdude -c urclock -xshowall calls appear sluggish 😁)

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

First thing I check is whether there is a regression with the Arduino Meag 2560 clone (using the on-board CH340). I will try out a FT232R USB to TTL adapter later.

It seems to be okay. I manually patched urclock.c on top of latest avrdude git. urboot hex file is from the latest urboot.hex repo.

PS C:\work\avr\avrdude_test\avrdude_issue1262> git diff
diff --git a/src/urclock.c b/src/urclock.c
index 1d613e6..b102292 100644
--- a/src/urclock.c
+++ b/src/urclock.c
@@ -2237,14 +2237,17 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) {
   if(serial_open(port, pinfo, &pgm->fd) == -1)
     return -1;

-  // Clear DTR and RTS to unload the RESET capacitor
+  // Set reset line high to discharge the capacitor, if present
   serial_set_dtr_rts(&pgm->fd, 0);
-  usleep(20*1000);              // 20 ms is ample for dis/charging the cap from reset to DTR/RTS
-  // Set DTR and RTS back to high
+  usleep(20*1000);
+  // Pull the reset line low
   serial_set_dtr_rts(&pgm->fd, 1);
+  usleep(20 * 1000);
+  // Set the reset line back to high
+  serial_set_dtr_rts(&pgm->fd, 0);

-  if((120+ur.delay) > 0)
-    usleep((120+ur.delay)*1000); // Wait until board comes out of reset
+  if((100+ur.delay) > 0)
+    usleep((100+ur.delay)*1000); // Wait until board comes out of reset

   pmsg_debug("%4ld ms: enter urclock_getsync()\n", avr_mstimestamp());
   if(urclock_getsync(pgm) < 0)
@@ -2256,7 +2259,6 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) {


 static void urclock_close(PROGRAMMER *pgm) {
-  serial_set_dtr_rts(&pgm->fd, 0);
   serial_close(&pgm->fd);
   pgm->fd.ifd = -1;
   if(ur.bloptiversion)          // Optiboot needs a pause between two successive avrdude calls

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c avrisp2 -p m2560 
-U .\urboot_mega-r3_16mhz_115200bps_uart0_rxe0_txe1_ee_led+b7_fr_ce_ur.hex -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM5
 -p m2560 -xshowall

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 1024 u7.7 
weu-hpr-c vector 0 (RESET) ATmega2560

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM5 -p m2560
 -U .\hex\blink-mega2560_lext-test.hex

avrdude_issue_1262: AVR device initialized and ready to accept instructions
avrdude_issue_1262: device signature = 0x1e9801 (probably m2560)
avrdude_issue_1262: Note: flash memory has been specified, an erase cycle will be performed.
                    To disable this feature, specify the -D option.
avrdude_issue_1262: erasing chip
avrdude_issue_1262: reading input file .\hex\blink-mega2560_lext-test.hex for flash
                    with 1346 bytes in 4 sections within [0, 0x3106d]
                    using 7 pages and 446 pad bytes
avrdude_issue_1262: preparing flash input for device bootloader
avrdude_issue_1262: writing 1346 bytes flash ...

Writing | ################################################## | 100% 0.17 s

avrdude_issue_1262: 1346 bytes of flash written
avrdude_issue_1262: verifying flash memory against .\hex\blink-mega2560_lext-test.hex

Reading | ################################################## | 100% 0.12 s

avrdude_issue_1262: 1346 bytes of flash verified

avrdude_issue_1262 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM5 -p m2560
 -xshowall

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 2022-07-06 18.41 blink-mega2560_lext-test.hex 200814 store 60262 meta 44 
boot 1024 u7.7 weu-hpr-c vector 0 (RESET) ATmega2560

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

Somehow I can not get FT232R to work with the patch and urboot UART1 FW. I also tried UART2 and UART3 version.

I can get it working after making the connection more secure.
https://github.com/stefanrueger/urboot.hex/tree/main/boards/mega-r3/fcpu_16mhz/115200_bps
Note: I need to disconnect the Reset pin from FT232RL in order for the AVRISPmkii to be able to program the bootloader.

Connection scheme:
https://content.arduino.cc/assets/Pinout-Mega2560rev3_latest.pdf

FT232RL USB to TTL -- Arduino mega2560 clone

GND -- GND
DTR -- Reset (no capacitor)
RXD -- TX1 (D3, UART1)
TXD  -- RX1 (D2, UART1)

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c avrisp2 -p m2560
 -U .\urboot_mega-r3_16mhz_115200bps_uart2_rxh0_txh1_ee_led+b7_fr_ce_ur.hex -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7
 -p m2560 -xshowall

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 1024 u7.7 
weu-hpr-c vector 0 (RESET) ATmega2560

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7
 -p m2560 -U .\hex\blink-mega2560_lext-test.hex

avrdude_issue_1262: AVR device initialized and ready to accept instructions
avrdude_issue_1262: device signature = 0x1e9801 (probably m2560)
avrdude_issue_1262: Note: flash memory has been specified, an erase cycle will be performed.
                    To disable this feature, specify the -D option.
avrdude_issue_1262: erasing chip
avrdude_issue_1262: reading input file .\hex\blink-mega2560_lext-test.hex for flash
                    with 1346 bytes in 4 sections within [0, 0x3106d]
                    using 7 pages and 446 pad bytes
avrdude_issue_1262: preparing flash input for device bootloader
avrdude_issue_1262: writing 1346 bytes flash ...

Writing | ################################################## | 100% 0.16 s

avrdude_issue_1262: 1346 bytes of flash written
avrdude_issue_1262: verifying flash memory against .\hex\blink-mega2560_lext-test.hex

Reading | ################################################## | 100% 0.12 s

avrdude_issue_1262: 1346 bytes of flash verified

avrdude_issue_1262 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7 -p m2560 -xshowall

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 2022-07-06 18.41 blink-mega2560_lext-test.hex 200814 store 60262 
meta 44 boot 1024 u7.7 weu-hpr-c vector 0 (RESET) ATmega2560

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

Same for UART3.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c avrisp2 -p m2560
 -U .\urboot_mega-r3_16mhz_115200bps_uart3_rxj0_txj1_ee_led+b7_fr_ce_ur.hex -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7
 -p m2560 -xshowall

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 1024 u7.7 
weu-hpr-c vector 0 (RESET) ATmega2560

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7 
-p m2560 -U .\hex\blink-mega2560_lext-test.hex

avrdude_issue_1262: AVR device initialized and ready to accept instructions
avrdude_issue_1262: device signature = 0x1e9801 (probably m2560)
avrdude_issue_1262: Note: flash memory has been specified, an erase cycle will be performed.
                    To disable this feature, specify the -D option.
avrdude_issue_1262: erasing chip
avrdude_issue_1262: reading input file .\hex\blink-mega2560_lext-test.hex for flash
                    with 1346 bytes in 4 sections within [0, 0x3106d]
                    using 7 pages and 446 pad bytes
avrdude_issue_1262: preparing flash input for device bootloader
avrdude_issue_1262: writing 1346 bytes flash ...

Writing | ################################################## | 100% 0.16 s

avrdude_issue_1262: 1346 bytes of flash written
avrdude_issue_1262: verifying flash memory against .\hex\blink-mega2560_lext-test.hex

Reading | ################################################## | 100% 0.12 s

avrdude_issue_1262: 1346 bytes of flash verified

avrdude_issue_1262 done.  Thank you.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7
 -p m2560 -xshowall

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 2022-07-06 18.41 blink-mega2560_lext-test.hex 200814 store 60262 meta 44 
boot 1024 u7.7 weu-hpr-c vector 0 (RESET) ATmega2560

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

Same for UART1.

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c avrisp2 -p m2560
 -U .\urboot_mega-r3_16mhz_115200bps_uart1_rxd2_txd3_ee_led+b7_fr_ce_ur.hex -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7
 -p m2560 -xshowall

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 0000-00-00 00.00  application 0 store 0 meta 0 boot 1024 u7.7
 weu-hpr-c vector 0 (RESET) ATmega2560

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7
 -p m2560 -U .\hex\blink-mega2560_lext-test.hex -qq && echo OK
OK

PS C:\work\avr\avrdude_test\avrdude_bin> .\avrdude_issue_1262 -c urclock -P COM7
 -p m2560 -xshowall -q

avrdude_issue_1262: AVR device initialized and ready to accept instructions
0000ffffffff 2022-07-06 18.41 blink-mega2560_lext-test.hex 200814 store 60262 
meta 44 boot 1024 u7.7 weu-hpr-c vector 0 (RESET) ATmega2560

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

BTW, it also helps to talk to the urboot bootloader for ATTiny13A (the flash writing issue is not with the patch but seems to be with the bootloader)
stefanrueger/urboot#19 (comment)

@stefanrueger
Copy link
Collaborator

@mcuee @mariusgreuel I have no doubt that the suggested modification works with typical reset circuits. I don't see how it can work with a direct connection.

DTR -- Reset (no capacitor)

Are you sure? Have you measured resistance directly from the AT2560 reset IC pin (not board reset header) to the FT232R DTR IC IC pin of the FT232R USB to TTL adapter (not the adapter board DTR header)? There might be an inline cap on the USB to TTL adapter.

The suggested code

      serial_set_dtr_rts(&pgm->fd, 0);
      usleep(50*1000);
      serial_set_dtr_rts(&pgm->fd, 1);
      usleep(50*1000);
      serial_set_dtr_rts(&pgm->fd, 0);
      usleep(50*1000);

will reset the board (almost) all the time if there was a direct connection from FT232R DTR to ATmega2560 reset. The last command above pulls DTR low at the end of open(). That is OK if isolated by a cap. But in a direct connection this puts the board in constant reset (it's low-active!)

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

I am pretty sure there is a direct short for my ATmega2560/ATTiny13A test. But I will check with a proper multimeter next week (say tomorrow or a bit later).

@mariusgreuel
Copy link
Contributor Author

Just to be on the same page, the code I proposed assumes a negative-logic USB to TTL serial adapter, high-level for RTS idle, and of course low-level to reset the AVR.

With a direct connection from RTS to /RESET, the idea is to start out with a high-level, and then briefly apply a low-level pulse.

When we have an Arduino Uno style circuitry with a 100n cap between the RTS output and RESET input and a pull-up on the RESET pin, I figured it makes sense to pull the RTS line high first to discharge the cap, just in case the RTS line was left at low-level state by some other tool.

I agree that the comments are not quite correct for the series cap case, as we set the state of the RTS line, not the reset line. So instead of 'Set reset', 'Set RTS/DTR' is better.

I think I tested the code with a direct connection to an ATtiny85 flashed with urboot, and with an Arduino Uno Rev3 as well. I never actually checked the reset level on the Arduino, I just assumed the 16U2 was a drop-in replacement for the FTDI chip they used before. Otherwise, they could have just dropped the cap (RANT: which would have made debugging so much easier - or even better, implement a composite USB device with a EDBG port and a serial port).

Is this better? (don't mind the 50ms):

  // The code assumes a negative-logic of the USB to TTL serial adapter, idle-high, low to reset
  // Set RTS/DTR high to discharge the series-capacitor, if present
  serial_set_dtr_rts(&pgm->fd, 0);
  usleep(50*1000);
  // Pull the RTS/DTR line low
  serial_set_dtr_rts(&pgm->fd, 1);
  usleep(50*1000);
  // Set the RTS/DTR line back to high
  serial_set_dtr_rts(&pgm->fd, 0);
  usleep(50*1000);

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

Just to be on the same page, the code I proposed assumes a negative-logic USB to TTL serial adapter, high-level for RTS idle, and of course low-level to reset the AVR.

Ah, I see, that will clear the confusions. And indeed FT232R is a negative logic USB to TTL serial adapter.
https://www.ftdichip.com/old2020/Support/Documents/DataSheets/ICs/DS_FT232R.pdf

DTR#, RTS#, CTS#, RI#, DSR#, DCD# mentioned in the datasheets are all ACTIVE LOW signal.

Same for CH340 series.
http://www.wch-ic.com/products/CH340.html

Same for CP2102.
https://www.silabs.com/documents/public/data-sheets/CP2102-9.pdf

I think all the popular USB to TTL chip will follow this convention (Active LOW).

In that case, I think the following comments are good.

  // The code assumes a negative-logic of the USB to TTL serial adapter, idle-high, low to reset
  // Set RTS/DTR high to discharge the series-capacitor, if present
  serial_set_dtr_rts(&pgm->fd, 0);
  usleep(50*1000);
  // Pull the RTS/DTR line low
  serial_set_dtr_rts(&pgm->fd, 1);
  usleep(50*1000);
  // Set the RTS/DTR line back to high
  serial_set_dtr_rts(&pgm->fd, 0);
  usleep(50*1000);

I have deleted my old comments to avoid confusions for others.

@mcuee
Copy link
Collaborator

mcuee commented Mar 5, 2023

@mariusgreuel

Then the question is what will be a reliable way to reset the chip after programming. I see you have remove the following line from urclock_close() function and move it up to urclock_open.

serial_set_dtr_rts(&pgm->fd, 0);

@stefanrueger
Copy link
Collaborator

stefanrueger commented Mar 5, 2023

assumes a negative-logic USB to TTL serial adapter

[edit: you are right: negative logic - that explains my confusion]

I have an USB BUB II with an FT232R on it and measured the RTS signal (on a lone solder pad that is directly connected to the chip): it's Vcc 0 V after serial_set_dtr_rts(&pgm->fd, 1) and 0 V Vcc after serial_set_dtr_rts(&pgm->fd, 0). That's why I don't think the code would work with that setup. That explains my confusion... Don't know whether the IC's DTR/RTS signal is high-impedance or low-impedance, though, but assume low-impedance. I expect the AVRs to have in internal pullup to Vcc on /Reset, certainly the ATmega328P does.

The DTR line has a cap between the IC pin and board as seen in the schematic below (C4). That's what I normally use to program with avrdude -c urclock.

usb-bub-ii-schematic

@stefanrueger
Copy link
Collaborator

Oooops. Measured again and more carefully. You are right @mariusgreuel @mcuee. low-active

So @mariusgreuel's patch will work with direct connection. Only change I'd do is to leave the 250 ms wait in arduino.c (for the reasons explained above). Do you want to do a PR, @mariusgreuel

@stefanrueger
Copy link
Collaborator

@mariusgreuel Your new comments in the code are much better (though I don't know what idle-high means).

When we have an Arduino Uno style circuitry with a 100n cap between the RTS output and RESET input and a pull-up on the RESET pin, I figured it makes sense to pull the RTS line high first to discharge the cap, just in case the RTS line was left at low-level state by some other tool.

True. The discharge time is vvv small assuming the DTR/RTS signal has low-impedance. 20 ms should be more than ample.

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

Successfully merging a pull request may close this issue.

3 participants