1 #
2 # Common Makefile for the PX4 bootloaders
3 #
4
5 #
6 # Paths to common dependencies
7 #
8 export BUILD_DIR_ROOT ?= build
9 export BL_BASE ?= $(wildcard .)
10 export LIBOPENCM3 ?= $(wildcard libopencm3)
11 export LIBKINETIS ?= $(wildcard lib/kinetis/NXP_Kinetis_Bootloader_2_0_0)
12 MKFLAGS=--no-print-directory
export BUILD_DIR_ROOT ?= build #指定构建目录的路径,如果没有定义,则使用右侧的默认值
export BL_BASE ?= $(wildcard .) #使用wildcard获取当前目录作为bootloader的基础路径
export LIBOPENCM3 ?= $(wildcard libopencm3) #使用wildcard查找libopencm3(一个处理ARM Cortex-M微控制器的低级硬件接口)的目录
export LIBKINETIS ?= $(wildcard lib/kinetis/NXP_Kinetis_Bootloader_2_0_0) #定义NXP Kinetis系列微处理器的bootloader库路径
MKFLAGS=--no-print-directory #设置Make的选项标志,这里设定不打印进入子目录的消息
export 将文件内的变量导出为环境变量
wildcard 一个Makefile的内置函数用于查找文件或目录
Makefile中的赋值:
延迟展开赋值 VAR = value #赋值时立即展开右边的值
FOO = $(BAR)
BAR = hello
all:
@echo $(FOO)
输出结果为hello
立即展开赋值 VAR := $(shell uname -r) #右侧表达式在赋值时立即求值,后续引用
VAR
时不会重新计算FOO := $(BAR)
BAR = helloall:
@echo $(FOO)
条件赋值 VAR ?= default_value #如果
VAR
之前已经被赋值,则不会覆盖追加赋值 VAR += more_value #追加赋值用于在现有变量的基础上追加新内容
13
14 SRC_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
15
16 COLOR_BLUE = \033[0;94m
17 NO_COLOR = \033[m
18
19 define colorecho
20 +@echo -e '${COLOR_BLUE}${1} ${NO_COLOR}'
21 endef
22
SRC_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) #获取当前Makefile所在的目录路径
COLOR_BLUE = \033[0;94m #定义颜色变量,\033[0;94m表示浅蓝色。用法为COLOR_BLUE"AAA",会输出浅蓝色的AAA字符串
NO_COLOR = \033[m #定义无颜色变量,\033[m表示清除颜色
define colorecho #定义名为colorecho的函数
+@echo -e '${COLOR_BLUE}${1} ${NO_COLOR}' #输出特定的颜色${1}是调用colorecho传入的第一个参数,
endef
MAKEFILE_LIST Makefile内置的特殊变量,包含了所有Makefile文件的列表
lastword 函数,取MAKEFILE_LIST中最后一个Makefile文件
realpath 函数,返回输入路径的绝对路径
shell dirname shell是一个Makefile函数,允许用户在Makefile内使用Shell命令;dirname是一个Shell命令,用于提取文件路径的目录部分,dirname /path/to/file会返回/path/to
+ 确保echo命令不会在并行模式下和其他任务同时执行,避免并发问题
@ 抑制echo命令本身的输出,只显示输出结果(带颜色的文本)
23 #
24 # Tools
25 #
26 export CC = arm-none-eabi-gcc
27 export OBJCOPY = arm-none-eabi-objcopy
28
29 #
30 # Common configuration
31 #
32 export FLAGS = -std=gnu99 \
33 -Os \
34 -g \
35 -Wundef \
36 -Wall \
37 -fno-builtin \
38 -I$(BL_BASE)/$(LIBOPENCM3)/include \
39 -I$(BL_BASE)/. \
40 -ffunction-sections \
41 -nostartfiles \
42 -lnosys \
43 -Wl,-gc-sections \
44 -Wl,-g \
45 -Werror
46
export CC = arm-none-eabi-gcc #定义编译器变量CC并导出,该变量默认为gcc或clang。arm-none-eabi-gcc是一种交叉编译器,用于编译在arm架构上运行的代码。
export OBJCOPY = arm-none-eabi-objcopy #定义并导出变量OBJCOPY,objcopy可以将编译生成的目标文件或可执行文件转换为其他格式,例如.ELF——>.bin
export FLAGS = -std=gnu99 \ ...... #定义并导出FLAGS变量,该变量包含了一系列编译选项,用于控制 C 编译器和链接器的行为。因为将多个信息换行,所以有\。
arm-none-eabi-gcc 一种交叉编译器,用于编译在arm架构上运行的代码。
arm-none-eabi-objcopy 是objcopy的交叉编译版本,适用于 ARM 架构的目标系统。
-std=gnu99 指定使用gnu99标准
-Os 优化选项,表示优化代码大小
-g 包含调试信息
-Wundef 启用对未定义宏的警告
-Wall 开启所有常见的警告
-fno-builtin 禁用对编译器内置函数的优化,防止编译器将某些标准函数替换为其内置实现
-I$(BL_BASE)/$(LIBOPENCM3)/include 添加头文件搜索路径,-I是编译器的一个选项,用于指定额外的头文件搜索路径
-I$(BL_BASE)/. 添加当前目录为头文件搜索路径
-ffunction-sections 将每个函数放入单独的section(段)中。使得每个函数有自己独立的内存段,这与链接器的--gc-sections选项结合使用,可以在链接时移除未使用的函数,从而减小最终生成的二进制文件的大小。
-nostartfiles 不使用标准的启动文件。告诉链接器不要使用标准C库的启动文件。这个选项通常用于嵌入式系统开发,因为嵌入式系统通常有自己定制的启动代码。
-lnosys 链接
nosys
库,nosys
是一个轻量级库,提供对某些 C 标准库功能的基本支持,但不包含完整的操作系统支持。通常用于没有操作系统的嵌入式环境。-Wl,-gc-sections 链接器选项,启用垃圾回收未使用的段,用于减小二进制文件大小
-Wl,-g 将调试信息传递给链接器
-Werror 将所有警告视为错误,一旦出现任何警告,编译将终止,并视为错误
47 ifneq ($(CRYPTO_HAL),)
48 include crypto_hal/$(CRYPTO_HAL)/Makefile.include
49 endif
50
51 export COMMON_SRCS = bl.c $(CRYPTO_SRCS)
52
53 export ARCH_SRCS = cdcacm.c usart.c
54
55
ifneq ($(CRYPTO_HAL),) #if not equal,条件判断指令,如果CRYPTO_HAL不等于空
include crypto_hal/$(CRYPTO_HAL)/Makefile.include #包含路径
endif
export COMMON_SRCS = bl.c $(CRYPTO_SRCS) #定义并导出存储源文件列表的变量COMMON_SRCS
export ARCH_SRCS = cdcacm.c usart.c #ARCH_SRCS,与特定平台架构有关的变量
cdcacm.c
可能与 USB CDC(Communication Device Class)相关。CDC 通常用于实现串行通信,如虚拟串口(VCP)
usart.c
通常与 USART(Universal Synchronous and Asynchronous Receiver-Transmitter)通信有关。USART 是用于串行数据传输的硬件模块,常用于嵌入式系统的串行通信。
58 # Note: px4fmuv3_bl is the same as px4fmuv2_bl except for a different USB devic e
59 # string
60 #
61 TARGETS = \
62 aerofcv1_bl \
63 auavx2v1_bl \
64 avx_v1_bl \
65 crazyflie21_bl \
66 crazyflie_bl \
67 cube_f4_bl \
68 fmuk66e_bl \
69 fmuk66v3_bl \
70 kakutef7_bl \
71 mindpxv2_bl \
72 modalai_fc_v1_bl \
73 modalai_voxl2_io_bl \
74 omnibusf4sd_bl \
75 pix32v5_bl \
76 px4aerocore_bl \
77 px4discovery_bl \
78 px4flow_bl \
79 px4fmu_bl \
80 px4fmuv2_bl \
81 px4fmuv3_bl \
82 px4fmuv4_bl \
83 px4fmuv4pro_bl \
84 px4fmuv5_bl \
85 px4fmuv5x_bl \
86 px4io_bl \
87 px4iov3_bl \
88 smartap_airlink_bl \
89 smartap_pro_bl \
90 tapv1_bl \
91 uvify_core_bl \
92 atl_mantis_edu_bl \
93 thepeach_k1_bl \
94 thepeach_r1_bl
95
96 all: $(TARGETS) sizes
97
定义了 Makefile 的 TARGETS
变量,其中列出了一系列 bootloader 目标文件。每个目标都代表一个不同的硬件平台或设备的 bootloader。这些目标通常会对应不同的硬件板卡,或者是同一硬件平台的不同版本,可能会有不同的功能配置,如 USB 设备字符串的不同。
这里没有列出px4fmuv6_bl,也就是pixhawk 6C对应的架构,有两种方法:1、看看px4fmuv5_bl和px4fmuv6_bl有什么相似之处,能不能用v5编译的代替;2、在TARGETS中添加px4fmuv6_bl。
all: $(TARGETS) sizes #all是一个规则名,通常用来定义默认的构建目标。如果你在命令行中运行 make
,默认情况下会执行 make all
。
sizes 通常用于计算和输出生成的二进制文件(例如ELF)或目标文件的大小。
这里要引入Makefile中目标(target)和依赖(dependences)的概念。
目标(Target):表示需要生成的文件或执行的任务。
依赖(Dependencies):目标所依赖的文件或其他目标。
命令(Commands):实现目标的具体步骤,通常是命令行工具的命令,例如
gcc
、cp
等。命令通常使用 Shell 语言。
98 clean:
99 cd libopencm3 && make --no-print-directory clean && cd ..
100 rm -f *.elf *.bin *.map # Remove any elf or bin files contained dire ctly in the Bootloader directory
101 rm -rf build # Remove build directories
102
clean #定义了一个目标,即要执行的任务,clean后面是目标的具体内容
cd libopencm3 && make --no-print-directory clean && cd .. #进入libopencm3目录并删除该库目录下生成的中间文件和构建产物。--no-print-directory
参数使得执行时不打印该目录的切换信息。
rm -f *.elf *.bin *.map #删除Bootloader目录下的.elf .bin .map文件,-f表示如果文件不存在,也不提示
rm -rf build #删除build目录
103 #
104 # Specific bootloader targets.
105 #
106
107 fmuk66v3_bl: $(MAKEFILE_LIST) $(LIBKINETIS)
108 ${MAKE} ${MKFLAGS} -f Makefile.k66 TARGET_HW=FMUK66_V3 LINKER_FILE =kinetisk66.ld TARGET_FILE_NAME=$@
109
110 fmuk66e_bl: $(MAKEFILE_LIST) $(LIBKINETIS)
111 ${MAKE} ${MKFLAGS} -f Makefile.k66 TARGET_HW=FMUK66_E LINKER_FILE= kinetisk66.ld TARGET_FILE_NAME=$@
112
113 auavx2v1_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
114 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=AUAV_X2V1 LINKER_FILE= stm32f4.ld TARGET_FILE_NAME=$@
115
116 kakutef7_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
117 ${MAKE} ${MKFLAGS} -f Makefile.f7 TARGET_HW=KAKUTEF7 LINKER_FILE=st m32f7.ld TARGET_FILE_NAME=$@
118
119 pix32v5_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
120 ${MAKE} ${MKFLAGS} -f Makefile.f7 TARGET_HW=HOLYBRO_PIX32_V5 LINKER _FILE=stm32f7.ld TARGET_FILE_NAME=$@
121
122 px4fmu_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
123 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=PX4_FMU_V1 LINKER_FILE= stm32f4.ld TARGET_FILE_NAME=$@
124
125 px4fmuv2_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
126 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=PX4_FMU_V2 LINKER_FILE =stm32f4.ld TARGET_FILE_NAME=$@
127
128 px4fmuv3_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
129 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=PX4_FMU_V3 LINKER_FILE =stm32f4.ld TARGET_FILE_NAME=$@
130
131 px4fmuv4_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
132 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=PX4_FMU_V4 LINKER_FILE =stm32f4.ld TARGET_FILE_NAME=$@
133
134 px4fmuv4pro_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
135 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=PX4_FMU_V4_PRO LINKER_F ILE=stm32f4.ld TARGET_FILE_NAME=$@ EXTRAFLAGS=-DSTM32F469
136
137 px4fmuv5_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
138 ${MAKE} ${MKFLAGS} -f Makefile.f7 TARGET_HW=PX4_FMU_V5 LINKER_FILE= stm32f7.ld TARGET_FILE_NAME=$@
139
140 px4fmuv5x_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
141 ${MAKE} ${MKFLAGS} -f Makefile.f7 TARGET_HW=PX4_FMU_V5X LINKER_FILE =stm32f7.ld TARGET_FILE_NAME=$@
fmuk66v3_bl: $(MAKEFILE_LIST) $(LIBKINETIS)
${MAKE} ${MKFLAGS} -f Makefile.k66 TARGET_HW=FMUK66_V3 LINKER_FILE =kinetisk66.ld TARGET_FILE_NAME=$@ #目标fmuk66v3_bl依赖于MAKEFILE_LIST和LIBKINETIS,指定 Makefile为Makefile.f4
,设置目标硬件为 PX4_FMU_V1
,使用链接器脚本 stm32f4.ld
MAKEFILE_LIST 一个自动变量,用于记录当前 Makefile 列表中包含的所有 Makefile 文件的名称。它在执行过程中会动态更新,包含每个被处理的 Makefile 的路径
$@ 当前目标的名称,这里就是fmu66v3
MAKE 调用 Make 命令,通常是
make
的别名
-f Makefile.k66
指定使用Makefile.k66
作为要执行的 Makefile 文件。这允许你针对特定平台或配置进行构建
194 # Default bootloader delay is *very* short, just long enough to catch
195 # the board for recovery but not so long as to make restarting after a 196 # brownout problematic.
197 #
198 px4io_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
199 ${MAKE} ${MKFLAGS} -f Makefile.f1 TARGET_HW=PX4_PIO_V1 LINKER_FILE= stm32f1.ld TARGET_FILE_NAME=$@
200
201 px4iov3_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
202 ${MAKE} ${MKFLAGS} -f Makefile.f3 TARGET_HW=PX4_PIO_V3 LINKER_FILE= stm32f3.ld TARGET_FILE_NAME=$@
203
204 tapv1_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
205 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=TAP_V1 LINKER_FILE=stm3 2f4.ld TARGET_FILE_NAME=$@
206
207 aerofcv1_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
208 ${MAKE} ${MKFLAGS} -f Makefile.f4 TARGET_HW=AEROFC_V1 LINKER_FILE=s tm32f4.ld TARGET_FILE_NAME=$@
209
210 atl_mantis_edu_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
211 ${MAKE} ${MKFLAGS} -f Makefile.f7 TARGET_HW=ATL_MANTIS_EDU LINKER_F ILE=stm32f7.ld TARGET_FILE_NAME=$@
212
px4io_bl: $(MAKEFILE_LIST) $(LIBOPENCM3) ${MAKE} ${MKFLAGS} -f Makefile.f1 TARGET_HW=PX4_PIO_V1 LINKER_FILE=stm32f1.ld TARGET_FILE_NAME=$@ #用于构建px4io的目标
213 #
214 # Show sizes
215 #
216 .PHONY: sizes
217 sizes:
218 @-find build/*/ -name '*.elf' -type f | xargs size 2> /dev/null || :
219
#定义一个伪目标sizes用于显示所有生成的ELF文件的大小
-name '*.elf'
:只查找以.elf
为后缀的文件
-type f
:指定只查找常规文件(排除目录和其他文件类型)
xargs size
:xargs
命令将find
查找到的文件传递给size
命令,size
会输出这些 ELF 文件中各个段(如代码段、数据段等)的大小
2> /dev/null
:这部分将所有来自标准错误的输出(如错误消息)重定向到/dev/null
,使得终端中不会显示这些错误
|| :
这是一个保护机制。如果find
没有找到任何 ELF 文件,整个命令可能会失败。|| :
表示即使前面的命令失败(返回非零退出状态),后面执行的命令也会返回成功(:
是一个空操作命令,总是返回成功状态)。
220 #
221 # Binary management
222 #
223 .PHONY: deploy
224 deploy:
225 zip -j Bootloader.zip build/*/*.bin
226
#定义了一个名为deploy的伪目标,用于打包所有生成的.bin文件到一个压缩包中。运行 make deploy
后,你将得到一个包含所有 .bin
文件的 Bootloader.zip
压缩包
- .PHONY
.PHONY
是 Makefile 中的一个指示符,表示目标并不实际指向一个文件。它告诉make
,即使文件系统中存在一个叫deploy的文件,make
仍然应将这个目标作为命令而不是文件来处理。这可以避免文件与命令名称冲突带来的问题。zip
:这是 Unix/Linux 系统中的命令,用于将文件压缩成.zip
格式。-j
:这是zip
命令的选项,表示将文件直接压缩进目标 zip 文件中而不保留文件的路径结构。也就是说,即使源文件存在于不同的子目录中,它们在压缩包中将位于根目录。Bootloader.zip
:这是压缩后的文件名,生成一个名为Bootloader.zip
的压缩包。build/*/*.bin
:这个模式表示在build
目录下查找所有子目录中的.bin
文件并将其添加到压缩包中。具体来说:
build/*/
:查找build
目录下的所有子目录。*.bin
:查找以.bin
为后缀的二进制文件。
227 #
228 # Submodule management
229 #
230
231 $(LIBOPENCM3): checksubmodules
232 ${MAKE} -C $(LIBOPENCM3) lib
233
234 .PHONY: checksubmodules
235 checksubmodules:
236 $(Q) ($(BL_BASE)/Tools/check_submodules.sh)
237
$(LIBOPENCM3): checksubmodules #定义目标LIBOPENCM3,依赖为伪目标checksubmodules
${MAKE} -C $(LIBOPENCM3) lib #切换到LIBOPENCM3目录,再执行make #这个目标是113~211行的目标的依赖
.PHONY: checksubmodules #声明checksubmodules是一个伪目标
checksubmodules:
$(Q) ($(BL_BASE)/Tools/check_submodules.sh) #执行脚本文件;Q的作用与@类似,如果Q的值为@,则在执行脚本文件的时候不打印该命令,但因为之前没定义Q,其为空字符串,所以会打印命令($(BL_BASE)/Tools/check_submodules.sh)
238 # Astyle
239 # --------------------------------------------------------------------
240 .PHONY: check_format format
241
242 check_format:
243 $(call colorecho,'Checking formatting with astyle')
244 @$(SRC_DIR)/Tools/check_code_style_all.sh
245 @cd $(SRC_DIR) && git diff --check
246
247 format:
248 $(call colorecho,'Formatting with astyle')
249 @$(SRC_DIR)/Tools/check_code_style_all.sh --fix
Makefile中没有明显的针对fmuv6的bootloader,但是根据下面的fmuv5和fmuv5x的编译信息,编译这两个架构需要的是Makefile.f7,可能意味着针对stm32f7芯片,6C的fmu芯片是stm32h743,h7系列。
137 px4fmuv5_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
138 ${MAKE} ${MKFLAGS} -f Makefile.f7 TARGET_HW=PX4_FMU_V5 LINKER_FILE= stm32f7.ld TARGET_FILE_NAME=$@
139
140 px4fmuv5x_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
141 ${MAKE} ${MKFLAGS} -f Makefile.f7 TARGET_HW=PX4_FMU_V5X LINKER_FILE =stm32f7.ld TARGET_FILE_NAME=$@
stm32h743和stm32f7系列的相同点和不同点:
相同点:内核,都是ARM Cortex-M7;开发环境,都可以用stm32CubeMX、stm32CubeIDE开发;调试,都支持SWD(Serial Wire Debug)和JTAG。
不同点:主频,H743——480MHz,F7——216MHz,等等。
最关键的,两者的架构相同。
看看Makefile.f7
1 #
2 # PX4 bootloader build rules for STM32F7 targets.
3 # Since the STM32F7 is not supported fully in libopencm3 at this time,
4 # this build is a bit of a hack to use the similar IP blocks of the F469
5 # for USB by telling libopencm3 it is an STM32F4
6 ARCH=stm32
7 OPENOCD ?= openocd
8
9 JTAGCONFIG ?= interface/olimex-jtag-tiny.cfg
10 #JTAGCONFIG ?= interface/jtagkey-tiny.cfg
11