From aa2f45111b2aa833fa88e5b185cced5917fbd982 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 28 Sep 2023 00:04:06 +0100 Subject: [PATCH] Reduce DTR/RTS-low time for reset generation to 100 us Standard AVR reset circuits deploy a connection from the DTR/RTS line of a USB-to-serial chip to the AVR via a small capacitor, see https://onlinedocs.microchip.com/pr/GUID-F626284A-58F0-4C25-A6F3-0EA5054F3E2B-en-US-6/index.html?GUID-B80B25FF-E9D7-4766-B562-DA197B8B938C Setting DTR/RTS low once will issue a reset. Setting this signal high again after a short time ensures that a direct connection DTR/RTS to reset also works. The duration of pulling DTR/RTS low must be relatively short, say RC/10, in order to avoid a reset spike above Vcc. If Vcc exceeds 5.5 V then a full 2 Vcc reset spike can potentially trigger HV programming. See also - https://github.com/avrdudes/avrdude/pull/1504#issuecomment-1735295710 - https://github.com/avrdudes/avrdude/pull/1505#issuecomment-1738053365 --- src/arduino.c | 8 +++++--- src/avrdude.1 | 4 ++-- src/doc/avrdude.texi | 4 ++-- src/stk500.c | 6 ++++-- src/urclock.c | 9 +++++---- src/wiring.c | 7 ++++--- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/arduino.c b/src/arduino.c index 3ca83615..7c705da2 100644 --- a/src/arduino.c +++ b/src/arduino.c @@ -97,10 +97,12 @@ static int arduino_open(PROGRAMMER *pgm, const char *port) { usleep(250 * 1000); // Pull the RTS/DTR line low to reset AVR serial_set_dtr_rts(&pgm->fd, 1); - usleep(50 * 1000); - // Set the RTS/DTR line back to high + // 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); - usleep(50 * 1000); + + usleep(100 * 1000); /* * drain any extraneous input diff --git a/src/avrdude.1 b/src/avrdude.1 index ac6369ab..f1e35291 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -1666,7 +1666,7 @@ query on flash prepared with -xnometadata yields useful results. .It Ar delay= Add a ms delay after reset. This can be useful if a board takes a particularly long time to exit from external reset. can be negative, -in which case the default 100 ms delay after issuing reset will be +in which case the default 120 ms delay after issuing reset will be shortened accordingly. .It Ar strict Urclock has a faster, but slightly different strategy than -c arduino to @@ -1795,7 +1795,7 @@ is greater than 0. Add a milliseconds delay after resetting the part through toggling the DTR/RTS lines. This can be useful if a board takes a particularly long time to exit from external reset. can be negative, in which case the -default 80 ms delay after issuing reset will be shortened accordingly. +default 100 ms delay after issuing reset will be shortened accordingly. .It Ar help Show help menu and exit. .El diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index a22ae0d9..f71598ba 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1304,7 +1304,7 @@ yields useful results. @item @samp{delay=} Add a ms delay after reset. This can be useful if a board takes a particularly long time to exit from external reset. can be negative, -in which case the default 100 ms delay after issuing reset will be +in which case the default 120 ms delay after issuing reset will be shortened accordingly. @item @samp{strict} Urclock has a faster, but slightly different strategy than -c arduino to @@ -1447,7 +1447,7 @@ No toggling of DTR/RTS is performed if @var{snooze} > 0. @item @samp{delay=} Add a milliseconds delay after reset. This can be useful if a board takes a particularly long time to exit from external reset. can be -negative, in which case the default 80 ms delay after issuing reset will +negative, in which case the default 100 ms delay after issuing reset will be shortened accordingly. @item @samp{help} Show help menu and exit. diff --git a/src/stk500.c b/src/stk500.c index 2c35ac2f..46678a8a 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -112,9 +112,11 @@ int stk500_getsync(const PROGRAMMER *pgm) { // This code assumes a negative-logic USB to TTL serial adapter // Pull the RTS/DTR line low to reset AVR: it is still high from open()/last attempt serial_set_dtr_rts(&pgm->fd, 1); - usleep(20*1000); - // Set the RTS/DTR line back to high + // 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); + usleep(20*1000); stk500_drain(pgm, 0); } diff --git a/src/urclock.c b/src/urclock.c index ed919a07..c65e01e7 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -2220,12 +2220,13 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) { usleep(20*1000); // Pull the RTS/DTR line low to reset AVR serial_set_dtr_rts(&pgm->fd, 1); - usleep(20*1000); - // Set the RTS/DTR line back to high + // 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((100+ur.delay) > 0) - usleep((100+ur.delay)*1000); // Wait until board comes out of reset + if((120+ur.delay) > 0) + usleep((120+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) diff --git a/src/wiring.c b/src/wiring.c index 8ee3f3ac..61cd9f37 100644 --- a/src/wiring.c +++ b/src/wiring.c @@ -146,14 +146,15 @@ static int wiring_open(PROGRAMMER *pgm, const char *port) { // Pull the RTS/DTR line low to reset AVR pmsg_notice2("wiring_open(): asserting DTR/RTS\n"); serial_set_dtr_rts(&pgm->fd, 1); - usleep(20*1000); + // 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); int delay = WIRINGPDATA(pgm)->delay; - if((80+delay) > 0) - usleep((80+delay)*1000); // Wait until board comes out of reset + if((100+delay) > 0) + usleep((100+delay)*1000); // Wait until board comes out of reset } // Drain any extraneous input