Создание Makefile для AVR

Эта статья посвящена созданию Make-файла с помощью утилиты Mfile. Полученный Makefile может быть использован для сборки проекта под микроконтроллеры семейства AVR с использованием компилятора gcc.

GCC благодаря проекту AVR-GCC (и avr-libc в частности) отлично подходит для разработки под микроконтроллеры семейства AVR. Поддержка AVR-GCC (в лице WinAVR) есть и в фирменной IDE AVR Studio, имеющей встроенные средства для сборки проектов и генерации make-файлов. Разработчики, использующие ОС Linux, могут выбрать в качестве среды разработки Eclipse, установив к нему плагин AVR Eclipse. Eclipse имеет собственную реализацию проектов. Собственно, плагин AVR Eclipse добавляет возможность использовать для сборки AVR-GCС. При этом, во время сборки Eclipse-проекта происходит генерация временного Make-файла, и, затем, его сборка с помощью make. Кроме добавления поддержки инструментария сборки, плагин AVR Eclipse позволяет автоматизировать процесс прошивки микроконтроллера.

Другой путь. Всегда есть другой путь.
— Мастер Ключей

Такой подход не всегда приемлем. Даже если вы используете Eclipse, вам может не понравится непрозрачность, возникающая при сборке проекта встроенными средствами. Особенно остро вы ощутите это, когда начнёте заниматься экспериментами с флагами оптимизации GCC (а вы этим непременно займётесь, так как скомпилированный без оптимизации образ получается непозволительно большим для прошивки в микроконтроллер). Кроме того, Eclipse, возможно, и является неплохой IDE для Java, но, когда речь заходит о микроконтроллерах, использование этого монстра видится избыточным. И уж тем более, Eclipse не является лучшим редактором кода. Так что если вы одумаетесь, и решите использовать для программирования VIM, вам придётся искать подходящие средства сборки проекта.

Все начинается с выбора.
— Морфеус

На первом месте среди инструментов сборки, конечно, стоит GNU Make. Всё, что вам надо для его использования в своём проекте — это так называемый Makefile, представляющий из себя особый скрипт, в котором описаны команды, используемые для компиляции и других рутинных операций, которые могут потребоваться. На тему использования GNU Make написано довольно много статей (в том числе и на русском языке), часть из которых без труда можно найти в интернете (начать поиск можно хотя бы со страницы в Wikipedia). Если вы не знакомы со структурой и синтаксисом Makefile, можете начать ознакомление со следующей весьма лаконичной статьи: http://www.linux.org.ru/books/make.html.

К счастью (особенно, если принять во внимание, что многие, кто только начинают своё знакомство с микроконтроллерами, вовсе не являются гуру программирования), можно обойтись и без сочинения Makefile «с нуля»: всё уже написано до нас. Постаравшись, мы можете найти множество заготовок Make-файлов, в том числе и заточенных специально для AVR (принципиальные их отличия заканчиваются на том, что вместо цели install, есть цель program 🙂 ). Многие из них снабжены развёрнутыми комментариями (порой и на русском языке), делающими процесс приспособления их к своим нуждам предельно простым.

На этом можно было бы остановиться, но мы пойдём несколько другим путём. Специально для генерации Makefile для проектов под AVR-GCC, была создана небольшая утилита Mfile, скачать которую можно по следующей ссылке: http://www.sax.de/~joerg/mfile/mfile.tar.gz. Распакуйте архив куда-нибудь (на пример, в домашний каталог; по-хорошему, таким вещам место в /opt/, но домашний каталог для начала вполне сойдёт).

user@hostname:~$ tar -xvvf mfile.tar.gz

Перейдите в каталог с вашим AVR-проектом, попытайтесь запустить скрипт с именем mfile.tcl из каталога, распакованного на предыдущем шаге.

user@hostname:~/Project/firmware$ ~/mfile/mfile.tcl
bash: /home/user/mfile/mfile.tcl: /usr/local/bin/tixwish: плохой интерпретатор: Нет такого файла или каталога

Скорее всего, у вас, как и у меня, с первого раза ничего не выйдет. Всё дело в имени интерпретатора скрипта, указанном (как это полагается) в первой строчке. К счастью, это легко исправить: попробуйте использовать wish, который есть в большинстве дистрибутивов. Для этого исправьте первую строку mfile.tcl с
#!/usr/local/bin/tixwish
на
#!/usr/bin/wish

После запуска на исполнение исправленного файла, должно появится окно с программой:

Основную часть окна программы занимает шаблон Make-файла. Меню «Makefile» позволяет изменять значения наиболее важных переменных:

Пункт меню «Main file name» позволяет задать имя главного файла проекта. Это может быть, к примеру, main.c. Имя файла следует вводить без расширения (посмотрите на содержание Makefile: введённое имя будет присвоено переменной TARGET, а в переменную SRC, отвечающую за список файлов с исходным кодом, попадёт оно же, но с добавлением расширения : SRC=$(TARGET).c). «MCU type» позволяет выбрать модель микроконтроллера из списка.

Обратите внимание на подсветку текста, изменяемого с помощью меню. Все параметры, естественно, доступны для изменения и после генерации Makefile, путём простой правки в текстовом редакторе.

Кроме сборки, этот Makefile будет отвечать и за прошивку скомпилированного hex-файла в микроконтроллер. Чтобы использовать эту возможность, измените соответствующим образом значения в пунктах «Programmer» и «Port». Остальные параметры чаще всего можно оставить «как есть».

По окончании конфигурации, сохраните полученный Makefile в каталог со своим проектом. Осталось только руками немного довести его под свои требования. Откройте Makefile в текстовом редакторе.

Если вы работаете с достаточно крупным проектом, он, скорее всего, состоит из нескольких *.c файлов. Добавьте их имена к переменной SRC (строка 11), просто дописав через отступ после $(TARGET).c

11
SRC = $(TARGET).c my_lib.c another_file.c

Кроме этого, вам может потребоваться передача через параметры компилятора некоторых макросов препроцессора: на пример, таким образом принято задавать F_CPU, хранящий частоту работы микроконтроллера. Разработчики скрипта позаботились о нас, оставив переменную CDEFS (строка 31). Задание макросов осуществляется с помощью ключа -D в строке параметров gcc. Сама строка параметров собирается по кусочкам в переменной CFLAGS(строка 41). И так, зададим частоту работы ядра микроконтроллера:

31
CDEFS = -D F_CPU=20000000

Ещё одной переменной, которую вам, возможно, захочется изменить, является CTUNING, отвечающая за различные флаги оптимизации (полезная статья по их выбору в случае программирования под AVR может быть найдена тут. В случае экспериментов с флагами оптимизации, очень удобно иметь возможность быстро включать и отключать определённые из них (так как эффект от них зачастую можно установить только опытным путём). Для этого будем формировать переменную не сразу, а последовательно прибавляя к ней нужные флаги. К примеру, неплохой результат может даль использование следующих флагов:

39
40
41
42
43
44
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CTUNING += --param inline-call-cost=2 -finline-limit=3 -fno-inline-small-functions 
CTUNING += -ffunction-sections -fdata-sections 
CTUNING += -ffreestanding
CTUNING += -fno-tree-scev-cprop
CTUNING += -fno-split-wide-types

Чтобы исключить какой-либо из них, просто закомментируйте нужную строку.
Ещё одно небольшое замечание: в сгенерированном Makefile переменная CTUNING нигде не используется. Для того, чтобы её содержимое было добавлено к флагам компилятора, надо просто добавить её к переменной CFLAGS:

47
48
CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CFLAGS += $(CTUNING)

В целом, Makefile готов, давайте посмотрим, что он умеет.
Команда make (или make all) из каталога с проектом выполняет сборку hex файла, пригодного для прошивки в микроконтроллер с помощью avrdude. Для автоматизации прошивки служит команда «make program». «make clean» производит чистку директории проекта от результатов предыдущих сборок.

Ничто не мешает вам определить собственные цели сборки для автоматизации регулярно выполняемых операций. На пример, часто возникает желание узнать о размере получившегося файла с прошивкой (для этого используется команда avr-size). Опишем новую цель size. Разработчики шаблона Makefile постарались, так что он уже содержит переменную SIZE (строка 133), содержащую имя программы, используемой для вывода размера (avr-size). Очевидно, результат будет следующим (просто добавьте эти строчки куда-нибудь в конец, обращая внимание на символ табуляции в начале второй строки):

223
224
size:
	$(SIZE) -C --mcu=$(MCU) $(TARGET).elf

Так как эта цель не генерирует никаких файлов (или «фальшивая»), надо добавить её в .PHONY во избежание конфликтов. Просто допишите clean в конце строки, начинающейся с .PHONY (обычно располагается в конце файла).

Теперь команда make size будет выводить статистику по использованию ресурсов микроконтроллера:

user@hostname:~/Project/firmware$ make size
avr-size -C --mcu=atmega48 main.elf
AVR Memory Usage
----------------
Device: atmega48
 
Program:    2136 bytes (52.1% Full)
(.text + .data + .bootloader)
 
Data:         49 bytes (9.6% Full)
(.data + .bss + .noinit)
 
EEPROM:       64 bytes (25.0% Full)
(.eeprom)

На этом мой рассказ окончен. Мне остаётся только пожелать вам удачи в создании Makefile, и, конечно, творческих успехов в собственных проектах!

Добавить комментарий