Grundlegendes Makefile für avr-gcc

7

Ich möchte ein Makefile zum Kompilieren von c-Programmen für das Arduino erstellen. Ich bin mit make etwas vertraut, habe es aber noch nie mit avr-gcc verwendet. Was ist der einfachste Weg, die folgenden Befehle in ein Makefile einzufügen?

$ 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
connorwstein
quelle
Da dies ein Arduino-Forum ist, wäre es politisch korrekter, mit zu kompilieren -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standardund zu verlinken libcore.a. :-)
Edgar Bonet

Antworten:

5

Es ist nicht anders als mit Make und jeder anderen Form von GCC zu arbeiten. Stellen Sie einfach Ihre CC-Variable und CFLAGS-Variable entsprechend ein und arbeiten Sie wie gewohnt.

Zum Beispiel habe ich gerade diesen umgehauen:

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

Das heißt, dass jede automatische C-Kompilierung mit avr-gcc und den in CFLAGS angegebenen Flags durchgeführt wird. Standardmäßig wird die Hex-Datei mit OBJCOPY erstellt, das auf avr gesetzt ist und auf der Datei led.elf basiert. Um diese Datei zu erhalten, wird das Ziel led.elf ausgeführt, mit dem die Objektdatei led.o verknüpft ist Die Standardbibliotheken verwenden alles, was in CC festgelegt wurde. Dazu benötigt es led.o und macht dies automatisch mit dem in CC angegebenen Programm und den Flags in CFLAGS. Sie können dann optional make installausführen avrdude, um die Hex-Datei auf dem Chip zu installieren.

Sie können es noch allgemeiner gestalten, um es in andere Projekte zu kopieren und die erforderlichen Mindeständerungen vorzunehmen:

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}

Das nutzt "automatische Variablen" und einfache Namensersetzung. BINenthält die "Basis" Ihrer Binärdateien, OBJSenthält die Liste der Objektdateien. $ @ ist der Name des aktuellen Ziels, $ <ist der Name der ersten Voraussetzung und $ ^ ist die Liste aller Voraussetzungen. Einfach umziehen BINund OBJSanpassen. Als Bonus habe ich eingeworfen make clean, um die kompilierten Dateien zu entfernen und Sie einfach mit der Quelle zu belassen.

Majenko
quelle
Das veröffentlichte Makefile benötigt eine weitere Zeile oben. das sagt: '.PHONY: install clean'
user3629249
@ user3629249 Warum? Das veröffentlichte Makefile funktioniert einwandfrei. Sie benötigen .PHONY nur für Ziele, die als Voraussetzungen bezeichnet werden, nicht für manuell aufgerufene Ziele.
Majenko
1
@Majenko Es wird empfohlen, ein falsches Ziel für alles zu erstellen, was eigentlich kein Dateiname ist. Wenn Sie eine aufgerufene Datei installoder eine aufgerufene Datei erstellen clean(vielleicht Shell-Skripte?), makeDenken Sie möglicherweise, dass dies der Fall ist, Up to dateund tun Sie nichts.
Charchargin
@WChargin Wenn Sie so etwas Dummes tun, dann verdienen Sie es, dass es nicht funktioniert. Ihre Shell-Skripte sollten sein clean.shund install.shwenn Sie sie haben müssen.
Majenko
2

Die akzeptierte Antwort ist großartig, da sie mir eine wertvolle Lektion in allen Arten von Debugging-Tools erteilt hat (avr-objdump -D ist ein enger Freund geworden). Die Zeile:

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

fehlt das Architekturflag und sollte lesen

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

Ohne das Architektur-Flag -mmcu schätzt avr-gcc, dass wir für die 8515-Architektur kompilieren (definitiv nicht), und es erzeugt die .elf-Datei ohne anfängliche Anweisungen zum Initialisieren, dh ohne Anweisungen zum Aufrufen der "Haupt" -Funktion usw.

Dies führt zu einem verwirrenden Verhalten, da jedes einfache Programm (z. B. Blinken) mit nur der "main" -Funktion einwandfrei funktioniert. Wenn Sie jedoch vor oder nach dem "main" eine andere Funktion definieren, wird diese Funktion ausgeführt und niemals "main" aufgerufen oder neu gestartet die ganze Zeit usw.

Ich bin auch kein besonderer Fan davon, die Überprüfung des korrekten MCU-Typs und des hochgeladenen Programms zu vermeiden, daher würde ich empfehlen, nicht -F und -V und stattdessen -v zu verwenden.

Die verbesserte Antwort könnte also lauten:

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}
Robert Špendl
quelle
Sie haben geschrieben: „ Ohne das Flag -mmcu-Architektur schätzt avr-gcc, dass wir für die 8515-Architektur kompilieren. “ Eigentlich ist es avr2: "Klassische Geräte mit bis zu 8 KB Programmspeicher."
Edgar Bonet
Ich bezog mich auf die Atmel-Referenz atmel.com/webdoc/avrlibcreferencemanual/… Sind sie falsch?
Robert Špendl
Vielleicht meinen sie die AT90S8515-MCU, die im Gegensatz zu ihrem Ersatz (ATmega8515) eine avr2-Architektur hat. Die Seite, auf die Sie verlinken, wurde möglicherweise zu einer Zeit geschrieben, als „8515“ nicht mehrdeutig war. Und sie nennen es keine "Architektur", da es nur eine von vielen MCUs ist, die die avr2-Architektur gemeinsam nutzen.
Edgar Bonet