AVR Mirror

From Wiki

Jump to: navigation, search


Contents

Writing your first AVR program in GCC

Prerequisites

Make sure you have avr-gcc built and installed.

These instructions were designed for anyone using an STK500 development board, and you have any device plugged into the board and ready to be programmed. This code should work with any Atmel AVR chip. It assumes that 8 input switches are hooked up to PORTD, and that 8 output LEDs are hooked up to PORTB.

These instructions are specifically for Linux computers, but the source code should work for any system (including Windows) with avr-gcc installed.

Create the input .c file

Save the following to a file named "mirror.c"

#include <avr/io.h>
#include <avr/wdt.h>

// Note: This is designed to run on an STK500.
// Please connect 10-pin jumpers from:
// PORTD to "SWITCHES"
// PORTB to "LEDS" 

int main(void) {
    // Disable the AVR's internal watchdog timer.
    wdt_disable();

    // Set PORTB as outputs; 
    DDRB = 0xFF;
    // Set the PIND as inputs. 
    DDRD = 0x00; 

    // Turn off all the outputs 
    PORTB = 0; 
    while (1) {
        uint8_t x;
	// Read PIND (switches)
        x = PIND;
 	// Write value to PORTB (LEDs)
        PORTB = x; 
    }
}

Create the Makefile

Save the following to a file named "Makefile"

CC=avr-gcc
OBJCOPY=avr-objcopy
STRIP=avr-strip
UISP=uisp 
OBJDUMP=avr-objdump

# NOTE: Change this to match your AVR chip type. 
MCU=atmega162
PROG_METHOD=stk500

# NOTE: Change this to match the serial port that your STK500 is connected to. 
PORT=/dev/ttyS0

SRECS = mirror.srec 

default: $(SRECS)

mirror: mirror.o

PROGRAMS=$(SRECS:.srec=)
OBJFILES=$(SRECS:.srec=.o)
ASSEMBLY=$(SRECS:.srec=.asm)

clean:
	rm -f $(SRECS) $(PROGRAMS) $(OBJFILES) $(ASSEMBLY)

%.o: %.c
	$(CC) -g -O -mmcu=$(MCU) -c $^ -o $@

%: %.o 
	$(CC) -g -O -mmcu=$(MCU) $^ -o $@

%.asm: %
	$(OBJDUMP) -S -d $^ > $@

%-stripped: %
	$(STRIP) $^ -o $@

%.srec: %-stripped
	$(OBJCOPY) -O srec $^ $@

%.hex: %-stripped
	$(OBJCOPY) -O ihex $^ $@

program-%: %.srec
	$(UISP) -dprog=$(PROG_METHOD) --segment=flash -dserial=$(PORT) -dpart=$(MCU) --erase 
	$(UISP) -dprog=$(PROG_METHOD) --segment=flash -dserial=$(PORT) -dpart=$(MCU) --upload if=$^
	$(UISP) -dprog=$(PROG_METHOD) --segment=flash -dserial=$(PORT) -dpart=$(MCU) --verify if=$^

Use the Makefile above to compile the program

# su 
# make mirror.hex
avr-gcc -g -O -mmcu=atmega162 -c mirror.c -o mirror.o
avr-gcc -g -O -mmcu=atmega162 mirror.o -o mirror
avr-strip mirror -o mirror-stripped
BFD: mirror: warning: Empty loadable segment detected, is this intentional ?
avr-objcopy -O ihex mirror-stripped mirror.hex
rm mirror-stripped

If you get any compiler errors, then you've probably done something wrong.

Go back and double-check what you've done, and try again. NOTE: Different versions of AVR-GCC, binutils, avr-libc, or UISP all may cause differences in the output, so you'll have to debug this yourself.

First, you need to program the device. Making sure that the STK500 is connected to the serial port of the computer, run this command:

# su
# make program-mirror
avr-strip mirror -o mirror-stripped
BFD: mirror: warning: Empty loadable segment detected, is this intentional ?
avr-objcopy -O srec mirror-stripped mirror.srec
uisp  -dprog=stk500 --segment=flash -dserial=/dev/ttyS0 -dpart=atmega162 --erase
Firmware Version: 1.7
Atmel AVR ATmega162 is found.
Firmware Version: 1.7
uisp  -dprog=stk500 --segment=flash -dserial=/dev/ttyS0 -dpart=atmega162 --upload if=mirror.srec
Firmware Version: 1.7
Atmel AVR ATmega162 is found.
Firmware Version: 1.7
Uploading: flash
uisp  -dprog=stk500 --segment=flash -dserial=/dev/ttyS0 -dpart=atmega162 --verify if=mirror.srec
Firmware Version: 1.7
Atmel AVR ATmega162 is found.
Firmware Version: 1.7
Verifying: flash
rm mirror-stripped

At this point, the device should be programmed, and all the LEDs on the STK500 should be off. Try pressing one of the switches on the STK500. The LED next to the switch that you've pressed should light up, indicating that the program is running, mirroring the values of PIND on PORTB. Congratulations, you've just compiled your own AVR program using GCC! Inspect the generated assembly code

If you're interested in the generated AVR assembly code, you can do this:

# su
# make mirror.asm
avr-objdump -S -d mirror > mirror.asm

Then, you can take a look at the file mirror.asm, which should have a source-code annotated assembly listing. Its interesting to compare what GCC generates with how you might choose to do the same thing. Good luck with AVR programming, and feel free to mail "avr at slacy dot com" with any questions or comments.

Personal tools