[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avrdude-dev] [bug #56584] Arduino double reset before programming (TIOC

From: spike
Subject: [avrdude-dev] [bug #56584] Arduino double reset before programming (TIOCM_DTR clear/set swapped)
Date: Sat, 6 Jul 2019 23:01:18 -0400 (EDT)
User-agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0


                 Summary: Arduino double reset before programming (TIOCM_DTR
clear/set swapped)
                 Project: AVR Downloader/UploaDEr
            Submitted by: spike
            Submitted on: Sun 07 Jul 2019 03:01:17 AM UTC
                Category: None
                Severity: 3 - Normal
                Priority: 5 - Normal
              Item Group: None
                  Status: None
                 Privacy: Public
             Assigned to: None
         Originator Name: spike
        Originator Email: 
             Open/Closed: Open
                 Release: SVN snapshot
         Discussion Lock: Any
     Programmer hardware: 
             Device type: arduino



Whenever I'm using the Arduino programmer (i.e. -carduino) the device to be
programmed is reset twice, roughly within 250ms before the DTR pin is actually
pulled low and data is pushed out the usb port. I've made some screenshots to
illustrate the point:

On Linux:
On Windows 7:

Looking at the source code (arduino.c) there's a comment referring to
unloading the RESET capacitor (which e.g. on the Arduino UNO R3 would be C5),
which would generate a falling edge on the RESET pin and therefore resetting
the microcontroller so the bootloader can do its thing:

  /* Clear DTR and RTS to unload the RESET capacitor 
   * (for example in Arduino) */
  serial_set_dtr_rts(&pgm->fd, 0);
  /* Set DTR and RTS back to high */
  serial_set_dtr_rts(&pgm->fd, 1);

Unfortunately, the code seems to do the opposite, i.e. setting DTR high
instead of low. If one looks into 'ser_posix.c' for example, the relevant
function is 'ser_set_dtr_rts'. Depending on the value of 'is_on' it sets or
clears the TIOCM_DTR and TIOCM_RTS bits:

  if (is_on) {
    /* Set DTR and RTS */
    ctl |= (TIOCM_DTR | TIOCM_RTS);
  else {
    /* Clear DTR and RTS */
    ctl &= ~(TIOCM_DTR | TIOCM_RTS);

This seems to be the wrong way around: DTR (and RTS) are active low as far as
I know, so setting the TIOCM_DTR bit actually pulls the output low. And it
seems to be the reason why the DTR pin is high for roughly 250ms. I would have
expected it to be low for about 250ms to unload the capacitor and generate the
reset edge, as was probably intended by the author/commenter of the code
I've swapped it around

  serial_set_dtr_rts(&pgm->fd, 1);
  /* Set DTR and RTS back to high */
  serial_set_dtr_rts(&pgm->fd, 0);

and now the DTR pin seems to behave properly:

On Linux after patch:
On Windows 7 after patch:

I've tested a couple of devices (m1284p, m32, m328p, t13) and avrdude still
works as expected. Why there are two reset pulses in the first place when
clearing TIOCM_DTR while it's idling high is beyond me. It seems pure
coincidence to me but then again I know very little about the I/O subsystem.
The double reset is not actually a big deal. It seems to work just fine for a
lot of people after all. There seem to be some rare intermittent timeouts on
'regular' Arduinos (pro mini, don't recall exactly) on Windows which might be
just timing related.
But there are a few oddball systems that implement the Arduino 'auto-reset'
circuit, i.e. a series capacitor and a diode across the reset pullup resistor,
but use RTS instead of DTR. That works fine on Linux (it actually generates
the exact same two resets) but fails on Windows. Apparently since there's a
quirk in Windows's usbser.sys which doesn't generate an edge when the pin is
already high on RTS (but does so on DTR). Also: Two resets are just not


Reply to this item at:


  Message sent via Savannah

reply via email to

[Prev in Thread] Current Thread [Next in Thread]