Atmega328 via Raspberry GPIO programming : fuses issue ?

Hi,
I'm trying to use a Raspberry as an ATmega programmer.
Wiring and toolchain installation is not an issue, but finding the right fuses settings is.

My ATmega is connected to the Raspberry via SPI and UART. I defined an additional pin to act as a reset, it's working well.
My ATmega is meant to be 3.3v, 8MHz on the internal oscillator.

Problem is : I can upload a sketch via serial only once. After, serial stops working (but SPI still works), and the only solution I found so far, is burning the same bootloader with Arduino IDE, on a spare PC. Burning the bootloader via SPI, direct on the Pi, works (I see it uploading), but doesn't revive the serial.

Here what I do in details. It is very reproductible.
I start with burning the bootloader to the chip in Arduino IDE, on a spare PC, using this board definition :

atmega328bb.name=[Ardu-Pi] ATmega328 3.3v 8MHz Int. Osc. 57600baud
atmega328bb.upload.protocol=stk500 
atmega328bb.upload.maximum_size=30720 
atmega328bb.upload.speed=57600 
atmega328bb.bootloader.low_fuses=0xE2 
atmega328bb.bootloader.high_fuses=0xD9 
atmega328bb.bootloader.extended_fuses=0x05 
atmega328bb.bootloader.path=arduino:atmega 
atmega328bb.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex 
atmega328bb.bootloader.unlock_bits=0x3F 
atmega328bb.bootloader.lock_bits=0x0F  
atmega328bb.build.mcu=atmega328p 
atmega328bb.build.f_cpu=8000000L 
atmega328bb.build.core=arduino 
atmega328bb.build.variant=standard

I then put the ATmega on the Raspberry Pi, then I check SPI connection :

avrdude -p atmega328p -c gpio -U lfuse:r:-:i -U hfuse:r:-:i -U efuse:r:-:i -U lock:r:-:i

returns :

avrdude-original: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.28s

avrdude-original: Device signature = 0x1e950f
avrdude-original: reading lfuse memory:

Reading | ################################################## | 100% 0.04s

avrdude-original: writing output file "<stdout>"
:01000000E21D
:00000001FF
avrdude-original: reading hfuse memory:

Reading | ################################################## | 100% 0.05s

avrdude-original: writing output file "<stdout>"
:01000000D926
:00000001FF
avrdude-original: reading efuse memory:

Reading | ################################################## | 100% 0.04s

avrdude-original: writing output file "<stdout>"
:0100000005FA
:00000001FF
avrdude-original: reading lock memory:

Reading | ################################################## | 100% 0.03s

avrdude-original: writing output file "<stdout>"
:010000000FF0
:00000001FF

avrdude-original: safemode: Fuses OK

avrdude-original done.  Thank you.

Then I check UART :

avrdude -v  -c arduino -p ATMEGA328P -P /dev/ttyS8 -b 57600

returns :

avrdude-original: Version 5.10, compiled on Jun 18 2012 at 12:38:29
                  Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
                  Copyright (c) 2007-2009 Joerg Wunsch

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

                  Using Port                    : /dev/ttyS8
                  Using Programmer              : arduino
                  Overriding Baud Rate          : 57600
done with autoreset
                  AVR Part                      : ATMEGA328P
                  Chip Erase delay              : 9000 us
                  PAGEL                         : PD7
                  BS2                           : PC2
                  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        65     5     4    0 no       1024    4      0  3600  3600 0xff 0xff
                    flash         65     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          1    0      0     0     0 0x00 0x00
                    signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

                  Programmer Type : Arduino
                  Description     : Arduino
                  Hardware Version: 2
                  Firmware Version: 1.16
                  Vtarget         : 0.0 V
                  Varef           : 0.0 V
                  Oscillator      : Off
                  SCK period      : 0.1 us

avrdude-original: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude-original: Device signature = 0x1e950f
avrdude-original: safemode: lfuse reads as 0
avrdude-original: safemode: hfuse reads as 0
avrdude-original: safemode: efuse reads as 0

avrdude-original: safemode: lfuse reads as 0
avrdude-original: safemode: hfuse reads as 0
avrdude-original: safemode: efuse reads as 0
avrdude-original: safemode: Fuses OK

So, my SPI and UART connections are verified and working.

Then, I try to upload a modified blink sketch (modified for LED on D8). The sketch has been compiled on the spare PC, using the custom board definition.

avrdude -v  -c arduino -p ATMEGA328P -P /dev/ttyS8 -b 57600 -U flash:w:Blink.cpp.hex

returns :

avrdude-original: Version 5.10, compiled on Jun 18 2012 at 12:38:29
                  Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
                  Copyright (c) 2007-2009 Joerg Wunsch

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

                  Using Port                    : /dev/ttyS8
                  Using Programmer              : arduino
                  Overriding Baud Rate          : 57600
done with autoreset
                  AVR Part                      : ATMEGA328P
                  Chip Erase delay              : 9000 us
                  PAGEL                         : PD7
                  BS2                           : PC2
                  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        65     5     4    0 no       1024    4      0  3600  3600 0xff 0xff
                    flash         65     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          1    0      0     0     0 0x00 0x00
                    signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

                  Programmer Type : Arduino
                  Description     : Arduino
                  Hardware Version: 2
                  Firmware Version: 1.16
                  Vtarget         : 0.0 V
                  Varef           : 0.0 V
                  Oscillator      : Off
                  SCK period      : 0.1 us

avrdude-original: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude-original: Device signature = 0x1e950f
avrdude-original: safemode: lfuse reads as 0
avrdude-original: safemode: hfuse reads as 0
avrdude-original: safemode: efuse reads as 0
avrdude-original: NOTE: FLASH memory has been specified, an erase cycle will be performed
                  To disable this feature, specify the -D option.
avrdude-original: erasing chip
avrdude-original: reading input file "Blink.cpp.hex"
avrdude-original: input file Blink.cpp.hex auto detected as Intel Hex
avrdude-original: writing flash (1106 bytes):

Writing | ################################################## | 100% 0.33s

avrdude-original: 1106 bytes of flash written
avrdude-original: verifying flash memory against Blink.cpp.hex:
avrdude-original: load data flash data from input file Blink.cpp.hex:
avrdude-original: input file Blink.cpp.hex auto detected as Intel Hex
avrdude-original: input file Blink.cpp.hex contains 1106 bytes
avrdude-original: reading on-chip flash data:

Reading | ################################################## | 100% 0.24s

avrdude-original: verifying ...
avrdude-original: 1106 bytes of flash verified

avrdude-original: safemode: lfuse reads as 0
avrdude-original: safemode: hfuse reads as 0
avrdude-original: safemode: efuse reads as 0
avrdude-original: safemode: Fuses OK

and the LED starts to blink.

Now I try to burn the same sketch a second time :

avrdude -v  -c arduino -p ATMEGA328P -P /dev/ttyS8 -b 57600 -U flash:w:Blink.cpp.hex

returns :

avrdude-original: Version 5.10, compiled on Jun 18 2012 at 12:38:29
                  Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
                  Copyright (c) 2007-2009 Joerg Wunsch

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

                  Using Port                    : /dev/ttyS8
                  Using Programmer              : arduino
                  Overriding Baud Rate          : 57600
done with autoreset
avrdude-original: stk500_recv(): programmer is not responding

So, UART is not working anymore.

I then check the fuses using SPI :

avrdude -p atmega328p -c gpio -U lfuse:r:-:i -U hfuse:r:-:i -U efuse:r:-:i -U lock:r:-:i

returns :

avrdude-original: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.34s

avrdude-original: Device signature = 0x1e950f
avrdude-original: reading lfuse memory:

Reading | ################################################## | 100% 0.06s

avrdude-original: writing output file "<stdout>"
:01000000E21D
:00000001FF
avrdude-original: reading hfuse memory:

Reading | ################################################## | 100% 0.05s

avrdude-original: writing output file "<stdout>"
:01000000D926
:00000001FF
avrdude-original: reading efuse memory:

Reading | ################################################## | 100% 0.08s

avrdude-original: writing output file "<stdout>"
:0100000005FA
:00000001FF
avrdude-original: reading lock memory:

Reading | ################################################## | 100% 0.05s

avrdude-original: writing output file "<stdout>"
:010000000FF0
:00000001FF

avrdude-original: safemode: Fuses OK

avrdude-original done.  Thank you.

So, the SPI connection still works, and the fuses settings didn't change.

So, why is it not working anymore with UART ?
I want to use the SPI to 'bootload' the ATmega with the right settings (3.3v, 8Mhz internal), and then only use UART to reprogram the chip.

What am I doing wrong here ?

How are you doing reset when using the serial bootloader for uploading? "-c arduino" isn't going to know about the special reset pin you've provided for SPI programming, and sharing the reset signal between a serial port and your additional reset signal could be "tricky."

Your "upload once" symptom is typical of not having an auto-reset; when there is no sketch loaded, the empty memory loops back around to the bootloader, so the bootloader essentially runs continuously. When there's a sketch, the sketch runs instead and the upload operation doesn't manage to reset the board to get into the bootloader.

Hi,
the reset thing with serial is done with a modified avrdude : GitHub - deanmao/avrdude-rpi: Fixing the lack of a DTR pin on the Raspberry Pi for the purposes of uploading hex files to the arduino

The atmega doesn't share the reset pin with SPI and serial, because I change the reset pin when I change the programming method : if I do a test using serial, I remove the SPI reset line and put the serial one instead.

When I try to upload the blink sketch the second time, I could see the LED blink twice fast, and then continues to blink normally, when the autoreset command is sent. So I'm assuming it's resetting normally ?
But I agree with you, this behaviour suggests there's a problem with autoreset (this is why I added some debug LEDs on D8 and on the reset line).

I just tried to use a known procedure (RFM12Pi V2 - Wiki | OpenEnergyMonitor) but it's not working either : burning the special optiboot with fuse settings for 3.3v/8MHz doesn't allow serial programming (the SPI programming works well though).