bugAVR Downloader/UploaDEr - Bugs: bug #56584, Arduino double reset before...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

bug #56584: Arduino double reset before programming (TIOCM_DTR clear/set swapped)

Submitter:  spike <spike>
Submitted:  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
Open/Closed:  Open Release:  SVN snapshot
Programmer hardware:  Device type:  arduino

Tue 03 Dec 2019 07:16:02 PM UTC, comment #2: 

Hello.  The existing code in AVRDUDE is correct.  We need to set DTR to 0 for some time to ensure that the the DTR pin is high and that the capacitor discharges.  (Both sides of the capacitor will be high after it discharges.)  Then we need to set DTR to 1, which causes a falling edge on the DTR pin, which sends a low  pulse to the AVR's reset line.  The reset line gradually rises back to a high level as the capacitor charges.

This code is probably redundant on some operating systems, like macOS, where DTR line automatically gets set high when you connect to a serial port.  But it's needed on Windows with usbser.sys, and in general.

David Grayson <davidegrayson>
Sun 07 Jul 2019 08:07:14 PM UTC, comment #1: 

Pretty much the same patch was already submitted (along with a really nice explanation) back in 2011: https://savannah.nongnu.org/patch/download.php?file_id=23541

Discussion here: https://savannah.nongnu.org/patch/?7559

This should also fix https://savannah.nongnu.org/patch/?9004 which I vaguely recall hitting at some point myself:

original submission:

> There seem to be some rare intermittent timeouts on 'regular' Arduinos (pro mini, don't recall exactly) on Windows

spike <spike>
Sun 07 Jul 2019 03:01:17 AM UTC, original submission:  

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: https://gist.githubusercontent.com/spike77453/891a1131232420a0937964cc944c3b49/raw/c2c84f56ce8b2f0c35fafec6e495f1216250ae23/DTR_Linux.png
On Windows 7: https://gist.githubusercontent.com/spike77453/891a1131232420a0937964cc944c3b49/raw/c2c84f56ce8b2f0c35fafec6e495f1216250ae23/DTR_Win7.png

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);
  usleep(250*1000);
  /* Set DTR and RTS back to high */
  serial_set_dtr_rts(&pgm->fd, 1);
  usleep(50*1000);

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 above.
I've swapped it around (https://gist.githubusercontent.com/spike77453/891a1131232420a0937964cc944c3b49/raw/c2c84f56ce8b2f0c35fafec6e495f1216250ae23/AVRDude_ClearDTR.patch):

  serial_set_dtr_rts(&pgm->fd, 1);
  usleep(250*1000);
  /* 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: https://gist.githubusercontent.com/spike77453/891a1131232420a0937964cc944c3b49/raw/c2c84f56ce8b2f0c35fafec6e495f1216250ae23/DTR_PatchedAVRDude_Linux.png
On Windows 7 after patch: https://gist.githubusercontent.com/spike77453/891a1131232420a0937964cc944c3b49/raw/c2c84f56ce8b2f0c35fafec6e495f1216250ae23/DTR_PatchedAVRDude_Win7.png

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 necessary

spike <spike>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by davidegrayson (Posted a comment)
  • -email is unavailable- added by spike (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

     

    No changes have been made to this item

    Back to the top

    Powered by Savane 3.13-3230.
    Corresponding source code