본문 바로가기
Development

맥에서 AVR 개발하기 2 : 개발 프로그램 컴파일하기

by 맥쓰는풍경/송호정 2014. 4. 26.

 맥에서 AVR 개발하기 2 : 개발 프로그램 컴파일하기

 



맥에서 AVR 개발하기 1 : AVR 툴체인 설치하기

맥에서 AVR 개발하기 2 : 개발 프로그램 컴파일하기

맥에서 AVR 개발하기 3 : ISP 드라이버 설치하기

맥에서 AVR 개발하기 4 : 다운로더 설치 및 프로그램 다운로드


 

0. 개요

 

지난번에 AVR 툴체인을 설치하였습니다.

그럼 이번에는 설치된 툴체인을 사용하여 개발된 프로그램을 컴파일해 보도록 하겠습니다.

 

우선 프로젝트에 맞는 AVR 프로그램을 개발합니다.

예를 들어 초음파 거리측정을 하는 프로그램을 개발했다고 가정합니다.

Project 이름은 SonicCalc 입니다.

SonicCalc.h SonicCalc.c

ExtInt.h ExtInt.c

TimerInt.h TimerInt.c

UART.h UART.c

 

필자는 프로그램을 모듈별로 파일을 분리하여 개발합니다.

파일의 이름에서 보듯이 SonicCalc는 초음파 거리 계산을 하는 모듈이며 메인 모듈입니다.

ExtInt는 외부 인터럽트 모듈, TimerInt는 타이머 인터럽트 모듈, UART는 시리얼 통신 모듈을 의미합니다. 


1. 환경설정 하기


이전 강좌에서 설정한 내용이지만 다시한번 확인합니다.


개발된 소스를 컴파일 하려면 툴체인이 설치된 디렉토리를 PATH에 넣어주어야 합니다.

이전 강좌에서 한 것처럼 터미널을 실행시킨 후 다음 명령어를 실행합니다.

$ export prefix=/opt/avr

$ export PATH=$prefix/bin:$PATH


이렇게 설정한 후 개발한 소스를 컴파일 하면 됩니다.


하지만 이렇게 하면 터미널을 종료했다 다시 시작하거나, 다른 터미널을 실행시키면 앞에서 설정한 PATH가 적용되지 않으므로 터미널을 실행시킬 때마다 PATH를 다시 입력해야 합니다.

터미널을 실행시킬 때 마다 위의 PATH가 항상 설정 되는것을 원한다면 사용자 홈 디렉토리의 .bash_profile 파일에 다음을 추가하면 됩니다.(앞에서 이미 추가하였다면 넘어갑니다).

$ vi ~/.bash_profile

export prefix=/opt/avr

export PATH=$prefix/bin:$PATH

 

이제 새로 터미널을 실행할 때마다 환경설정이 적용된 것을 확인할 수 있습니다.

$ env

TERM_PROGRAM=Apple_Terminal

SHELL=/bin/bash

.

.

.

PATH=/opt/avr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin

.

.

.

prefix=/opt/avr

.

.

.

 

2.  빌드폴더 만들기

 

소스가 있는 프로젝트 폴더에서 컴파일해도 무관하지만, 필자는 object 파일 등이 소스와 함께 존재하는 것이 별로 좋아하지 않으므로 빌드 폴더를 만들어서 사용합니다.

 

$ mkdir build

$ cd build

 

3. Makefile 만들기

 

그럼 컴파일을 하기 위한 Makefile을 만듭니다.

Makefile은 직접 만들어도 되지만 여러가지 옵션들을 고민하면서 만들어야 하므로 공부를 좀 해야 합니다.

그래서 가장 쉬운 방법으로 윈도우즈의 AVR Studio에서 자동으로 만들어주는 Makefile을 가지고 왔습니다.

윈도우즈의 AVR Studio를 사용하여 만든 프로젝트 폴더 아래의 default 폴더를 보면 Makefile이 있습니다.

이 Makefile을 복사해 온 후, 파일에서 Target MCU와 PROJECT, 컴파일 할 소스등을 수정하면 됩니다.

(아래의 Makefile은 필자의 개발 환경에 맞는 설정들이며 사용자에 따라 다를 수 있습니다).

 

$ vi Makefile
 
###############################################################################
# Makefile for the project SonicCalc
###############################################################################
 
## General Flags
PROJECT = SonicCalc
MCU = atmega128
TARGET = SonicCalc.elf
CC = avr-gcc
CPP = avr-g++
 
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)
 
## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
 
## Assembly specific flags
ASMFLAGS = $(COMMON)
 
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
 
## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -Wl,-Map=SonicComm.map
 
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
 
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
 
## Libraries
LIBS = -lm -lprintf_flt
 
## Objects that must be built in order to link
OBJECTS = SonicCalc.o ExtInt.o TimerInt.o UART.o
 
## Objects explicitly added by the user
LINKONLYOBJECTS =
 
## Build
all: $(TARGET) SonicCalc.hex SonicCalc.eep SonicCalc.lss
 
## Compile
SonicCalc.o: ../SonicCalc.c
        $(CC) $(INCLUDES) $(CFLAGS) -c  $<
 
ExtInt.o: ../ExtInt.c
        $(CC) $(INCLUDES) $(CFLAGS) -c  $<
 
TimerInt.o: ../TimerInt.c
        $(CC) $(INCLUDES) $(CFLAGS) -c  $<
 
UART.o: ../UART.c
        $(CC) $(INCLUDES) $(CFLAGS) -c  $<
 
##Link
$(TARGET): $(OBJECTS)
         $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
 
%.hex: $(TARGET)
        avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@
 
%.eep: $(TARGET)
        -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
 
%.lss: $(TARGET)
        avr-objdump -h -S $< > $@
 
## Clean target
.PHONY: clean
clean:
        -rm -rf $(OBJECTS) SonicCalc.elf dep/* SonicCalc.hex SonicCalc.eep SonicCalc.lss SonicCalc.map
 
## Other dependencies
-include $(shell mkdir dep 2>NUL) $(wildcard dep/*)

 

4. 컴파일 하기

 

Makefile을 만들었으면 이제 프로젝트 소스를 컴파일 합니다.

컴파일을 단순히 make 명령을 입력하는 것으로 끝납니다.

 

$ make

 

컴파일 과정에서 에러가 발생하면 에러를 확인하고 소스를 수정합니다.

에러가 없이 컴파일이 완료되었습니다.

.

.

.

avr-gcc  -mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT SonicCalc.o -MF dep/SonicCalc.o.d  -c  ../SonicCalc.c

avr-gcc  -mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT ExtInt.o -MF dep/ExtInt.o.d  -c  ../ExtInt.c

avr-gcc  -mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT TimerInt.o -MF dep/TimerInt.o.d  -c  ../TimerInt.c

avr-gcc  -mmcu=atmega8 -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT UART.o -MF dep/UART.o.d  -c  ../UART.c

avr-gcc -mmcu=atmega8 -Wl,-Map=SonicComm.map SonicComm.o UART.o ExtInt.o TimerInt.o Utility.o EEPROM.o SPI.o    -lm -lprintf_flt  -o SonicComm.elf

avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  SonicComm.elf SonicComm.hex

avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex SonicComm.elf SonicComm.eep || exit 0

avr-objdump -h -S SonicComm.elf > SonicComm.lss

 

에러가 없이 컴파일이 완료되면 다음과 같이 컴파일 후 생성된 결과 파일들을 확인할 수 있습니다.

$ ls

NUL             SonicCalc.elf   SonicCalc.map   UART.o          ExtInt.o

SonicCalc.hex   SonicCalc.o     Makefile        SonicCalc.eep   SonicCalc.lss

TimerInt.o      dep

 

AVR 툴체인을 사용하여 개발된 소스의 컴파일을 완료하였습니다.

이제 컴파일 결과로 생성된 .hex 파일을 타겟 보드에 다운로드 하면 됩니다.

 

다음에는 이렇게 생성된 HEX 파일을 다운로드 하기위한 ISP 드라이버 설치 방법에 대하여 알아보도록 하겠습니다.

 

반응형

댓글