Основной make-файл для avr-gcc

7

Я хотел бы сделать make-файл для компиляции c программ для Arduino. Я немного знаком с make, но никогда не использовал его с avr-gcc. Как проще всего поместить приведенные ниже команды в make-файл?

$ 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
источник
Поскольку это форум Arduino, было бы более политически правильно компилировать -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standardи связывать с ним libcore.a. :-)
Эдгар Бонет

Ответы:

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чтобы установить шестнадцатеричный файл в чип.

Вы можете сделать его еще более общим, чтобы скопировать его в другие проекты и внести минимальные необходимые изменения:

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содержит список объектных файлов. $ @ - имя текущей цели, $ <- имя первой предпосылки, а $ ^ - список всех предпосылок. Просто переоденься BINи OBJSподойдет. В качестве бонуса я добавил, make cleanчтобы удалить скомпилированные файлы и просто оставить вас с источником.

Маженко
источник
опубликованному make-файлу нужна еще одна строка вверху; что говорит: «.PHONY: установить чистый»
user3629249
@ user3629249 Почему? Makefile, как опубликовано, работает отлично. Вам нужно только .PHONY для целей, вызываемых как предварительные условия, а не целей, вызываемых вручную, каковы они есть.
Маженко
1
@Majenko Хорошей практикой является создание фиктивной цели для всего, что не является именем файла. Если вы создаете файл с именем installили файл с именем clean(сценарии оболочки, возможно?), То makeможете подумать, что они Up to dateи ничего не делают.
wchargin
@WChargin Если вы делаете что-то столь же глупое, как это, то вы заслуживаете, чтобы это не сработало. Ваши сценарии оболочки должны быть, clean.shи install.shесли вы должны их иметь.
Маженко
2

Принятый ответ великолепен, поскольку он дал мне ценный урок во всех видах инструментов отладки (avr-objdump -D стал близким другом). А именно, строка:

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

отсутствует флаг архитектуры и должен прочитать

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

Без флага архитектуры -mmcu, avr-gcc предполагает, что мы компилируем для архитектуры 8515 (определенно нет), и он создает файл .elf без начальных инструкций для инициализации, то есть без инструкций для вызова «основной» функции и т. Д.

Это приводит к путанице в поведении, так как любая простая программа (например, моргание), работающая только с «основной» функцией, работает отлично, но если вы определяете другую функцию до или после «основной», она запускает эту функцию и никогда не вызывает «главную» или перезапускает все время и т. д.

Я также не особо люблю избегать проверки правильности типа 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 КиБ».
Эдгар Бонет
Я имел в виду ссылку Atmel atmel.com/webdoc/avrlibcreferencemanual/… Они ошибаются?
Роберт Шпендл
Возможно, они имеют в виду микроконтроллер AT90S8515, который, в отличие от его замены (ATmega8515), имеет архитектуру avr2. Страница, на которую вы ссылаетесь, возможно, была написана в то время, когда «8515» не был неоднозначным. И они не называют это «архитектурой», так как это всего лишь один из многих микроконтроллеров, разделяющих архитектуру avr2.
Эдгар Бонет