Developing for the ATmega328P under Linux

View document on multiple pages.

1. Introduction
2. Compiling binutils
3. Compiling avr-gcc
4. Compiling avr-libc
5. Compiling AVRDUDE

1. Introduction

The Atmel AVR ATmega328P is part of the mega48/mega88/mega168 series of microcontrollers, which are used on the Orangutan Robot Controllers, Arduino boards, and in many other robot controllers and individual electronics projects. The mega328 has twice as much program (Flash) memory, RAM, and EEPROM as the mega168, while keeping the same architecture and pinout as the earlier chips. This means that most projects based on the earlier processors can be easily upgraded to the 328, making it possible to fit more complex programs or deal with more much more data.

Note: The newer AVR ATmega328PB improves on the ATmega328P by adding more pins and peripherals. This chip is available on our A-Star 328PB Micro.

GCC support for the mega328P

The following systems have compiler support for the ATmega328 included:

  • Microsoft Windows with Microchip Studio (or AVR Studio and WinAVR)
  • Microsoft Windows, Linux, or macOS with the Arduino IDE
  • Microsoft Windows, Linux, or macOS with MPLAB X 5.05 or later
  • Ubuntu Linux versions 8.10 (intrepid) and up
  • Fedora 9 updates / Fedora Development
  • Debian Linux 5.0.0 (lenny) and up

If you are using a system without 328P support, it is possible to install the latest version of the compiler and related tools from source by following the step-by-step instructions in Section 3.

AVRDUDE support for the mega328P

The popular AVR programming software AVRDUDE includes support for the mega328 in version 5.6 and up.

2. Compiling binutils

Checking the currently installed version of avr binutils

Run the following command:

avr-as  --version

Downloading the source code

Get the latest version from the binutils FTP site. We tested these instructions with version 2.19.1.

Unpacking the archive

Run the following command:

tar xzf ~/Desktop/binutils-2.19.1.tar.gz
cd binutils-2.19.1

Configuring and compiling binutils

The options given here just specify that the AVR version of binutils should be compiled:

./configure --prefix=/usr/local --target=avr
make
sudo make install

Next steps

You should now have the latest version of all of the binutils utilities compiled for the avr and installed in your /usr/local/bin. Proceed to Section 3 to install avr-gcc.

3. Compiling avr-gcc

The latest versions of GCC (4.2.3 and up) include support for the ATmega328P, as well as the ATmega48P, ATmega88P, and ATmega168P.

Checking the currently installed version of avr-gcc

Run the following command:

avr-gcc --version

You can test for support by creating an empty file test.c and running avr-gcc -mmcu=atmega328p test.c. If your version of gcc does not support the chip, you will see the following errors:

unknown MCU 'atmega328p' specified
...
test.c:1: error: MCU "atmega328p" supported for assembler only

Installing prerequisites

Recent versions of GCC (4.3.x) depend on GMP and MPFR, which can be installed from their web pages. Under Ubuntu, you can get these packages by running the following command.

sudo apt-get install libgmp3-dev libmpfr-dev

Other distributions probably provide similar packages.

Downloading the source code

Get gcc-4.3.3.tar.bz2 or a later version from the GCC FTP site or from a mirror closer to you if possible. We recommend getting the full GCC, which includes the C++ compiler, not just gcc-core.

Unpack the archive

Run the following command:

tar xjf ~/Desktop/gcc-4.3.3.tar.bz2
cd gcc-4.3.3

Configure, compile, and install GCC

Note that you need to compile GCC from a separate directory, and that we are specifying that only C and C++ be included. If you want to try compiling FORTRAN, ObjectiveC, or GCJ for the AVR, you’re on your own!

mkdir build
cd build
../configure --prefix=/usr/local --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp
make
sudo make install

Next steps

The latest version of avr-gcc should now be on your path. Next, proceed to Section 4 to install avr-libc for all of the AVR microcontrollers supported by GCC.

4. Compiling avr-libc

Downloading the archive

Get the latest version from the avr-libc website. You should get version 1.6.6 or higher.

Configuring and compiling avr-libc

Run the following command:

tar xjf ~/Desktop/avr-libc-1.6.6.tar.bz2
cd avr-libc-1.6.6

Compiling avr-libc

Make sure that the latest avr-gcc is on your path as the default avr-gcc before you run these commands, or you will not get support for the mega328. When running configure, you should see a line of output that says (make sure “checking if avr-gcc has support for atmega328p… yes”. If you don’t see this, double-check your avr-gcc installation.

./configure --host=avr --prefix=/usr/local
make
sudo make install

Next steps

You should now have an avr-libc installed that includes support for the mega328, so you will be able to compile programs for this microcontroller. To program a chip, you will probably want AVRDUDE. Section 5 contains instructions for compiling installing and installing the latest version.

5. Compiling AVRDUDE

Checking the currently installed version of AVRDUDE

Run the following command:

avrdude -v

You need at least version 5.6 for ATmega328P support.

Downloading the source code

Get the latest version from the AVRDUDE web site.

Unpacking the archive

Run the following command:

tar xzf ~/Desktop/avrdude-5.6.tar.gz
cd avrdude-5.6

Compiling and installing AVRDUDE

Unlike the other packages, AVRDUDE does not need to be specifically told to compile for the AVR. So you should be able to compile it with no special options:

./configure
make
sudo make install

Optional: configuring earlier versions of AVRDUDE for the ATmega328P

The following configuration file will let versions of AVRDUDE before 5.6 work with the 328. Just copy these definitions to the end of avrdude.conf, which can be found in /etc, /usr/local/etc, or sometimes in the same directory as the avrdude executable.

#------------------------------------------------------------
# ATmega328P
#------------------------------------------------------------

part
    id              = "m328p";
    desc            = "ATMEGA328P";
     has_debugwire = yes;
     flash_instr   = 0xB6, 0x01, 0x11;
     eeprom_instr  = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,
                     0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,
                     0x99, 0xF9, 0xBB, 0xAF;
    stk500_devcode  = 0x86;
    # avr910_devcode = 0x;
    signature       = 0x1e 0x95 0x0F;
    pagel           = 0xd7;
    bs2             = 0xc2;
    chip_erase_delay = 9000;
    pgm_enable       = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
                       "x x x x x x x x x x x x x x x x";

    chip_erase       = "1 0 1 0 1 1 0 0 1 0 0 x x x x x",
                       "x x x x x x x x x x x x x x x x";

    timeout         = 200;
    stabdelay       = 100;
    cmdexedelay     = 25;
    synchloops      = 32;
    bytedelay       = 0;
    pollindex       = 3;
    pollvalue       = 0x53;
    predelay        = 1;
    postdelay       = 1;
    pollmethod      = 1;

    pp_controlstack     =
        0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
        0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
        0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
        0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
    hventerstabdelay    = 100;
    progmodedelay       = 0;
    latchcycles         = 5;
    togglevtg           = 1;
    poweroffdelay       = 15;
    resetdelayms        = 1;
    resetdelayus        = 0;
    hvleavestabdelay    = 15;
    resetdelay          = 15;
    chiperasepulsewidth = 0;
    chiperasepolltimeout = 10;
    programfusepulsewidth = 0;
    programfusepolltimeout = 5;
    programlockpulsewidth = 0;
    programlockpolltimeout = 5;

    memory "eeprom"
        paged           = no;
        page_size       = 4;
        size            = 1024;
        min_write_delay = 3600;
        max_write_delay = 3600;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read            = " 1 0 1 0 0 0 0 0",
                          " 0 0 0 x x x a9 a8",
                          " a7 a6 a5 a4 a3 a2 a1 a0",
                          " o o o o o o o o";
    
        write           = " 1 1 0 0 0 0 0 0",
                          " 0 0 0 x x x a9 a8",
                          " a7 a6 a5 a4 a3 a2 a1 a0",
                          " i i i i i i i i";

        loadpage_lo     = "  1   1   0   0      0   0   0   1",
                          "  0   0   0   0      0   0   0   0",
                          "  0   0   0   0      0   0  a1  a0",
                          "  i   i   i   i      i   i   i   i";

        writepage       = "  1   1   0   0      0   0   1   0",
                          "  0   0   x   x      x   x   a9  a8",
                          " a7  a6  a5  a4     a3  a2   0   0",
                          "  x   x   x   x      x   x   x   x";

        mode            = 0x41;
        delay           = 5;
        blocksize       = 4;
        readsize        = 256;
        ;

    memory "flash"
        paged           = yes;
        size            = 32768;
        page_size       = 128;
        num_pages       = 256;
        min_write_delay = 4500;
        max_write_delay = 4500;
        readback_p1     = 0xff;
        readback_p2     = 0xff;
        read_lo         = " 0 0 1 0 0 0 0 0",
                          " 0 0 a13 a12 a11 a10 a9 a8",
                          " a7 a6 a5 a4 a3 a2 a1 a0",
                          " o o o o o o o o";
        
        read_hi          = " 0 0 1 0 1 0 0 0",
                           " 0 0 a13 a12 a11 a10 a9 a8",
                           " a7 a6 a5 a4 a3 a2 a1 a0",
                           " o o o o o o o o";
        
        loadpage_lo     = " 0 1 0 0 0 0 0 0",
                          " 0 0 0 x x x x x",
                          " x x a5 a4 a3 a2 a1 a0",
                          " i i i i i i i i";
        
        loadpage_hi     = " 0 1 0 0 1 0 0 0",
                          " 0 0 0 x x x x x",
                          " x x a5 a4 a3 a2 a1 a0",
                          " i i i i i i i i";
        
        writepage       = " 0 1 0 0 1 1 0 0",
                          " 0 0 a13 a12 a11 a10 a9 a8",
                          " a7 a6 x x x x x x",
                          " x x x x x x x x";

        mode        = 0x41;
        delay       = 6;
        blocksize   = 128;
        readsize    = 256;

        ;
        
    memory "lfuse"
        size            = 1;
        min_write_delay = 4500;
        max_write_delay = 4500;
        read            = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
                          "x x x x x x x x o o o o o o o o";
        
        write           = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
                          "x x x x x x x x i i i i i i i i";
        ;
    
    memory "hfuse"
        size            = 1;
        min_write_delay = 4500;
        max_write_delay = 4500;
        read            = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
                          "x x x x x x x x o o o o o o o o";
        
        write           = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
                          "x x x x x x x x i i i i i i i i";
        ;
    
    memory "efuse"
        size            = 1;
        min_write_delay = 4500;
        max_write_delay = 4500;
        read            = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
                          "x x x x x x x x x x x x x o o o";
        
        write           = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
                          "x x x x x x x x x x x x x i i i";
        ;
    
    memory "lock"
        size            = 1;
        min_write_delay = 4500;
        max_write_delay = 4500;
        read            = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
                          "x x x x x x x x x x o o o o o o";
        
        write           = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
                          "x x x x x x x x 1 1 i i i i i i";
        ;
    
    memory "calibration"
        size            = 1;
        read            = "0 0 1 1 1 0 0 0 0 0 0 x x x x x",
                          "0 0 0 0 0 0 0 0 o o o o o o o o";
        ;
    
    memory "signature"
        size            = 3;
        read            = "0 0 1 1 0 0 0 0 0 0 0 x x x x x",
                          "x x x x x x a1 a0 o o o o o o o o";
        ;
;

New Products

VL53L5CX Time-of-Flight 8×8-Zone Distance Sensor Carrier with Voltage Regulator, 400cm Max
Free Circuit Cellar magazine December 2021
Motoron M2S18v18 Dual High-Power Motor Controller Shield Kit for Arduino
12V Step-Up Voltage Regulator U3V40F12
Free Circuit Cellar magazine April 2022
Motoron M2S24v16 Dual High-Power Motor Controller Shield Kit for Arduino
DRV8874 Single Brushed DC Motor Driver Carrier
Motoron M2S18v20 Dual High-Power Motor Controller Shield for Arduino (Connectors Soldered)
6V Step-Up Voltage Regulator U3V40F6
DRV8876 (QFN) Single Brushed DC Motor Driver Carrier
Log In
Pololu Robotics & Electronics
Shopping cart
(702) 262-6648
Same-day shipping, worldwide
Menu
Shop Blog Forum Support
My account Comments or questions? About Pololu Contact Ordering information Distributors