Disabling auto reset on the Arduino Due

jumper

Autoreset disable jumper
(modified 16u2 firmware)

This post is about a simple modification to the firmware of the atmega16u2 on the Arduino Due board, that makes it possible to disable auto reset on the Due’s programming USB port.

Edit: as Topaz replied, there is a much easier way to disable auto reset: put a 1K resistor between reset and 3V3. Nevertheless the firmware mod described here has the convenience that it disables auto reset while auto upload still works. –  And it is good fun too!

I found this feature was best introduced via a small tour of observations about auto reset on various Arduino types.

Auto reset on classic Arduinos.

On classic Arduinos, the nDTR output pin of the USB to serial converter is connected to the AVR’s nRESET pin. If you start avrdude to upload a sketch, the serial line is opened and the operating system normally brings nDTR low. This is because with a classic modem, nDTR (Data Terminal Ready) indicates to the modem that the “terminal” (the PC) is ready to  for communication. So connecting nDTR to nRESET automatically resets the AVR.

There is a serial capacitor between nDTR and nRESET that starts charging up (through nRESET’s 10K pullup resistor) from the moment nDTR goes low, thus providing for a short reset pulse.

Further there is a diode from nRESET to 5V. This is because when nDTR goes back high, there is momentarily 10V on nRESET. Absence of such a diode was reported to cause unintentional high voltage programming on the AVR.

Sometimes the RTS signal is used instead of DTR.

Most Arduino’s have a trace that can be cut to disable auto reset. On my Duemilanove I soldered a jumper across the trace so I can easily close the trace again if I want auto reset.

Another method mentioned often in the fora is to place a 20uF cap between nRESET and ground that prevents nRESET from being pulled low. See here.

Why disabling auto reset?

The side effect of auto reset is that if you you open the serial port just to see the output of your program, the processor is reset as well. In many (if not most) situations, this is not what you want. However, it looks like over time, Arduino users started considering this behavior as normal and even desired. This is because if the processor is reset and thus the sketch is restarted, the messages sent to the serial line in the beginning of the sketch will nicely show up in your terminal program.

A related problem with auto reset is that when software on your PC opens the serial port and sends data to it, the Arduino resets, its bootloader starts running and it will consume the first bytes sent by the PC…

The Leonardo’s USB port.

The Leonardo has a different behaviour. It does not auto reset if you open the serial port. When the IDE wants to upload a sketch, it has to indicate this intent by “touching” the port at the magic baud rate of 1200bps. Only then auto reset will happen. I find this behaviour more useful. But you lose the feature of catching early println’s in your terminal program. No big deal to me, but apparently it was important enough to for the developers come up with the

while (!Serial)
    ;

idiom. The idea is this: since the sketch is not restarted when the port is opened, we let the sketch wait until the port is opened.

If you have a look at how the boolean operator for class Serial is implemented you’ll see that it returns true when DTR or RTS are asserted i.e. when the port is “open”.

The Due’s native USB port.

The Due’s native USB port works much like the Leonardo’s. So if you want to avoid auto reset on the Due, the simplest way is to use this port. Use SerialUSB instead of Serial in your sketch.

The Due’s programming USB port.

The Due’s programming USB port is a real uart on the sam, connected to an uart on the atmegu16u2 which serves as serial to USB converter. To be able to flash a new sketch into the sam,  the 16u2 must perform a special sequence: it must first pulse high the sam’s erase line, then pulse low nRESET. Of coarse this is not done whenever the serial port is opened: this would erase the flash upon every opening of the serial port! So this erase+reset sequence is only done after the ide has indicated its intent to upload a sketch by opening the port at 1200 bps.

But what happens if you open the serial port at another baudrate than 1200 bps? The erase line is not touched, but what about the reset line?  Well, in this case the sam gets reset too! Clearly the designers opted to be consistent with the behaviour of the Uno, not that of the Leonardo.

Seen the similarity with the Uno, I tried disabling auto reset by installing a 20uF capacitor between the nRESET of the Due and ground. That does not work. Reason is that the Due has no 10nF capacitor between the 16u2’s output and the sam’s nRESET. Therefore, nRESET is pulled low much longer: 200msec. This is enough to drain the capacitor and reset happens.

By the way, there is no buffer between the 16u2’s output pin and the sam’s nRESET. This looks odd because it could damage the Due. Here, it does not hurt because the 16u2’s firmware never drives the pin high, it either pulls it low to reset the sam or configures it as input (high impedance) otherwise. In the latter case, the sam internally pulls up nRESET (to 3V3).

I find the use of a big capacitor to disable auto reset not a proper solution anyway. A jumper would be better. But there is no trace you can cut to disable autoreset like on the Uno.

So I decided to solder jumpers to the four free gpio’s of the 16u2 that are broken out. I modified the firmware such that it only carries out auto reset when a jumper bridge is in place between PB5 and PB7.due_16u2_gpio

See my previous post for where to find the code for the 16u2 firmware.

In Arduino-usbserial.c:

#define JUMPER_SENSE 5
#define JUMPER_GND 7
#define JUMPER_DEBUG 4

JUMPER_GND (PB7) is driven low and JUMPER_SENSE (PB5) senses whether it is jumpered (pulled low) to the first one. This is set up in SetupHardware():

...
/* Jumper pins */
PORTB |=  (1<<JUMPER_SENSE); // pull-up
DDRB  &= ~(1<<JUMPER_SENSE); // input
PORTB &= ~(1<<JUMPER_GND);   // low
DDRB  |=  (1<<JUMPER_GND);   // output

When the PC opens the port, this causes EVENT_CDC_Device_ControLineStateChanged() to get called. Lines in bold were add:

void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
    ...
    if (Selected1200BPS) {
        /* Start Erase / Reset procedure when receiving the magic "1200" baudrate */
        ResetTimer = 120;
    } else if (!PreviousDTRState && CurrentDTRState) {
        /* Reset on rising edge of DTR
           but only if jumper is NOT in place */
        if (PINB & (1 << JUMPER_SENSE))
            ResetTimer = 30;
    }
}

So, if the line state changes (port opened or closed) at 1200 bps, the ResetTimer is set to 120. The main loop of the firmware will start counting down ResetTimer from 120 to zero, executing the erase+reset sequence in this process.

When opened at another baud rate, the ResetTimer will set to 30. As a consequence the main loop will only execute the last part of the sequence, which is the reset part. The firmware modification makes sure the reset part is only armed if the jumper is NOT in place.

The nice thing is that even with auto reset disabled, uploading sketches still works automatically! This is because when uploading, the magic 1200 bps baud rate is used which still arms the erase+reset sequence!

8 thoughts on “Disabling auto reset on the Arduino Due

  1. Topaz

    Hi
    First, thanks for the hard work here, very appreciated. Just wanted to add that the MASTER-RESET is available as a aduino shield pin and thus can be connected to the 3v3 using a resistor using these pins.
    Have fun,
    Topaz

    Reply
    1. petervho Post author

      You are absolutely right and that is the simplest and most logic way to avoid auto reset. I must admit that I overlooked this possibility, a bit mislead by the many variations there have been in the auto reset mechanism and schematic. With the Due it now is remarkably easy.

      There is a 10K series resitor between the 16u2’s output and the MASTER-RESET so it is no problem pulling it up while the 16u2 drives it low. A resistor between 3V3 and the reset pin is still desirable to avoid a short when accidentally pushing the reset button, right? I tried with a 1K resistor, which works well.

      For a moment I thought to remove this post alltogether. But the approach with the modified 16u2 still has an advantage: it disables autoreset but you still can auto upload sketches. I find it convenient. And besides it is good fun playing with the 16u2 firmware. I will put a big edit though in the beginning of the post…

      Thanks!

      Reply
  2. Ruben

    Hello Peter,

    In your post you mention the object SerialUsb to use the native usb port of the due. I saw this object also mentioned on the page of the arduino site itself (http://arduino.cc/en/Reference/Serial), however I fail to find any information on this object.
    Do I need a library to use the object or is it available by default? Where do I find which methods I can call on this object?

    Thanks for your feed-back.
    (I tried registering on the arduino forum, but I fail to recieve an email regarding my registration.)

    Best regards,
    Ruben

    Reply
    1. petervho Post author

      It is always available and you can use it just like you would use Serial.

      You may want to have a look below the directory ARDUINO_INSTALLDIR/hardware/arduino/sam/cores/arduino to see how the class hierarchy is built up. See classes Print, Stream, HardwareSerial, UARTClass, and Serial_

      Reply
  3. Gerard

    Hello Peter,

    do you have a compiled version of the 16u2 firmware with the reset disable function?

    Kind regards

    Reply
    1. Esaac

      Hello Gerard,

      Were you able to modify and compile the atmega16u2 firmware as in the steps above? I have the source files and have made the changes, but run into a lot of errors when trying to compile. Just wondering what your success/experience was like.

      Best

      Reply
  4. Pingback: Pi Zero W resets Arduino Due during power up ~ Raspberry Pi ~ TroubleToday.net

Leave a comment