AVR-GCC的基本Makefile


7

我想制作一个用于为arduino编译c程序的makefile。我对make有点熟悉,但从未将其与avr-gcc一起使用。将命令放在makefile中的最简单方法是什么?

$ avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c
$ avr-gcc -mmcu=atmega328p led.o -o led
$ avr-objcopy -O ihex -R .eeprom led led.hex
$ avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex

由于这是一个Arduino论坛,因此从进行编译-I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standard和链接在政治上更加正确libcore.a。:-)
埃德加·博内

Answers:


5

与使用Make和任何其他形式的GCC一样。只需相应地设置CC变量和CFLAGS变量即可正常运行。

例如,我只是把它敲了一下:

CC=avr-gcc
OBJCOPY=avr-objcopy

CFLAGS=-Os -DF_CPU=16000000UL -mmcu=atmega328p
PORT=/dev/ttyACM0

led.hex: led.elf
    ${OBJCOPY} -O ihex -R .eeprom led.elf led.hex

led.elf: led.o
    ${CC} -o led.elf led.o

install: led.hex
    avrdude -F -V -c arduino -p ATMEGA328P -P ${PORT} -b 115200 -U flash:w:led.hex

就是说,任何自动C编译都将使用avr-gcc和CFLAGS中指定的标志来完成。默认情况下,它将使用OBJCOPY来创建十六进制文件,该文件设置为avr,它依赖于文件led.elf-因此,要获取该文件,它将运行led.elf目标,该目标将对象文件led.o与使用CC中设置的默认库。为此,它需要led.o,它会使用CC中指定的程序和CFLAGS中的标志自动进行设置。然后,您可以选择make install将运行avrdude的hex文件安装到芯片上。

您可以使其更加通用,因此可以将其复制到其他项目中并进行必要的最小更改:

BIN=led
OBJS=led.o test.o

CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS=-Os -DF_CPU=16000000UL -mmcu=atmega328p
PORT=/dev/ttyACM0

${BIN}.hex: ${BIN}.elf
    ${OBJCOPY} -O ihex -R .eeprom $< $@

${BIN}.elf: ${OBJS}
    ${CC} -o $@ $^

install: ${BIN}.hex
    avrdude -F -V -c arduino -p ATMEGA328P -P ${PORT} -b 115200 -U flash:w:$<

clean:
    rm -f ${BIN}.elf ${BIN}.hex ${OBJS}

使用“自动变量”和简单的名称替换。 BIN包含二进制文件的“基础”,OBJS包含目标文件的列表。$ @是当前目标的名称,$ <是第一个必备项的名称,$ ^是所有必备项的列表。只是改变BINOBJS适合。作为奖励,我投入了make clean删除已编译文件的工作,只剩下源代码了。


发布的makefile在顶部附近需要另一行;那说:'.PHONY:安装干净'
user3629249

@ user3629249为什么?发布的makefile可以完美运行。您只需要.PHONY即可将目标称为先决条件,而无需手动调用这些目标。
马延科

1
@Majenko最好是为实际上不是文件名的任何对象创建伪目标。如果创建一个名为install或名为clean(可能是shell脚本?)的文件,则make可能会以为它们什么Up to date也没做。
wchargin

@WChargin如果您像那样愚蠢地做某事,那您就应该不起作用。您的外壳程序脚本应该是clean.shinstall.sh如果必须,则应包含它们。
马延科

2

可以接受的答案很棒,因为它为我提供了各种调试工具的宝贵经验(avr-objdump -D成为了密友)。即,该行:

${OBJCOPY} -O ihex -R .eeprom $< $@

缺少体系结构标志,应阅读

$ {OBJCOPY} -mmcu = atmega328p -O ihex -R .eeprom $ <$ @

如果没有-mmcu体系结构标志,avr-gcc可能会猜测我们正在为8515体系结构进行编译(肯定不是),并且它会生成.elf文件,而没有用于初始化的初始指令,即,没有用于调用“ main”函数等的指令。

这会导致行为混乱,因为任何仅带有“ main”功能的简单程序(例如,闪烁)都可以正常运行,但是如果您在“ main”之前或之后定义另一个功能,则它将运行该功能并且从不调用“ main”或重新启动一直等等

我也不是特别喜欢避免验证正确的MCU类型和上载的程序,因此我主张不要使用-F和-V而是使用-v。

因此,改进后的答案可能是:

PKG=led
BIN=${PKG}
OBJS=${PKG}.o
MCU=atmega328p

CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS=-Os -DF_CPU=16000000UL -mmcu=${MCU} -Wall
PORT=/dev/ttyACM0

${BIN}.hex: ${BIN}.elf
        ${OBJCOPY} -O ihex $< $@

${BIN}.elf: ${OBJS}
        ${CC} -mmcu=${MCU} -o $@ $^

install: ${BIN}.hex
        avrdude -v -c arduino -p ${MCU} -P ${PORT} -b 115200 -U flash:w:$<

clean:
        rm -f ${BIN}.elf ${BIN}.hex ${OBJS}

您写道:“ 如果没有-mmcu体系结构标志,avr-gcc可能会猜测我们正在为8515体系结构进行编译 ”。实际上,它是avr2:“具有多达8 KiB程序存储器的“经典”设备。”
Edgar Bonet

我指的是Atmel参考资料atmel.com/webdoc/avrlibcreferencemanual / ...他们是否误解了?
罗伯特·史本德(RobertŠpendl)

也许它们的意思是AT90S8515 MCU,与它的替代产品(ATmega8515)不同,它具有avr2架构。链接到的页面可能是在“ 8515”不明确的时候编写的。而且,他们不称其为“架构”,因为它只是共享avr2架构的众多MCU之一。
Edgar Bonet
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.