-
今天有空,解释下
Winavr
中的
makefile
!
2008-10-19 16:49:21|
分类:
微控制器
|
标签:
|
字号大中小
订阅
# Hey Emacs, this is a -*- makefile -*-
#
# WinAVR Sample makefile
written by Eric B. Weddington,
J
鰎
g Wunsch, et al.
# Released to the Public Domain
# Please read the make user manual!
#
# Additional material for
this makefile was submitted by:
#
Tim Henigan
#
Peter Fleury
#
Reiner Patommel
#
Sander Pool
#
Frederik Rouleau
#
Markus Pfaff
#
#
On command line:
#
# make
all = Make software.
#
#
make clean = Clean out built project files.
#
# make coff = Convert ELF
to AVR COFF (for use with AVR Studio 3.x or
VMLAB).
#
# make extcoff =
Convert ELF to AVR Extended COFF (for use with AVR
Studio
#
4.07
or greater).
#
# make
program = Download the hex file to the device,
using avrdude.
Please
#
customize the avrdude settings below
first!
#
# make filename.s =
Just compile filename.c into the assembler code
only
#
# To rebuild project
do
#
风城少主
于
2008
年
10
月
19
日
笔
E_mail :
wyoujtg@
欢迎转载和与我交流!
今天有空,解释下
Winavr<
/p>
中的
makefile
!
注:从
―/*‖
到
―*/‖
之间的内容是我加入的
# MCU name
MCU = atmega128
/*
在
makefile
文件中定义的变量,有点类似
C
语言中的宏,它代
表了一个文本字符串;在
C
语言中,
在
编译的预处理阶段,用到宏的地方都会用宏的定义进行精确的展开,而在
makefil
e
文件执行的时候,变
量也会自动按它的值展开在所使用的位置
。既然称作变量,当然就是可改变的,这就是它与
C
语言中的宏
的不同之处。
在上面定义了一个变量
MCU
,并赋予它的初值为
atmeg
a128
。
变量的赋值,有如下三种方法:
1). MCU = atmega128
//
直接赋值
2). MCU := $$(AVR)
//
直接赋值,但有限制
3). MCU+ = atmega128
//
追加方式
讲下第二种,这句话的意思是把变量
AVR
的值赋予变量
p>
MCU
,使用一个变量时需要用
$$()
p>
,这个要
记住!
―=‖
号前有个
―
:
‖
< br>,这要求变量
AVR
要在变量
M
CU
定义之前被定义,这就是限制!
前面讲到它有点类似
C
语言中的宏,它代表了一个文本字符串,
追加方式可以理解为两个字符串连
接在一起。
这个变量的作用主要是传递
MCU
型号给编译器,好让
它选择与
MCU
型号对应头文件等。
*/
# Output
format. (can be srec, ihex, binary)
FORMAT = ihex
/*
定义一个变量
FORMAT
,
值为
p>
ihex
,
作用是选择生成的烧录文件的格
式
,
该变量可设置的值有
srec,
ihex, binary */
# Target file name (without extension).
TARGET = main
/*
定义一个变量
TARGET
,值为
ma
in
,作用是告诉编译器最终目标的名字叫什么,在这里就讲下什
么叫目标,请看下面:
foo.o: foo.c
foo.h
gcc
–
c
–
g
foo.c
foo.o
也就是目标!
foo.c
foo.h
是
foo.o
目标所依赖的
文件,如果
foo.c
与
foo.h<
/p>
当中有一个或以上文
件比
foo.o
p>
文件要新的话,就执行命令
gcc
–
c
–
g
foo.c
,注意命令必须以
Tab
键
开始!
将它一般化就如下:
target ... : prerequisites ...
command
target
是一个
目标文件,可以是中间代码文件(
Object File
),
也可以是执行文件,还可以是一个标
签(
Label
)。
prerequisites
是要生成那个
target
所需要或依赖的文件或目
标。
command
是
make
需要执行的命令(以
Tab
键开始)。
说白一点就是,
prerequisites
中如果有一个或以上的文件比
ta
rget
文件要新的话,
command
所定义
的命令就会被执行。这就是
Makefile
的规则,也就是
Makefile
中最核心的内
容。
*/
# List C source files here. (C
dependencies are automatically generated.)
SRC = app.c fun.c
/*
定义一个变量
SRC
,值为
app.c fun.c
,作用是选择需要
编译的
C
源文件
*/
# List
Assembler source files here.
# Make
them always end in a capital .S.
Files
ending in a lowercase .s
# will not be
considered source files but generated files
(assembler
# output from the compiler),
and will be deleted upon
# Even though
the DOS/Win* filesystem matches both .s and .S the
same,
# it will preserve the spelling
of the filenames, and gcc itself does
#
care about how the name is spelled on its command-
line.
ASRC =
/*
定义一个变量
ASRC
,值为空,作用
是选择需要编译的汇编源文件
*/
# Optimization level, can be [0, 1, 2,
3, s].
# 0 = turn off
optimization. s = optimize for size.
#
(Note: 3 is not always the best optimization
level. See avr-libc FAQ.)
OPT = s
/*
定义一个变量
OPT
,值为
s
,作用是选择编译优化级别,该变量可设
置的值有
0, 1, 2, 3,
s
;
这里选择
s
,也就是告诉编译器,专门优化代码的大小
*/
# Debugging format.
# Native formats for AVR-GCC's -g are
stabs [default], or dwarf-2.
# AVR
(extended) COFF requires stabs, plus an avr-
objcopy run.
DEBUG = stabs
/
*
定义一个变量
DEBUG
,值为
p>
stabs
,作用是选择调试格式,可设置的值有
< br>stabs [
缺省
],dwarf-2
;
而
COFF
调试文件要求选择
stabs
,以插入
avr-objcopy
文件运行。
*/
# List any extra
directories to look for include files here.
#
Each directory must be
seperated by a space.
EXTRAINCDIRS =
./include
/*
定义一个变量
EXTRAINCDIRS
,值为
./include
p>
,作用是设置编译器编译时搜索包含文件的路径,
可以设置多个,但
要用空格分开。
假如上面的
foo.
c
包含了
foo.h
文件,而
foo.h
文件在
foo.c
< br>所在目录的子目录
include
中,那么
EXTRAINCDIRS
设为
./inclu
de
,
如果
foo.h
文件在
foo.c
所在目录的上一级目录的另一子目录
iclude
中,
EXTRAINCD
IRS
应设为
../include
*/
# Compiler
flag to set the C Standard level.
# c89
-
# gnu89 - c89 plus GCC
extensions
# c99
- ISO C99
standard (not yet fully implemented)
#
gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
/*
p>
定义一个变量
CSTANDARD
,值为<
/p>
gnu99
,作用是选择编译器版本
*/
# Place -D
or -U options here
CDEFS =
# Place -I options here
CINCS =
/*
定义变量
p>
CDEFS
和
CINCS
< br>,值为空,作用是设置编译选项,前面命令
gcc
–
c
–
g
foo.c
中
–
c
< br>–
g
就是编译选项,下面是更多的编译选项:
*/
#
Compiler flags.
#
-g*:
generate debugging information
产生调试信息
#
-O*:
optimization
level
优化级别
#
-f...:
tuning, see
GCC manual and avr-libc documentation
#
-Wall...:
warning level
警告级别
#
-Wa,...:
tell GCC to
pass this to the assembler.
传递参数给汇编器
#
-adhlns...: create assembler listing
创建汇编列表
CFLAGS = -g$$(DEBUG)
CFLAGS
+= $$(CDEFS) $$(CINCS)
CFLAGS += -O$$(OPT)
CFLAGS += -funsigned-char -funsigned-
bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$$(<:.c=.lst)
CFLAGS += $$(patsubst
%,-I%,$$(EXTRAINCDIRS))
CFLAGS +=
$$(CSTANDARD)
/*
定义变量
< br>CFLAGS
,值为
-g$$(DEBUG)
,作用是设置编译选项,前面定义了
DEBUG =
stabs
,
所以
< br>CFLAGS
值应为
-g stabs
< br>,之后对变量
CFLAGS
进行追加,完成之后,
CFLAGS
值为综合的编
译选项!
讲下
-adhlns=$$(<:.c=.ls
t)
的意思:
<
是一个临时变量,它的
值是一些文件的列表,
<:.c=.lst
就是把
<
变
量的值中所有
.c
p>
扩展符替换为
.lst
,然后再赋予变量<
/p>
-adhlns
。
在这里并不打算细致讲解上面是什么意思
*/
# Assembler
flags.
#
-Wa,...:
tell GCC to pass this to the
assembler.
传递参数给汇编器
#
-ahlms:
create listing
创建列表
#
-gstabs:
have the assembler create line number
information; note that
#
for use in COFF files, additional
information about filenames
#
and function names needs to be present
in the assembler source
#
files -- see avr-libc docs [FIXME: not
yet described there]
#
大概就是告诉汇编器产生行号、文件名、函数名信息,因为
CO
FF
调试文件
#
要用到
ASFLAGS =
-Wa,-adhlns=$$(<:.S=.lst),-gstabs
/*
定义变量
ASFLAGS
,值为
-Wa,-adhlns=$$(<:.S=.lst),-gstabs
p>
,作用是设置汇编选项,基本和上面差
不多
*/
#Additional
libraries.
/*
额外库文件配置选项
*/
# Minimalistic printf
version
PRINTF_LIB_MIN =
-Wl,-u,vfprintf -lprintf_min
/*
< br>定义变量
PRINTF_LIB_MIN
,值为
-Wl,-u,vfprintf -lprintf_min
,作用是
设置
printf
版本为迷你版
*/
# Floating
point printf version (requires MATH_LIB = -lm
below)
PRINTF_LIB_FLOAT =
-Wl,-u,vfprintf -lprintf_flt
/*
< br>定义变量
PRINTF_LIB_FLOAT
,值为
p>
-Wl,-u,vfprintf -lprintf_flt
,作
用是设置
printf
版本为支持浮点
数版
*/
/*
上面的两个变量其实并不传给编译器,以下的是起作用的
,如果要设置
printf
版本为迷你版,只需
要
PRINTF_LIB =$$( PRINTF_LIB_MIN)
,下面空着是代表默认的标准版
*/
PRINTF_LIB =
# Minimalistic scanf version
/*
有
printf
当然也有
scanf
,下面是它的配置选项,和
printf
差不多,跳过
*/
SCANF_LIB_MIN =
-Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version
(requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf
-lscanf_flt
SCANF_LIB =
/*
下面是数学库的配置选项,定义变量
MATH_LIB
,值为<
/p>
-lm */
MATH_LIB = -lm
# External memory options
/*
下面是外扩内存的配置选项
*/
# 64 KB of
external RAM, starting after internal RAM
(ATmega128!),
# used for variables
(.data/.bss) and heap (malloc()).
/*
p>
大概就是
MCU
为
ATmega128
时
,
外扩了
64 KB
的
RA
M
,
如果你想既想用它来做数据区和堆栈区
,
又想用它来做堆区(动态内存分配),就设置
EXTME
MOPTS
为这个值
*/
#EXTMEMOPTS =
-Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after
internal RAM (ATmega128!),
# only used
for heap (malloc()).
/*
大概就是
MCU
为
ATmega128
时,外扩了
64
KB
的
RAM
,仅用它来做堆区(动态内存分配),就
设置
EXTMEMO
PTS
为这个值
*/
#EXTMEMOPTS = -Wl,--
defsym=__heap_start=0x801100,--
defsym=__heap_end=0x80ffff
/*
一般
MCU
不扩外部
RAM
,就让它空着
*/
EXTMEMOPTS =
#
Linker flags.
#
-Wl,...:
tell GCC to pass this to linker.
传给链接器
#
-Map:
create map file
建立映射文件
#
--cref:
add cross
reference to
map file
增加交叉重映射文件
/*
首先解析一下什么叫编译和链接
(
一位前辈写的
)
:
一般来
说,无论是
C
、
C++
、还是
pas
,首先要把源文件编译成中间代码文件,
在
Windows
下也就
是
.obj
文件
,
UN
IX
下是
.o
文件
,
即
Object File
,
这个动作叫
做编译
(
compile
)
。
然后再把大量的
Object
File
合成执行文件,这个动作叫作链接(
link
)。
编译时,编译器需要的是语法的
正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编
译器头文件的所在位置
(头文件中应该只是声明,而定义应该放在
C/C++
文件中)
,只要所有的语法正确,
编译器就可以
编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(
O
文件或是
OBJ
文件)。
链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(<
/p>
O
文件或是
OBJ
文
件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标
文件(
Object File
),
在
大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文
件名
,
这对于编译很不方便
,
所以
,
我们要给中间目标文件打个
包
,
在
Windows
下这种包叫
―
库文件
(
‖
Library
File)
,也就是
.lib
p>
文件,在
UNIX
下,是
< br>Archive File
,也就是
.a
文件。
总结一下,源文件首先会生成
中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器
只检测程序语法
p>
,
和函数
、
变量是
否被声明
。
如果函数未被声明
,
编译器会给出一个警告
,
但可以生成
Object
File
。而在链接程序时,链
接器会在所有的
Object
File
中找寻函数的实现,如果找不到,那到就会报链接
错误码(
L
inker
Error
),在
VC<
/p>
下,这种错误一般是:
Link
200
1
错误,意思说是说,链接器未能找到函
数的实现。你需要指定
函数的
Object File.
*/
LDFLAGS = -Wl,-Map=$$(TARGET).map,--cref
LDFLAGS += $$(EXTMEMOPTS)
LDFLAGS += $$(PRINTF_LIB) $$(SCANF_LIB)
$$(MATH_LIB)
/*
定义变量
LDFLAGS
,作用是设置链接选项,传给链接器,可以看出链接跟内存分布和库有
很大关
系
*/
# Programming support
using avrdude. Settings and variables.
/*
以下是使用
avrdude
p>
调试器的编程支持,一般用不上,略过
*/
# Programming hardware:
alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12
stk200 stk500
#
# Type:
avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER =
stk500
# com1 = serial
port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = com1
#
programmer connected to serial device
AVRDUDE_WRITE_FLASH = -U
flash:w:$$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U
eeprom:w:$$(TARGET).eep
# Uncomment the following if you want
avrdude's erase cycle counter.
# Note
that this counter needs to be initialized first
using -Yn,
# see avrdude manual.
-
-
-
-
-
-
-
-
-
上一篇:经典情歌对唱120首(KTV专用)
下一篇:适合两个人唱的120首歌