Arduino/AVR Command-Line Dev Environment PDF Print E-mail
Written by William Grim   
Wednesday, 22 October 2008 12:58

This article is for those who want to develop software for the Arduino ATmega168-based microcontrollers but don't want to use the Arduino IDE. The reasons for not wanting to use the IDE can range from simply disliking the IDE to feeling the need to be able to write code that ports more easily to different kinds of Atmel-based microcontrollers. The steps introduced here should be applicable to several different AVR models, allowing you to push beyond the Arduino platform.

While this article will focus on FreeBSD as its development platform, it should be quite easy to install the avr-gcc toolchain on another platform and to follow the steps for building and uploading the sample code to an AVR from that platform. Should you find yourself on a platform other than FreeBSD, please skip the Toolchains section, except to take note of the applications you will need.

Toolchains

Let's start with the tools you're going to need in FreeBSD (using 6.3-RELEASE as of this writing). All of this software is available in /usr/ports. Please use "portinstall -R -P <package>" (requires /usr/ports/ports-mgmt/portupgrade).

  1. gmake
  2. avr-gcc
  3. avr-libc-devel
  4. avr-binutils
  5. avrdude

You're also going to need the FTDI driver (uftdi.ko). To load it, run the following as root: "kldload uftdi". Then detach your Arduino if it's attached and reattach it to your PC's USB host. You should see /dev/cuaUX and /dev/ttyUX appear, where X is some number representing the device's location. If you don't know which number is your board's location, run "usbdevs -v".

Building and Uploading

Once you've deployed the proper toolchain, let's start with a piece of code that is easy to test: the "Hello, world!" blinking LED example! This will put us on common ground when building and deploying the software so you can be sure if it worked or not. Please copy the following code into "blink.c".

#include <avr/io.h>
#include <util/delay.h>
 
 
int main (void)
{
  /* set PORTB for output*/
  DDRB = 0xFF;

  while (1) {
    /* set PORTB.6 high */
    PORTB = 0x20;

    _delay_ms(1000);

    /* set PORTB.6 low */
    PORTB = 0x04;

    _delay_ms(1000);
  }

  return 1;
}

Now, going to the directory containing blink.c, run the following commands (explanations later):

avr-gcc -DF_CPU=16000000UL \
    -mmcu=atmega168 -o blink.out blink.c # ignore the warning for now
avr-objcopy -O ihex -R .eeprom blink.out blink.hex
sudo avrdude -V -F -c stk500v1 -p m168 -b 19200 -P /dev/cuaU0 -U flash:w:blink.hex

You should now see the little LED blinking fairly rapidly.

Line-by-Line

avr-gcc -DF_CPU=16000000UL \
    -mmcu=atmega168 -o blink.out blink.c # ignore the warning for now

This tells GCC to compile blink.c into blink.out, setting up the code so it knows it'll be running on a 16 MHz ATmega168. This is for timing purposes and must be set correctly. We also tell GCC that the MCU is an ATmega168. Without this, it will not map I/O pins and other hardware correctly when it outputs assembly.

avr-objcopy -O ihex -R .eeprom blink.out blink.hex

This copies information from the ELF binary, blink.out, to blink.hex. The eeprom section is copied, which contains the part of the binary that needs to execute on the ATmega168.

sudo avrdude -V -F -c stk500v1 -p m168 -b 19200 -P /dev/cuaU0 -U flash:w:blink.hex

This final line uploads blink.hex into the ATmega168's flash memory via your USB link to the Arduino. The Arduino's built-in programmer follows the stk500v1 protocol for getting information from a serial line into its flash memory, and it expects data to be sent to it at 19,200 baud. NOTE: You must have root privileges for this to work (this is what "sudo" provides).

Notes

In general, you can use avr-gcc to build your code for various kinds of Atmel-based MCUs. Consult the avr-gcc documentation for a list of the various architectures available for "-mmcu", and be sure to pass the appropriate frequency (Hz) to "-DF_CPU=".

Example Makefile

The following GNUmakefile could prove useful to those wanting a simple template they can use to start larger projects. Tweak as necessary.

CC=avr-gcc
CFLAGS=-Wall -Os -DF_CPU=$(F_CPU) -mmcu=$(MCU)
MCU=atmega168
F_CPU=16000000UL

OBJCOPY=avr-objcopy
BIN_FORMAT=ihex

PORT=/dev/cuaU0
BAUD=19200
PROTOCOL=stk500v1
PART=$(MCU)
AVRDUDE=avrdude -F -V

RM=rm -f

.PHONY: all
all: blink.hex

blink.hex: blink.elf

blink.elf: blink.s

blink.s: blink.c

.PHONY: clean
clean:
	$(RM) blink.elf blink.hex blink.s

.PHONY: upload
upload: blink.hex
	$(AVRDUDE) -c $(PROTOCOL) -p $(PART) -P $(PORT) -b $(BAUD) -U flash:w:$<

%.elf: %.s ; $(CC) $(CFLAGS) -s -o $@ $<

%.s: %.c ; $(CC) $(CFLAGS) -S -o $@ $<

%.hex: %.elf ; $(OBJCOPY) -O $(BIN_FORMAT) -R .eeprom $< $@

Last Updated on Thursday, 13 November 2008 02:05
 
viagra canada no prescription | discount viagra | order viagra online | where to buy viagra | viagra online pharmacy | cialis online no prescription | cheap viagra online | viagra price | order viagra online no prescription | viagra uk