Еще один шаблон проекта под STM32 на gcc

Вдруг пригодиться кому… Ну и критику гуру хотелось бы услышать.


Наиболее интересный момент

# Компиляция
#------------------------------------------------------------------------------- 
%.o: %.c
	@$(CC) $(CFLAGS) -MD -c $< -o $@


# Сгенерированные gcc зависимости
#-------------------------------------------------------------------------------
include $(wildcart *.d)

Ключ -MD заставляет генерировать gcc файлы зависимостей. Подсмотрел здесь.
Архив с проектом в аттаче.

Собственно Makefile

# Имя проекта
#-------------------------------------------------------------------------------
TARGET  = template

# Используемые модули библиотеки периферии
#-------------------------------------------------------------------------------
# PERIPHDRIVERS += stm32f10x_adc
# PERIPHDRIVERS += stm32f10x_bkp
# PERIPHDRIVERS += stm32f10x_can
# PERIPHDRIVERS += stm32f10x_cec
# PERIPHDRIVERS += stm32f10x_crc
# PERIPHDRIVERS += stm32f10x_dbgmcu
# PERIPHDRIVERS += stm32f10x_exti
# PERIPHDRIVERS += stm32f10x_flash
# PERIPHDRIVERS += stm32f10x_fsmc
PERIPHDRIVERS += stm32f10x_gpio
# PERIPHDRIVERS += stm32f10x_i2c
# PERIPHDRIVERS += stm32f10x_iwdg
# PERIPHDRIVERS += stm32f10x_pwr
PERIPHDRIVERS += stm32f10x_rcc
# PERIPHDRIVERS += stm32f10x_rtc
# PERIPHDRIVERS += stm32f10x_sdio
# PERIPHDRIVERS += stm32f10x_spi
# PERIPHDRIVERS += stm32f10x_tim
# PERIPHDRIVERS += stm32f10x_usart
# PERIPHDRIVERS += stm32f10x_wwdg
# PERIPHDRIVERS += misc.c

# Дефайны
#-------------------------------------------------------------------------------
DEFINES += USE_STDPERIPH_DRIVER
DEFINES += STM32F10X_MD_VL

DEFINES += GCC_ARMCM3
DEFINES += VECT_TAB_FLASH

# Инструменты
#-------------------------------------------------------------------------------
AS = arm-none-eabi-gcc
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
CP = arm-none-eabi-objcopy
SZ = arm-none-eabi-size
RM = rm

# Пути к CMSIS, StdPeriph Lib
#-------------------------------------------------------------------------------
CMSIS_PATH         = cmsis
STDPERIPH_INC_PATH = stdperiph/inc
STDPERIPH_SRC_PATH = stdperiph/src

# startup файл
#-------------------------------------------------------------------------------
STARTUP = startup/startup_stm32f10x_md_vl.s

# Пути поиска исходных файлов
#-------------------------------------------------------------------------------
SOURCEDIRS := src
SOURCEDIRS += $(CMSIS_PATH)

# Пути поиска хидеров
#-------------------------------------------------------------------------------
INCLUDES += .
INCLUDES += $(SOURCEDIRS) 
INCLUDES += $(CMSIS_PATH)
INCLUDES += $(STDPERIPH_INC_PATH)

# Библиотеки
#-------------------------------------------------------------------------------
LIBPATH +=
LIBS    +=

# Настройки компилятора
#-------------------------------------------------------------------------------
CFLAGS += -mthumb -mcpu=cortex-m3 # архитектура и система комманд
CFLAGS += -std=gnu99              # стандарт языка С
CFLAGS += -Wall -pedantic         # Выводить все предупреждения
CFLAGS += -Os                     # Оптимизация
CFLAGS += -ggdb                   # Генерировать отладочную информацию для gdb
CFLAGS += -fno-builtin

CFLAGS += $(addprefix -I, $(INCLUDES))
CFLAGS += $(addprefix -D, $(DEFINES))

# Скрипт линкера
#-------------------------------------------------------------------------------
LDSCR_PATH = ld-scripts
LDSCRIPT   = stm32f100rb.ld

# Настройки линкера
#-------------------------------------------------------------------------------
LDFLAGS += -nostartfiles
LDFLAGS += -L$(LDSCR_PATH)
LDFLAGS += -T$(LDSCR_PATH)/$(LDSCRIPT)
LDFLAGS += $(addprefix -L, $(LIBPATH))
LDFLAGS += $(LIBS)

# Настройки ассемблера
#-------------------------------------------------------------------------------
AFLAGS += -ahls -mapcs-32

# Список объектных файлов
#-------------------------------------------------------------------------------
OBJS += $(patsubst %.c, %.o, $(wildcard  $(addsuffix /*.c, $(SOURCEDIRS))))
OBJS += $(addprefix $(STDPERIPH_SRC_PATH)/, $(addsuffix .o, $(PERIPHDRIVERS)))
OBJS += $(patsubst %.s, %.o, $(STARTUP))

# Пути поиска make
#-------------------------------------------------------------------------------
VPATH := $(SOURCEDIRS)

# Список файлов к удалению командой "make clean"
#-------------------------------------------------------------------------------
TOREMOVE += *.elf *.hex
TOREMOVE += $(addsuffix /*.o, $(SOURCEDIRS))
TOREMOVE += $(addsuffix /*.d, $(SOURCEDIRS))
TOREMOVE += $(STDPERIPH_SRC_PATH)/*.o
TOREMOVE += $(patsubst %.s, %.o, $(STARTUP))
TOREMOVE += $(TARGET)

# Собрать все
#-------------------------------------------------------------------------------
all: $(TARGET).hex size	

# Очистка
#-------------------------------------------------------------------------------
clean:
	@$(RM) -f $(TOREMOVE)  

# Создание .hex файла
#-------------------------------------------------------------------------------
$(TARGET).hex: $(TARGET).elf
	@$(CP) -Oihex $(TARGET).elf $(TARGET).hex
	
# Показываем размер
#-------------------------------------------------------------------------------
size:
	@echo "---------------------------------------------------"
	@$(SZ) $(TARGET).elf

# Линковка
#------------------------------------------------------------------------------- 
$(TARGET).elf: $(OBJS)
	@$(LD) $(LDFLAGS) $^ -o $@

# Компиляция
#------------------------------------------------------------------------------- 
%.o: %.c
	@$(CC) $(CFLAGS) -MD -c $< -o $@
	
%.o: %.s
	@$(AS) $(AFLAGS) -c $< -o $@

# Сгенерированные gcc зависимости
#-------------------------------------------------------------------------------
include $(wildcart *.d)
  • +4
  • 11 апреля 2012, 13:24
  • storm_ua
  • 1
Файлы в топике: stm32-gcc-template.zip

Комментарии (31)

RSS свернуть / развернуть
А не могли бы вы написать какую-нибудь вводную статью по этим make-файлам?

Меня как новичка интересует не взгляд гуру, который может детально описать каждую мелочь, а более общее описание, на пальцах буквально. Что значат все эти $, %, @ и почему в такой последовательности. Ну или ткните меня в какую-нибудь готовую статью, если есть.
0
Краткий туториал с первой страницы гугла
Но новичку я бы рекомендовал использовать eclipse для stm32
0
Согласен, я немного неправильно сформулировал свою просьбу. Статей, подобных той что по ссылке, немало, но как правило они сводятся к виду «вот смотрите это комментарий, это таргет, это команда, а все остальное — в офф.документации».

Думаю документацию могут почитать все, она доступна. Поэтому меня больше интересуют не сами возможные команды и параметры, а практики их использования. Вот например для DVCS mercurial есть очень подробная документация, с примерами. Но найти хороший workflow для работы с этой системой на порядок сложнее.

Грубо говоря, вопрос не «как» а «почему»
0
GCC полное руководство
Глава 14. Утилита Make
0
Статью не напишу, ибо чукча скорее читатель чем писатель =)

Вот пара ссылок:
Перевод Makefile Mini HOWTO
Как устроен Makefile и что это такое?
GNU Make
Эффективное использование GNU Make
0
Где карта, Билли содержимое линкер скрипта?
И как, поправив одну строчку, сменить используемый МК.
Ещё, советую отказаться от явного указания используемой перифирии, а собрать всю библиотеку, после чего собирать всё с функцией исключения неиспользованных функций.
0
О, дельный совет… Я думал раз линкуется библиотека, так линкуется полностью…
0
Если бы либы линковались полностью, в них не было бы никакого смысла.
0
Библиотеки почти всегда линкуются динамически. Реже — полностью. -ffunction-sections используют редко — уменьшает скорость компеляции. Советую заглянуть как нибуть в скипты сборки вашего дистрибутива…
0
Я, как бы, в курсе :)
0
смотри в сторону -ffunction-sections
0
Благодарю за пинок.
0
Я думал раз линкуется библиотека, так линкуется полностью…
Именно такой эффект даёт несогласованное в Delphi сочетание RTTI, VCL и оптимизатора. Один из больших минусов Delphi — гиганские exe-шники.
0
Скорее это не минус Delphi, а минус собственно VCL. В Delphi вместо стандартной VCL можно использовать сторонние библиотеки KOL и MCK, которые и дадут маленький размер exe-шника. Но, на мой взгляд, в наше время маленький размер программы уже не особо важен (конечно, если это не десятки и сотни Мб для простой программы).
0
либо exe на пару сотен кило и dll с тулкитом на 10-15 метров весом
В этом плане в пингвинах все умно сдеалано ;). Там .so с библиотекой — одна на всю систему будет. Ну а в виндовсе все как обычно…
0
Причина не в виндовсе, а в том, что в линухе эта библиотека в 95% случаев уже будет установлена в системе, а в оставшихся 5% ее доустановит менеджер пакетов.
Под виндой Qt/GTK/wx относительно редки и рассчитывать на их наличие в системе не приходится. На менеджер пакетов рассчитывать тоже не приходится, так как его нету. Приходится тащить библиотеку с собой.
Ну а раз библиотека у всех с собой — ее незачем класть в публичное место. Можно положить рядом с собой. Тем более сей библиотеки версий куча, и не факт что с другой версией будет работать. У того же линукса тоже в библиотеках запросто могут лежать libqt-2.0.so, libqt-3.0.so (вроде принцип именования там немного другой, но похожий, а конкретно я не помню).

А вот с библиотеками от M$, вроде ActiveX контролов и иже с ними — как раз дела обстоят примерно как в линуксе.
0
Во первых, я бы не назвал «гигантским» ехе файл на 400кб. Достаточно взглянуть на любой другой GUI-тулкит (wxWidgets, Qt, LCL...) — размеры ехе начинаются от 4МБ (либо exe на пару сотен кило и dll с тулкитом на 10-15 метров весом).
Во вторых, смарт-линкер в дельфи работает отлично. И не прикручен через костыли, как в GCC. Просто VCL специально написана так, чтобы код контролов компилировался полностью (иначе создается из формы кнопка и тут опа — а половины ее кода нету).
В третьих, главная причина размера ехе-файлов дельфи — это не RTTI и даже не VCL, а DFM. Формы в Delphi создаются динамически по DFM-файлу (он лежит в ресурсах exe), поэтому в ехе компилируется весь код всех контролов, которые могут встретиться в DFM. Зато VCL позволяет загружать формы в реалтайме и откуда угодно, подменять ресурсы форм (на этом основан встроенный механизм локализации приложений, который правда никто не использует) и так далее.

Все эти KOL и иже с ними основаны именно на замене десериализатора форм на код вида
Form1:=TForm1.Create;
Form1.Left:=100;
Form1.Width:=640;
...
Form1.Button1:=TButton.Create;
Form1.Button1.Left:=10;
Form1.Button1.Top:=10;
Form1.Button1.Width=75;
...

В VCL же достаточно нарисовать в дизайнере форму и загрузить ее вызовом Application.CreateForm(TForm1, Form1). Из альтернатив только KOL/MCK предоставляет автоматический генератор этого кода — библиотеку MCK. Но у нее свои минусы (оно прикручено к дельфи через костыли и регулярно глючит). Кроме того, все эти библиотеки как правило не обладают ни функционалом, ни гибкостью VCL.
0
Эх, всё это правильные опровдания, конечно.
Хоть я Дельфю и критикую, но 95% моих PC программ — на ней, и 95% из них на VCL.
А на ассемблере только 1%. Остальное С++.
Просто, в душе понимаешь, что в твой ехе-шник напихали много лишнего, что программа никогда не будет использовать. А душа стремится к совершенству. :)
0
А с чего ты взял, что оно не используется? То, что на API можно написать программу, которая так же выглядит и работает и весит в 10 раз меньше (правда, такого соотношения размеров можно получить только на мелких программах — строк до тысячи) не значит, что остальные 90% кода не используются.

Практически никто не знает дельфи и как он внутри устроен, но все кричат про гигантские exe и неиспользуемый код.
0
Код-то видно. Заходишь в отладку, включаешь окно CPU. Смотришь на дизасемблер. Весь код методов классов, которые я не использовал — откомпилирован. А там их целая помойка, замаешся листать. Ставь точки останова — они никогда не сработают. Я ставил, проверял. :)
Да и просто-же, вот как расчитывают КПД? Энергии вкочали — ВО! Полезной работы — тююю. И не надо разбираться как внутри установка устроена.
0
Если класс включен — значит, он тем или иным образом может использоваться.
В частности, классы VCL включаются из-за того, что они используются в автовызываемой процедуре Register. Будут ли они использованы для чего-то еще — зависит уже не от кода программы, а от внешних данных.
Да и просто-же, вот как расчитывают КПД? Энергии вкочали — ВО! Полезной работы — тююю. И не надо разбираться как внутри установка устроена.
Вот только энергия и работа измеряются в одних единицах, в отличие от программ, так что сравнение не очень-то корректно. Этот размер расходуется на удобство программирования. Не нравится — от VCL всегда можно отказаться. Правда, писать будет сложнее и не факт что ты вообще закончишь прогу, да и ошибок тем больше, чем сложнее программу писать.
0
Согласен, это не сравнение. Просто пример, когда можно оценить интегральный общий параметр без анализа системы.
Чёто мы зацепились. Давлю по тормозам. :)
0
Ну собсна основное возражение было к
Именно такой эффект даёт несогласованное в Delphi сочетание RTTI, VCL и оптимизатора
Поскольку на самом деле VCL так написана, что выкидывать при линковке там нечего — на момент компиляции предсказать какой код будет использоваться невозможно.
0
И да, если отказаться от GUI-тулкита, то можно писать на WinAPI мелкие exe — от 16 килобайт (это размер CRT — базовой библиотеки поддержки языка). Если CRT модифицировать — можно создавать exe от пары килобайт (правда, половина фишек языка отвалится — вроде строк, исключений, стандартного ввода-вывода и прочего).
0
Друзья, тут про STM32, а не про дельфи, и другие GUI.
Мне вот тоже полностью не понятно как MAKE файлом пользоватся, Eclipse тож, не понятен…
Да ещё новый CMSIS вышел… Где вот STARTUP = startup/startup_stm32f10x_md_vl.s это уже не найти, так просто.
0
Хороший шаблон, упростил свой посматривая в него.
0
Я бы добавил еще информативности при сборке/очистке проекта
# Собрать все
#-------------------------------------------------------------------------------
all: start $(TARGET).hex size stop	

# Очистка
#-------------------------------------------------------------------------------
clean:	start rmfile stop	

# Старт
#-------------------------------------------------------------------------------
start:
	@echo "Start ---------------------------------------------------------------"

# Стоп
#-------------------------------------------------------------------------------
stop:
	@echo "Stop ----------------------------------------------------------------"

# Удаление
#-------------------------------------------------------------------------------
rmfile:
	@echo $(RM) -f $(TOREMOVE)  
	@$(RM) -f $(TOREMOVE)  

# Создание .hex файла
#-------------------------------------------------------------------------------
$(TARGET).hex: $(TARGET).elf
	@echo "Create HEX =>" $(CP) -Oihex $(TARGET).elf $(TARGET).hex
	@$(CP) -Oihex $(TARGET).elf $(TARGET).hex
	
# Показываем размер
#-------------------------------------------------------------------------------
size:
	@echo "Size ----------------------------------------------------------------"
	@$(SZ) $(TARGET).elf

# Линковка
#------------------------------------------------------------------------------- 
$(TARGET).elf: $(OBJS)
	@echo "Linking =>" $^ 
	@$(LD) $(LDFLAGS) $^ -o $@

# Компиляция
#------------------------------------------------------------------------------- 
%.o: %.c
	@echo "Compilling C source =>" $< 
	@$(CC) $(CFLAGS) -MD -c $< -o $@
	
%.o: %.s
	@echo "Compilling ASM source =>" $<
	@$(AS) $(AFLAGS) -c $< -o $@
0
Недостаток этого в том, что не видно, что делается на самом деле. Иногда надо поменять параметры компиляции одного модуля, это проще всего сделать взяв строку из терминала а не из Makefile. Хотя для мелких проектов и если никто больше его ковырять не будет, не значимо.
0
А как сделать чтобы он все генерируемые файлы (*.o и *.d) Складывал в отдельную, мной указанную, папочку? А то проект лежит в дропбоксе, каждый раз синхронизирует, что как бы парит.
0
Надо саму компиляцию производить из этой папки, куда оно будет складываться.
Создаём папку build, помещаем туда Makefile, cd build && make.
0
Использую ваш makefile как основу у себя. Спасибо. К сожалению, не сразу заметил, что у вас опечатка, довольно долго пользовался с ошибкой
include $(wildcart *.d)
Исправьте, может кто-то еще будет исполььзовать «не глядя».
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.