Arduino software reset

mdiaconescu's picture

Choosing a MCU with a small amount of RAM (e.g., the ATmega328p MCU has only 2KB RAM), and programming it by using dynamic memory allocation (e.g., by using malloc) may cause memory fragmentation having as side effect strange MCU behavior. In such cases, observing the "real free" amount of RAM and rebooting the device whenever a dangerously low level is detected may be the only (or the simplest) solution for having the project running for a long amount of time.

We present three currently available and simple methods which allows to programmatically reset an Arduino.

Watchdog reset - the recommended method

Whenever possible, this is the method one should use. Not only that was designed and implemented by the chip manufacturer, but also produces a clean reset, with the same results as when you freshly power the Arduino (or the custom Arduino-brained project board). Think on a watchdog as on a kind of guardian for the micro-controller, able to power it off then back on. Once a watchdog was started, the program must emit signals (also named reset signals) within specified time slots, and in the absence of the correct signal, it simply produces a reset. The specific time periods are called prescallers and are normally defined as constants. For Atmel MCUs found in the Arduino boards, the following prescaller constants were defined: WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, WDTO_4S, and WDTO_8S. Their names are suggestive, indicating possible time slots between 15 milliseconds and 8 seconds.

The following code shows how to use the watchdog to reset the Arduino on-demand:

#include <avr/wdt.h>

void softwareReset( uint8_t prescaller) {
  // start watchdog with the provided prescaller
  wdt_enable( prescaller);
  // wait for the prescaller time to expire
  // without sending the reset signal by using
  // the wdt_reset() method
  while(1) {}
}

void setup() { // add setup code here...}

void loop() {
  // ... various code...

  // restart in 60 milliseconds
  softwareReset( WDTO_60MS);
}

We have discussed about how use a watchdog for auto-reset purposes, but it has many other use cases, such as waking-up the MCU from power-down states or debugging.

Program restart - the unclean method

This method does not really perform a MCU reboot, but rather a program restart. The obvious negative effect is that the MCU hardware states remains mostly unchanged. This includes the pin modes, their current HIGH or LOW states and so on. The following code shows how to implement the softwareReset method by using assembly language and executing a jump to the address where the program starts:

void softwareReset( unsigned long delayMillis) {
  uint32_t resetTime = millis() + delayMillis;
  while ( resetTime > millis()) { 
    /* wait and do nothing until the required delay expires... */
  }
  // jump to the start of the program
  asm volatile ( "jmp 0");  
}

Enforce hardware reset - the hacker's method

This method requires to connect one of the digital pins (e.g., digital pin 7) to the reset pin of the Arduino via a 1kOhm or 2.2kOhm resistor. Then set the digital pin as OUTPUT and keep it HIGH as long as no reboot/reset is required. Once a reboot is needed, just set the digital pin to LOW. This method works because by putting the reset pin to a LOW state, the micro-controller receives a "hardware reset signal". The following Arduino sketch code shows how to implement and use this method:

void softwareReset( uint8_t prescaller) {
  uint32_t resetTime = millis() + delayMillis;
  while ( resetTime > millis()) { 
    /* wait and do nothing until the required delay expires... */
  }
  // set digital pin 7 to LOW - reset the MCU
  digitalWrite( 7, LOW);
}

void setup() { 
  // set digital pin 7 mode to OUTPUT 
  // it is connected to reset pin via 1kOHM resistor 
  pinMode( 7, OUTPUT);
  digitalWrite( 7, HIGH);
}

void loop() {
  // ... various code...

  // restart in 60 milliseconds
  softwareReset( 60);
}

Unfortunately, this method can't be used on all Arduino boards and also not with every Atmel MCU. The main problem is that the digital pins goes in a LOW state when set to OUTPUT thus resulting in a reset loop which may require to remove the connection with the reset pin before being able to reprogram the MCU. We confirm that Arduino UNO and Arduino MEGA2560 boards can be safely used with this method.

While Arduino was mostly in our discussion (so, Atmel MCUs), there are many other MCUs designed and produced by various manufacturers where the above presented methods work in the same way. However, different code may be required and in case of using "the hacker method", one may need also to study the chip datasheet for being able to correctly use the reset and I/O pins and even may have to use a different resistor value.

Category: