Atmega32M1 Optiboot upload problems under embedded linux

Hello everybody,

I'm currently trying to update a ATmega32M1 Arduino from my embedded linux platform.
As Bootloader I use the one from this awesome project.

The successful workflow so far is the following:

  • Burn bootloader via ATMEL ICE and Atmel Studio on Win10 machine
  • Program the applikation via UART from AVR Studio on Win10 machine
  • Connect Arduino to Linux machine
  • Check serial communication @57600 Baud is working

Now on to the troublesome part:

  • invoking avrdude on the linux machine with: /usr/bin/avrdude -C mypath/avrdude.conf -v -v -v -v -p
    atmega32m1 -c arduino -P /dev/ttyS3 -b 57600 -D -U flash:w:mypath/app.ino.hex:i
  • Reset Arduino - since there is no autoreset I implemented a software reset via watchdog
  • Reset Arduino - alternatively reset by removing power

The avrdude options are adopted from Atmel Studio while programming the application for the first time.

This procedure ends with the following error:

         Using Port                    : /dev/ttyS3
         Using Programmer              : arduino
         Overriding Baud Rate          : 57600
avrdude: Send: 0 [30]   [20]
avrdude: Send: 0 [30]   [20]
avrdude: Send: 0 [30]   [20]
avrdude: Recv: . [0d]
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x0d
avrdude: Send: 0 [30]   [20]
avrdude: Recv: 7 [37]
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x37
avrdude: Send: 0 [30]   [20]
avrdude: Recv: 9 [39]
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x39
avrdude: Send: 0 [30]   [20]
avrdude: Recv: 3 [33]
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x33
avrdude: Send: 0 [30]   [20]
avrdude: Recv: 9 [39]
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x39
avrdude: Send: 0 [30]   [20]
avrdude: Recv: O [4f]
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x4f
avrdude: Send: 0 [30]   [20]
avrdude: Recv: . [0a]
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x0a
avrdude: Send: 0 [30]   [20]
avrdude: Recv: . [0a]
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x0a
avrdude: Send: 0 [30]   [20]
avrdude: Recv: . [0a]
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x0a
avrdude: Send: 0 [30]   [20]
avrdude: Recv: . [0a]
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x0a

The responses vary:

        Using Port                    : /dev/ttyS3
         Using Programmer              : arduino
         Overriding Baud Rate          : 57600
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x36
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x39
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x4b
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x0a
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x0a
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x0a
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x0a
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x0a
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x0a

To sum things up:

  • bootloader works the first time for application upload with the win10 machine
  • serial communications between arduino and linux machine are correct
  • avrdude commands do work under win 10

This leaves me wondering what might be the source of the "not in sync" errror.
Is this related to the bootloader or avrdude?
Any ideas or suggestions? (Installing the arduino ide is probably not an option due to the linux system being very restricted)

  • Board not being reset properly (does it blink the led to indicate the bootloader is running) - you have a pretty narrow window to reset the board in with optiboot (unless your version extended that time). In this case, you can upload code only once after burning the bootloader (with no other code on the chip, it will start executing code from address zero, proceed through 30kb of 0xFFFF (a no-op instruction) before hitting the bootloader and running that). Why can't you do autoreset?

  • Different voltage supplied, and board running off of internal oscillator. Internal oscillator speed changes significantly over the operating voltage range, and will only be close enough to the nominal frequency for UART speed to be correct at certain voltages, otherwise there will be a baud rate mismatch and gibberish will be received/transmitted.

  • Bootloader not burned correctly - fuses not set to enable bootloader (though this is ruled out if it works from a different system), so you can upload a sketch only once after burning bootloader.

  • IIRC, Optiboot jumps straight to the application code upon power on.

Thanks for your input!

Concerning an improper reset:
Since I was not sure whether the watchdog triggered reset is enough I also tried simply unplugging the board and then plugging it in again. This is propably the best reset I can do. (Unfortunately this didn't help)

Concerning the bootloader not entering bootloader mode:
I can reprogram the board via uart multiple times from the windows pc, so this should not be the issue.

I only have Rx/Tx and GND Connections available, autoreset needs more pins I guess?

Power supply or a baudrate mismatch can be excluded because serial communications do work flawlessly.

Tomorrow I'll give it another try and keep you updated.

Autoreset, yes - you connect one side of a 0.1uF cap to the DTR or RTS line of the serial adapter, and the other side to the RST pin (there should also be the 10k pullup on reset too, but that's pretty standard).

How did you bootload it if you don't have access to reset? You need reset for ISP programming. You could connect to that pin. Also, you can use the reset button if the board has one.

Worst case, you could solder a flying lead onto reset pin - if you're good at soldering you could add on autoreset pretty quickly (remember to hotglue the wire to something, otherwise it will fatigue and snap right where it connects to PCB). This will at least let you proceed with development on your prototype board (and you'll know to include autoreset in the next rev).

As DrAzzy said, if your optiboot is based on "recent" code, then it uses watchdog reset to start the application, and power-on reset will skip the bootloader. You need an actual "external reset" to start the bootloader - that normally happens via the autoreset circuitry, or you can add a "switch" between the RESET pin and ground.

Thanks to your help, I made some slight progress by resetting the arduino board via the reset pin available via ISP header.

This is the error avrdude prints now:

/usr/bin/avrdude -C /mypath/avrdude.conf -v -p atmega32m1 -c arduino -P /dev/ttyS3 -b 57600 -D -U f
lash:w:/mypath/app.ino.hex:i

avrdude: Version 6.3, compiled on Jun 20 2018 at 15:08:31
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/mypath/avrdude.conf"
         User configuration file is "/home/root/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyS3
         Using Programmer              : arduino
         Overriding Baud Rate          : 57600
         AVR Part                      : ATMEGA32M1
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom         4    20    64    0 no       1024    8      0  9000  9000 0xff 0xff
           flash         33     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          4    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x0d

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x56

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x62

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x61
         Hardware Version: 1378400
         Firmware Version: 408880.52088

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x74

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x31

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x3a

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x20

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x31
         Vtarget         : 40887.6 V
         Varef           : 137840.0 V
         Oscillator      : 9.016 Hz
         SCK period      : 56519.1 us


avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x56

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x31
avrdude: stk500_initialize(): (a) protocol error, expect=0x14, resp=0x33
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x36

avrdude done.  Thank you.

The capacitor for auto reset will be included in the next board revision:)

“Vbat1: 1V” ...

westfw:
“Vbat1: 1V” ...

I'm not quite sure what you mean by this?
The Target Voltage (seems okay)? Or Varef (shouldn't be of any concern for flashing?)

Some progress:
when starting starting avrdude with option -vvvvv it works!

The way I see this, avrdude is to fast accessing the serial port. So slowing down things with output to stderr does the trick here.

So the followup question is: can I somehow delay avrdude a bit? (pipeing the output to /dev/null instead of stderr doesn't work - again too fast)

Another question concerning the reset: can I somehow circumvent the hardware reset and jump directly to the bootloader?

"Vbat1: 1V" ...

I'm not quite sure what you mean by this?

If you look at the "responses" that avrdude is getting, the spell out the message I quoted.

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, [color=red]resp=0x56[/color]

(0x56 is capital-'V', etc)

So it looks to me like your code is running, rather than the bootloader. This isn't really surprising, since there is only a pause of about 1s to see if there are bootloader commands that will cause the bootloader to continue running; it's really set up for auto-reset. It's also possible that "something" is buffering data from before the reset...

Indeed, this is part of the version string printed at the beginning.
I added the autoreset and now it works like a charm - thank you very much for your help!