AVR Mirror
From Wiki
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.
