Fork me on GitHub

Project Notes

#220 AVR GCC Toolchain

Programming an Arduino with C and a command line.

Notes

The Arduino IDE is the most convenient way to get started with Arduino, but it does obscure the underlying mechanics of building software for an Arduino.

How to do it from scratch?

I use a Mac and homebrew, so what follows is a MacOSX-specific guide to building software for an Arduino from the command line. I’m using a few posts from the net as my guide, in particular Setting up AVR-GCC Toolchain on Linux and Mac OS X from maxembedded.

UPDATE: the installation procedure has changed. The instructions are update below.

Software Components

Software Installation

Installing avr-gcc actually pulls in avr-gcc and avr-binutils.

brew tap osx-cross/avr
brew install avr-gcc
brew install avrdude --with-usb

Testing the Software Installation

$ which avr-gcc
/usr/local/bin/avr-gcc
$ avr-gcc --version
avr-gcc (GCC) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ which avrdude
/usr/local/bin/avrdude
$ avrdude -?
Usage: avrdude [options]
[...]
avrdude version 6.3, URL: <http://savannah.nongnu.org/projects/avrdude/>

All good to go!

Example: blinky.c

Use avr-gcc to compile and generate the Intel Hex format file. Source is blinky/blinky.c and is written for an atmega328p/Arduino Uno.

$ cd blinky
$ avr-gcc -w -Os -Wl,--gc-sections -DF_CPU=16000000UL -mmcu=atmega328p -c blinky.c
$ avr-gcc -mmcu=atmega328p blinky.o -o blinky.elf
$ avr-objcopy -j .text -j .data -O ihex blinky.elf blinky.hex

I have an Arduino connected to the USB and appearing on /dev/cu.usbmodem14541. Use avrdude to flash it with some options:

  • -D : disable auto erase for flash
  • -v : verbose output
  • -c arduino : specify the programmer to be used
  • -p atmega328p
  • -P /dev/cu.usbmodem14541 : port
  • -b 115200 : baud rate
  • -U flash:w:blinky.hex:i : Perform a memory operation:
    • flash : memtype is flash ROM
    • w : read the specified file (blinky.hex) and write it to flash (memtype)
    • i : specify the file is Intel Hex format
$ avrdude -D -v -c arduino -p atmega328p -P /dev/cu.usbmodem14541 -b 115200 -U flash:w:blinky.hex:i

avrdude: Version 6.3, compiled on Mar 15 2016 at 21:26:45
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/usr/local/Cellar/avrdude/6.3/etc/avrdude.conf"
         User configuration file is "/Users/paulgallagher/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/cu.usbmodem14541
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         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    20     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: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: reading input file "blinky.hex"
avrdude: writing flash (178 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 178 bytes of flash written
avrdude: verifying flash memory against blinky.hex:
avrdude: load data flash data from input file blinky.hex:
avrdude: input file blinky.hex contains 178 bytes
avrdude: reading on-chip flash data:

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

avrdude: verifying ...
avrdude: 178 bytes of flash verified

avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK (E:00, H:00, L:00)

avrdude done.  Thank you.

Example: Makefile

The commands above are a bit tedious. A simple Makefile automates the process:

$ cd blinky
$ make clean
rm *.o
rm *.elf
rm *.hex
$ make
avr-gcc -w -Os -Wl,--gc-sections -DF_CPU=16000000UL -mmcu=atmega328p -c blinky.c
avr-gcc -mmcu=atmega328p -Wl,-Map,blinky.map blinky.o -o blinky.elf
avr-objcopy -j .text -j .data -O ihex blinky.elf blinky.hex
avr-objdump -h -S blinky.elf > blinky.lst
$ make flash
avrdude -D -v -c arduino -p atmega328p -P /dev/cu.usbmodem14541 -b 115200 -U flash:w:blinky.hex:i
[...]
avrdude done.  Thank you.

Credits and References

About LEAP#220 avr-gccavrdude
Project Source on GitHub Project Gallery Return to the LEAP Catalog

This page is a web-friendly rendering of my project notes shared in the LEAP GitHub repository.

LEAP is just my personal collection of projects. Two main themes have emerged in recent years, sometimes combined:

  • electronics - usually involving an Arduino or other microprocessor in one way or another. Some are full-blown projects, while many are trivial breadboard experiments, intended to learn and explore something interesting
  • scale modelling - I caught the bug after deciding to build a Harrier during covid to demonstrate an electronic jet engine simulation. Let the fun begin..
To be honest, I haven't quite figured out if these two interests belong in the same GitHub repo or not. But for now - they are all here!

Projects are often inspired by things found wild on the net, or ideas from the many great electronics and scale modelling podcasts and YouTube channels. Feel free to borrow liberally, and if you spot any issues do let me know (or send a PR!). See the individual projects for credits where due.