Wednesday, May 30, 2012

Arduino Mega2560 - Wrapping up the Bootloader Problem

In various posts (here, here, here) I've whined and discussed the problems with the bootloader implemented on the Mega2560 board.  This is a great little board with enough memory and IO ports to do a ton of things around the house.  Someday, I hope to implement a swimming pool controller with one of these.  However, the bootloader has two critical problems:  First, If you have three exclamation points in the code you're loading, the loader jumps into an on-board monitor and doesn't complete.  This is easy to find and correct IF (big if here) you know about it and the sequence !!! isn't in data or code.  The first time I encountered this problem I had a data table that had, 0x21, 0x21, 0x21 in it.  This took a hex dump and search to find the problem.  The second problem is that the watchdog timer would hang up in a loop.  The symptom here is that the watchdog times out, and then fires again before you can get to the first instruction of your sketch;  meaning you have to power down the board and get a new sketch in place before the timer expires.  If you have a really short watchdog timer, this is hard.

I came up with a work around for the watchdog timer problem and just tried to avoid the !!! problem while waiting impatiently for the Arduino developers to fix the problems.  Every week or two, I posted to the developer's mailing list my continuing concern about this problem.  I even contacted the author of the bootloader for help.  Eventually (last month), after almost a year of whining, there was a bootloader made available for the board.  I tested it, it worked, and now I have it running in my house controller.  The new bootloader isn't part of any official release and isn't burned into the boards coming out of production, but one can get it and put it on the board to overcome these problems.  

Notice, there isn't any automatic way to get the fix in place, you have to get the code and burn it on the board yourself.  Or maybe you have a friend that can do it for you.  I've used both the LadyAda USBTinyISP and the Atmel AVRISP MkII to program the new bootloader.  LadyAda's device throws an error when you use it because it isn't perfect for loading into large memory spaces.  However, if you just ignore the error and get on with it, it will work.  The error looks something like:

avrdude: verification error, first mismatch at byte 0x3e000
                               0x0d != 0xff
                      avrdude: verification error; content mismatch

Of course, there are lots of other errors possible, but my experience is that the one above can be ignored.  When you use the AVRISP MkII with the Arduino IDE, you have to use the drivers that come with the IDE, don't load the drivers that you get with the programmer.  Yes, I made all these mistakes getting the board to work for me.  There is also the possibility of using another Arduino as an ISP.  You'll have to hunt for the proper code to do it though; I didn't use this method.  Take a look at the Arduino Forum at arduino.cc to find more information.

The boot loader is available as a hex file in the Arduino repository at: https://github.com/arduino/Arduino-stk500v2-bootloader/tree/master/goodHexFiles  Just put this in the Arduino bootloader directory, rename it properly and load it onto the board.  Sounds easy right?   ... Right?

So, now we have this wonderful little board containing tons of IO pins, three serial ports, and plenty of memory to work with.  It can even be made to recover on it's own with some watchdog programing.

17 comments:

  1. Thanks for the write up and solution to the mega 2560 bootloader watchdog problem. I have been searching most of the day once I found out my watchdog code on my UNO could turn the Mega 2560 I just bought into a brick.

    Question: do the fixed bootloader solve the 3 exclamation mark 'feature'?
    If you print a string like Good Job!!! the Mega will go into either rest or bootload.

    ReplyDelete
  2. Yes, absolutely. The !!! problem was fixed a while ago and I used that version for a while. When this one showed up, I grabbed it and tested it to be sure. The only thing I couldn't test was really big executable files; I could only try out around 150K or so. So, this version will fix both of these long term problems.

    ReplyDelete
  3. Just wanted to let you know that the 'fixed' boot loader for the arduino mega 2560 works like a charm, it fixes the watchdog issue and the 3 exclamation marks issue. I used an Atmel AVRISP mk11 and the arduino ide (v1.0.1) to burn the new boot loader, had to install the avrisp2.inf driver before it would work.
    I learned to NOT install the Atmel AVRStudio software and Not to install their AVRISPMK11 usb driver.

    I also put the following variable declarations and routine in my code outside of the setup and loop routines. Its supposed to disable the watchdog a bootup time before the setup routine runs. The linker is supposed to cause it to run before setup. Not sure yet if its needed with the fixed bootloader but it does not appear to hurt anything on a 'fixed' Mega 2560 R3 and works fine with the factory bootloader for the UNO R3.

    Here is the code:
    //**************************************************
    uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
    void get_mcusr(void) \
    __attribute__((naked)) \
    __attribute__((section(".init3")));

    void get_mcusr(void)
    {
    mcusr_mirror = MCUSR;
    MCUSR = 0;
    // We always need to make sure the WDT is disabled immediately after a
    // reset, otherwise it will continue to operate with default values.
    //
    wdt_disable();
    }
    //***********************************************/

    ReplyDelete
    Replies
    1. I get wdt_disable(); is not declared in this scope when trying to compile. How would I declare it?

      Thank you

      Delete
    2. You have to include the file "wdt.h" up at the top of the module.

      Delete
  4. WOW!! Thank you. I had no idea that the linker could be used this way. This could have saved me a bunch of trouble over time. I've fought the watchdog problem on several boards and updated a number of boot loaders to get around the problem. This little disable could have saved my butt a few times.

    ReplyDelete
  5. Hi, so this post helped my problem of having my arduino no longer be locked out by the watchdog timer. I did the new bootloader (the one linked in this page - all i did was drop it into the bootloader folder), and ran the following code from http://community.cosm.com/node/860


    my code:
    #include // include the library

    unsigned long reboot=15000; //reboots arduino every n seconds (+8 seconds as defined in watchdog statement)
    void setup() {
    // initialize the digital pin as an output.
    // Pin 13 has an LED connected on most Arduino boards:
    pinMode(13, OUTPUT);
    Serial.begin(115200);
    wdt_enable(WDTO_8S); //Set up the watchdog timer. If it isn't reset every 8 seconds, the arduino will reset
    wdt_reset(); //Good practice to reset the watchdog in setup so you don't get locked out
    digitalWrite(13, HIGH); // set the LED on
    delay(4000);
    Serial.println("Rebooted");
    }


    void loop() {
    // Serial.println("Hi");
    digitalWrite(13, HIGH); // set the LED on
    delay(500); // wait for half second
    digitalWrite(13, LOW); // set the LED off
    delay(1000); // wait for a second
    Serial.println (millis());
    if (reboot > millis()) {
    wdt_reset(); }
    }

    My board is a mega 2560. and im running Arduino 1.0.1

    So my problem: it counts up to ~ 23 seconds (15 seconds wait, then 8 sec watchdog), and the board then freezes. Ie it does not reset itself and start counting again. A power cycle fixes the problem.

    So to recap: I no longer have frozen out ardunio boards thanks to this bootloader. but i still have trouble with the watchdog timer. Did I miss something?

    Much thanks


    ReplyDelete
  6. Help me understand something. The only thing you did was to put the bootloader into the IDE bootloader directory? You didn't actually burn it into the chip?

    ReplyDelete
  7. By the way, this is the code I used to test it:

    #include avr/wdt.h // be sure to put the angle brackets around this.

    void setup(){

    wdt_reset(); // First thing, turn it off
    wdt_disable();
    Serial.begin(57600);
    Serial.println("Hello, in setup!!!");
    }

    int firstTime = true;

    void loop() {
    if (firstTime){
    firstTime = false;
    Serial.println("In loop waiting for Watchdog");
    wdt_enable(WDTO_8S); // eight seconds from now the device will reboot
    }
    // now just do nothing
    }

    ReplyDelete
  8. You can put a 470K resistor between the AREF and A1 to fix the watchdog timer issue.

    ReplyDelete
  9. I can't test this since I have modified all my mega2560 boards with the new bootloader. However, I can't see any reason why it would work. How can putting a voltage on the first analog pin have any affect on the watchdog timer?

    ReplyDelete
  10. Dave,
    thanks for your reply - sorry I didn't post until now. I bought a USB tinyISP device. I downloaded the hex file to the arduino/bootloader folder. I opened up your code you posted in the comments. I followed the instructions for hardware setup posted here:http://www.ladyada.net/make/usbtinyisp/faq.html. I selected the USBTinyISP programmer from the Arduino IDE (v1.0.1). Then I hit "Burn bootloader". After over 10 min I got the error message you did in your main post -- avrdude verification error. I unplugged the usbtinyisp, plugged in the arduino board directly and tried to burn the example program "Blink" onto it through the 'upload' command - the normal way of doing things. it still freezes when "uploading..." Any other suggestions or have I done anything incorrectly? How can I get my board to unfreeze? It no longer waits 23 seconds and then freezes, but it isnt much use now as it is. Much thanks

    ReplyDelete
    Replies
    1. Did you figure out a way to fix your mega2560 board? I've done exactly the same as you, and it does not work for me either..

      Delete
  11. I never had that happen. It also took less than 10 minutes to burn the bootloader. I never timed it though, so I can't give you a number to work with. Assuming that you renamed the file that you downloaded to be the correct one, I suggest you give it another try to see if it will work the second time; if it fails the same way, go back to the original bootloader and see if you can get it back that way.

    Failing that (hopefully not) download version 21 of the arduino IDE and give that a try using the same setup. I haven't tried burning a new bootloader with the later versions of the IDE, so I don't know what happens with them.

    There have been several people contact me that have done this, all successfully, but that doesn't mean much since we've all seen differing results for this kind of thing.

    ReplyDelete
  12. So no love for a arduino mega1280 bootloader upgrade/fix?

    ReplyDelete
  13. I haven't seen any fix for the 1280 anywhere. Go visit the developer's list and start bugging them about it.

    ReplyDelete
  14. Thanks for the three exclamation hint!

    ReplyDelete