Makefile de base pour avr-gcc

7

Je voudrais faire un makefile pour compiler des programmes c pour l'arduino. Je suis un peu familier avec make mais je ne l'ai jamais utilisé avec avr-gcc. Quelle est la façon la plus simple de mettre les commandes ci-dessous dans un 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
connorwstein
la source
Comme il s'agit d'un forum Arduino, il serait plus politiquement correct de compiler avec -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standardet d'établir un lien avec libcore.a. :-)
Edgar Bonet

Réponses:

5

Ce n'est pas différent de travailler avec Make et toute autre forme de GCC. Réglez simplement votre variable CC et votre variable CFLAGS en conséquence et travaillez comme d'habitude.

Par exemple, je viens de faire tomber celui-ci:

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

Cela signifie que toute compilation C automatique se fera avec avr-gcc et les indicateurs spécifiés dans CFLAGS. Par défaut, il créera le fichier hex en utilisant OBJCOPY, qui est défini sur celui d'avril, qui s'appuie sur le fichier led.elf - donc pour obtenir ce fichier, il exécute la cible led.elf, qui relie le fichier objet led.o avec les bibliothèques par défaut utilisant tout ce qui a été défini dans CC. Pour ce faire, il a besoin de led.o, et il le fait automatiquement en utilisant le programme spécifié dans CC et les drapeaux dans CFLAGS. Vous pouvez ensuite éventuellement à make installqui s'exécutera avrdudepour installer le fichier hexadécimal dans la puce.

Vous pouvez le rendre encore plus générique pour pouvoir le copier dans d'autres projets et apporter les modifications minimales nécessaires:

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}

Cela utilise des "variables automatiques" et un simple remplacement de nom. BINcontient la "base" de vos fichiers binaires, OBJScontient la liste des fichiers objets. $ @ est le nom de la cible actuelle, $ <est le nom du premier prérequis et $ ^ est la liste de tous les prérequis. Il suffit de changer BINet OBJSde convenir. En bonus, j'ai ajouté make cleanpour supprimer les fichiers compilés et vous laisser la source.

Majenko
la source
le makefile affiché a besoin d'une autre ligne vers le haut; qui dit: '.PHONY: install clean'
user3629249
@ user3629249 Pourquoi? Le makefile tel que publié fonctionne parfaitement. Vous n'avez besoin de .PHONY que pour les cibles appelées comme prérequis, et non pour les cibles appelées manuellement.
Majenko
1
@Majenko Il est recommandé de créer une cible bidon pour tout ce qui n'est pas réellement un nom de fichier. Si vous créez un fichier appelé installou un fichier appelé clean(scripts shell, peut-être?), Vous makepouvez penser qu'ils le sont Up to dateet ne rien faire.
wchargin
@WChargin Si vous faites quelque chose d'aussi stupide que cela, alors vous méritez que cela ne fonctionne pas. Vos scripts shell devraient l'être clean.shet install.shsi vous devez les avoir.
Majenko
2

La réponse acceptée est excellente car elle m'a donné une leçon précieuse sur toutes sortes d'outils de débogage (avr-objdump -D est devenu un ami proche). À savoir, la ligne:

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

manque le drapeau d'architecture et devrait lire

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

Sans l'indicateur d'architecture -mmcu, avr-gcc suppose que nous compilons pour l'architecture 8515 (certainement pas) et il produit le fichier .elf sans instructions initiales pour l'initialisation, c'est-à-dire sans instructions pour appeler la fonction "principale", etc.

Il en résulte un comportement déroutant car tout programme simple (par exemple clignotant) avec uniquement la fonction "principale" fonctionne parfaitement, mais si vous définissez une autre fonction avant ou après le "principal", il exécute cette fonction et n'appelle jamais "principal" ou il redémarre tout le temps, etc.

Je ne suis pas non plus un fan particulier d'éviter la vérification du type de MCU correct et du programme téléchargé, donc je recommanderais de ne pas utiliser -F et -V et d'utiliser -v à la place.

Ainsi, la réponse améliorée pourrait être:

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
la source
Vous avez écrit: " Sans l'indicateur d'architecture -mmcu, avr-gcc suppose que nous compilons pour l'architecture 8515 ". En fait, c'est avr2: «Appareils« classiques »avec jusqu'à 8 Ko de mémoire de programme.»
Edgar Bonet
Je faisais référence à la référence Atmel atmel.com/webdoc/avrlibcreferencemanual/… Se trompent -ils?
Robert Špendl
Peut-être qu'il s'agit du MCU AT90S8515 qui, contrairement à son remplacement (ATmega8515), a une architecture avr2. La page vers laquelle vous créez un lien a peut-être été écrite à une époque où «8515» n'était pas ambigu. Et ils ne l'appellent pas une «architecture», car ce n'est qu'un des nombreux microcontrôleurs partageant l'architecture avr2.
Edgar Bonet