0
\$\begingroup\$

I have two ATMEGA328's and I'm experiencing a very strange problem. I have a very simple code to blink a LED:

    #define F_CPU 8000000UL

    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdlib.h>

    void delayms( uint16_t millis ) 
    {
            while ( millis ) 
            {
                    _delay_ms( 1 );
                    millis--;
            }
    }

    int main( void ) 
    {
            DDRD = 0b11111111;

            int interval = 1000;

            while ( 1 ) 
            {
                    PORTD = 0b11111111;
                    delayms( interval );
                    PORTD = 0b00000000;
                    delayms( interval );
            }

            return 0;
    }

And here is the Makefile:

    CC=/usr/bin/avr-gcc
    MEGA=328p
    CFLAGS=-g -Os -Wall -mcall-prologues -mmcu=atmega$(MEGA)
    OBJ2HEX=/usr/bin/avr-objcopy 
    PROG=/usr/bin/avrdude
    TARGET=blink

    program : $(TARGET).hex
            $(PROG) -c avrispv2 -p m$(MEGA) -P /dev/ttyACM2 -e
            $(PROG) -c avrispv2 -p m$(MEGA) -P /dev/ttyACM2 -U flash:w:$(TARGET).hex

    %.obj : %.o
            $(CC) $(CFLAGS) $< -o $@

    %.hex : %.obj
            $(OBJ2HEX) -R .eeprom -O ihex $< $@

    clean :
            rm -f *.hex *.obj *.o

The code works perfectly, but here's the strange part:

ATMEGA #1:

  • Works as expected when connected straight to the 5V source. Meaning it executes the last code, that was written to it.
  • Can't be programmed. avrdude: stk500v2_command(): command failed. Can't connect.

ATMEGA #2:

  • Works only through Arduino case. When connected straight to the 5V source, PORTD outputs nothing.
  • Can be programmed.

This mystery has happened so many times before. All I can think of is that it has something to do with the fuse bits or possibly the frequency is 'hardcoded' for one chip at 8Mhz and 16Mhz for the other one. I was expecting that F_CPU defines that and avrdude uses that definition to set the fuses correctly.

I don't want to use an external oscillator. Any hints on what's going on?

UPDATE: Here's the output for one of the ATMEGAs that failed to program.

/usr/bin/avrdude -c avrispv2 -p m328p -P /dev/ttyACM0 -e -U lfuse:w:0xe2:m -B 250.0 -U hfuse:w:0xd9:m

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.07s

avrdude: Device signature = 0x1e950f
avrdude: erasing chip
avrdude: reading input file "0xe2"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.07s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xe2:
avrdude: load data lfuse data from input file 0xe2:
avrdude: input file 0xe2 contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: reading input file "0xd9"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xd9:
avrdude: load data hfuse data from input file 0xd9:
avrdude: input file 0xd9 contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified

avrdude: safemode: Fuses OK (E:07, H:D9, L:E2)

avrdude done.  Thank you.

/usr/bin/avrdude -c avrispv2 -p m328p -P /dev/ttyACM0 -U flash:w:serial.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.07s

avrdude: Device signature = 0x1e950f
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "serial.hex"
avrdude: input file serial.hex auto detected as Intel Hex
avrdude: writing flash (912 bytes):

Writing |                                                    | 0% 0.00s
avrdude: stk500v2_ReceiveMessage(): timeout
Writing | ######                                             | 12% 2.84s
avrdude: stk500v2_ReceiveMessage(): timeout
Writing | #############                                      | 25% 5.68s
avrdude: stk500v2_ReceiveMessage(): timeout
Writing | ###################                                | 37% 8.52s
avrdude: stk500v2_ReceiveMessage(): timeout
Writing | ###############################                    | 62% 14.20s
avrdude: stk500v2_ReceiveMessage(): timeout
Writing | ######################################             | 75% 17.04s
avrdude: stk500v2_ReceiveMessage(): timeout
Writing | ############################################       | 87% 19.89s
avrdude: stk500v2_ReceiveMessage(): timeout
Writing | ################################################## | 100% 22.73s

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

Reading |                                                    | 0% 0.00s
avrdude: stk500v2_ReceiveMessage(): timeout
Reading | ######                                             | 12% 2.80s
avrdude: stk500v2_ReceiveMessage(): timeout
Reading | ###################                                | 37% 8.39s
avrdude: stk500v2_ReceiveMessage(): timeout
Reading | #########################                          | 50% 11.18s
avrdude: stk500v2_ReceiveMessage(): timeout
Reading | ###############################                    | 62% 13.98s
avrdude: stk500v2_ReceiveMessage(): timeout
Reading | ############################################       | 87% 19.57s
avrdude: stk500v2_ReceiveMessage(): timeout
Reading | ################################################## | 100% 22.37s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x80 != 0x0c
avrdude: verification error; content mismatch

avrdude: safemode: Fuses OK (E:07, H:D9, L:E2)

avrdude done.  Thank you.

Makefile:9: recipe for target 'program' failed
make: *** [program] Error 1
\$\endgroup\$
8
  • \$\begingroup\$ How can Atmega #1 work as expected if it can't be programmed? And what does the Arduino case do?... Sounds like a hardware problem. Like "straight to the 5V source" doesn't provide the necessary voltage for programming on #1, and #2 the case is distributing the power for you? \$\endgroup\$ Commented Sep 26, 2016 at 21:24
  • \$\begingroup\$ "#define F_CPU 8000000UL" Doesn't set any fuses, it just directs how the compiled code calculates timing related things. You will probably have to explicitly tell avrdude how to set the fuses, and yes the actual clock so produced needs to match what you set in the define, or else everything following from the define will be off by the ratio of difference. \$\endgroup\$ Commented Sep 26, 2016 at 21:24
  • \$\begingroup\$ @DigitalNinja It can't be programmed, but it executes the last program that was written to it without the Arduino Uno. \$\endgroup\$
    – 0x29a
    Commented Sep 26, 2016 at 21:27
  • \$\begingroup\$ Try to connect to both chips with avrdude in the verbose mode (-v). e.g. avrdude -c avrispv2 -p m328p -P /dev/ttyACM2 -v and post what you get. It should cast some light on what fails. \$\endgroup\$
    – jms
    Commented Sep 26, 2016 at 21:34
  • 1
    \$\begingroup\$ The internal clock is not accurate enough to support reliable "rs232 serial" comms, so the avrdude utility can't reliably communicate with the bootloader. You should still be able to load firmware through the ISCP (SPI) port, using a programmer instead of the on-chip bootloader. \$\endgroup\$
    – MarkU
    Commented Sep 26, 2016 at 22:51

1 Answer 1

2
\$\begingroup\$

I got very confused by your setup: I thougth that you always placed the ATmega328 on a prototyping board (e.g. solderless breadboard), and you were trying to program the ATmega with a standalone stk500v2 -style programmer. While you mentioned that chip #2 works when placed in an "arduino case", I thought that you meant an electronics enclosure intended for an arduino, not an actual arduino PCB.

I think that I have finally understood what you have tried to do:

  • You have two ATmega328 chips, an Arduino Uno board, and a Pololu PGM03A in-circuit serial programmer (which is very similar to the original STK500V2 programmer by Atmel).

  • To program an ATmega328, you connected the PGM03A to the ICSP programming header of the Arduino Uno, and placed the chip in the socket of the Arduino.

  • To use an ATmega328, you removed it from the Arduino PCB and placed it on some prototyping board, to see if it works without the arduino.

My hypothesis on why the two chips don't work:

ATmega #2 is the one which came with the arduino. As the arduino board has a 16 MHz crystal, the chip fuse bits were programmed at the factory so that the ATmega runs at 16 MHz using the integrated crystal oscillator. Thus the ATmega works fine and gets programmed correctly when placed on the arduino board (crystal present), but fails to boot on a separate board (which doesn't have a crystal) due to not having any clock source.

ATmega #1 is programmed to use the internal RC oscillator at some frequency (very likely 8 MHz, possibly 1MHz, 128 kHz or 16 kHz), which is why it works as expected both on the arduino board and on a separate board without a crystal.
When programming an ATmega328 with a serial programmer, the clock speed of the ATmega has to be at least four times the clock speed of the serial data. As far as I know, the default SPI clock frequency of the PGM03A is 4 MHz, while a maximum of 2 MHz is required to successfully program an ATmega running at 8 MHz. Thus the ICSP is trying to send data too fast for the ATmega to receive.

In order to get ATmega #2 to run stand-alone, you have two options:

  • Add a crystal to your board

  • Program the fuse bits so that the ATmega uses the internal RC oscillator instead. For example, running avrdude with the options -U lfuse:w:0xe2:m -U hfuse:w:0xd9:m will configure the chip to run at 8 MHz using the RC oscillator. There are nifty online tools for calculating the right fuse settings, and they even output the avrdude command line options directly.

In order to get ATmega #1 to program, you need to lower the programmers SPI frequency, which can be done with the -B bitclock option of avrdude (where bitclock is the period of one clock cycle in microseconds). For example, to program a chip running at 1 MHz you need to set the frequency to one quarter of the clock frequency (250 kHz) or less. As 250 kHz implies a period of 4 microseconds (1 / 250 kHz = 4 µs), you would give avrdude the command line option -B 4.0

\$\endgroup\$
7
  • \$\begingroup\$ Thank you very much you understood me correctly. Can't wait to get home and try it out, thanks! \$\endgroup\$
    – 0x29a
    Commented Sep 27, 2016 at 14:36
  • \$\begingroup\$ I tried various variations for the -B option, but couldn't get the chip to be programmed. I tried setting the fuse bits for the other atmega as you described and worked like a charm! I can still program it without the -B option, I guess one something's wrong with the other ATMEGA, thank you!! \$\endgroup\$
    – 0x29a
    Commented Sep 27, 2016 at 18:26
  • \$\begingroup\$ @0x29a If -B 4.0 didn't work, you need to go lower. Try e.g. -B 250.0 (4 kHz), which will work with any clock frequency you can set with the fuse bits. It'll be extremely slow trough. One you get it working, you should reprogram new fuse settings (the same ones you programmed the other with) to get it working properly. \$\endgroup\$
    – jms
    Commented Sep 27, 2016 at 18:30
  • \$\begingroup\$ I changed to 250.0, i got a different output, but still timeout messages, I updated my question with the output, thanks! \$\endgroup\$
    – 0x29a
    Commented Sep 27, 2016 at 20:09
  • \$\begingroup\$ @0x29a How are you programming it? Are you still using the PGM03A to program via the ICSP header, or are you now trying to program the ATmega on the arduino using the arduino itself as a programmer (nothing connected to the ICSP header)? The chips don't have any bootloader on them when they come from the factory, so you can't program them with the arduino itself without programming a bootloader first. The chip that came with the arduino obviously has a bootloader on it. \$\endgroup\$
    – jms
    Commented Sep 27, 2016 at 21:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.