赞
踩
betaflight 代码结构参考:
betaflight 代码结构 - 哔哩哔哩 (bilibili.com)
Betaflight 的Makefile 体系与移植参考:
Betaflight 的Makefile 体系与移植 - 哔哩哔哩 (bilibili.com)
AT32国产飞控最近比较火,佬儿出了一些关于BF飞控移植的文章,但不太详细。这里记录了本人学习BF飞控时关于Makefile部分的总结,留待参照。
AT32飞控实物:
CPU: AT32VMT7
主频: 288MHz
引脚: 100 Pin(“V”)
Flash: 4032 KB(“M”)
RAM: 384 KB
内核:32位ARM® Cortex®-M4内核
1、系统计算能力,主频在140mhz 以上(对比stm32f405)
2、系统内存在 128kb 以上,flash在 512kb 及以上,如果是spi集成外部flash,执行效率会下降2-3倍
1. SBUS接收机 uart1_rx
Betaflight源码地址:
https://github.com/flightng/atbetaflight
也可以使用百度网盘:
链接:https://pan.baidu.com/s/1JVMqFuiKKQpDiMzGRpQegg
提取码:6q86
开发工具为Ubuntu 18.04.6 + Vscode + arm-none-eabi-gcc 10.3.1
其中arm-none-eabi-gcc 安装可以参考:
STM32高级开发(5)-gcc-arm-none-eabi-CSDN博客
文章中arm-none-eabi-gcc的版本较低,可在arm官网下载该软件:
Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer
三、源码编译
使用vscode打开BF源码后,在第一次在终端输入make会出在报错且没有编译出obj文件夹,报错内容有git字样。
源码文件没有建立为git仓库。git使用可以网上搜索教程或者参考这个文档:
链接:https://pan.baidu.com/s/1RzRXGwTwV9UBXsOP8yaTkw
提取码:z624
(1)使用命令
git init
创建仓库
(2)使用
git add . (注意后面有个“.”)
将所有未跟踪文件加入暂存区
(3)使用
git commit -a
提交文件作为一个新版本,此后会出现版本名编辑窗口。
(4)输入版本名,如 1_read
ctrl + O 写入内容
回车,确定写入
ctrl + X 离开
(5)使用git status 可以查看当前仓库内容改变状态,
使用git log 可以查看所有历史版本:
(6)此时输入make命令,即可正常编译。编译完成会在obj文件夹下生成.hex文件:
打开源码的主Makefile,从头开始,主Makefile文件的大致内容为(行数以实际为准):
(1)前置变量(~55)
默认构建目标
19: TARGET ?= AT32F437DEV
源目录
68: SRC_DIR := $(ROOT)/src/main
(2)对下级make文件的调用与前期设置(56~225)
主要调用./make ./src/main/target(/AT32F437DEV) 下的.mk文件
在源代码更改时需要维护的内容
(3)对编译工具的设置(226~311)
(4)编译目标设置(322 ~ 351)
(5)具体编译部分(352 ~ )
默认构建目标
19: TARGET ?= AT32F437DEV
源目录
68: SRC_DIR := $(ROOT)/src/main
include $(ROOT)/make/build_verbosity.mk (80)
(1)功能设置冗余度
(2)变量:
V(命令行变量):
## V : Set verbosity level based on the V= parameter
## V=0 Low
## V=1 High
AT := @ (makefile命令前加“@”不输出, 通过export递归传递到其他makefile中)
当命令行V=0,即输出短命令时,有变量:
export V0 := $(AT)
export V1 := $(AT)
export STDOUT:= "> /dev/null"
include $(ROOT)/make/system-id.mk (84)
设置系统类型与电脑CPU架构
(1)引用变量:
UNAME: 操作系统名
ARCH: 电脑CPU架构
OSFAMILY: 操作系统名(小写)
include $(ROOT)/make/checks.mk (90)
代码检查
(1)目标:
checks
(2)变量:
VALID_TARGETS ?
include $(ROOT)/make/$(OSFAMILY).mk (99)
配置系统环境
(1)如果有python3
PYTHON:=python3
(2)否则:
PYTHON_VERSION_ python版本号
PYTHON_MAJOR_VERSION_ python主版本号
PYTHON =python
(3)export PYTHON
(102)
安装编译工具?gcc-arm-none-eabi-10.3-2021.10
(1)变量:
命令行变量:
1. TOOLS_DIR
编译工具所在位置
2. ARM_SDK_PREFIX
SDK(软件开发工具)前缀
创建变量:
1. ARM_SDK_DIR
2. GCC_REQUIRED_VERSION
版本号
include $(ROOT)/make/targets.mk(122)
1. 命令行变量
TARGET 对应的芯片(此处使用TARGET=AT32F437DEV)
-include $(ROOT)/src/main/target/$(BASE_TARGET)/$(TARGET).mk (./make/targets.mk 12)
include $(ROOT)/make/mcu/$(TARGET_MCU).mk (173)
include $(ROOT)/make/source.mk (224)
.DEFAULT_GOAL := hex (201)
注:
.DEFAULT_GOAL内置变量用来设置Makefile中的默认目标。 在所有的目标中,Makefile会首先执行“终极目标”,而若make命令中没有指定目标的话,.DEFAULT_GOAL指定的默认目标就是终极目标
- hex:
- @echo "make .hex have run"
- $(V0) $(MAKE) -j $(TARGET_HEX)
为执行$(V0) $(MAKE) -j $(TARGET_HEX)时寻找$(TARGET_HEX)目标所在Makefile的目录。
其后会依次对目标
$(TARGET_HEX) 353行 -》
$(TARGET_ELF) 411行 -》
$(TARGET_OBJS)
进行递归检测与更新, 其中 $(TARGET_OBJS)较为特殊
对$(TARGET_OBJS)目标的更新的规则包括三部分。
$(TARGET_OBJS): Makefile $(TARGET_DIR)/target.mk $(wildcard make/*)
该规则表示是当Makefile(就是批主Makefile)、$(TARGET_DIR)/target.mk、$(wildcard make/*) 三部分文件更新时更新$(TARGET_OBJS)。(虽然这里没有关于$(TARGET_OBJS)目标更新的命令,但由于下面这一部分$(TARGET_OBJS)目标规则的存在,此处的规则并非没有意义。)
- $(OBJECT_DIR)/$(TARGET)/%.o: %.c
- $(V1) mkdir -p $(dir $@)
- ……
- $(OBJECT_DIR)/$(TARGET)/%.o: %.s
- $(V1) mkdir -p $(dir $@)
- @echo "%% $(notdir $<)" "$(STDOUT)"
- $(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
-
- $(OBJECT_DIR)/$(TARGET)/%.o: %.S
- $(V1) mkdir -p $(dir $@)
- @echo "%% $(notdir $<)" "$(STDOUT)"
- $(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
为对.s、.S以汇编文件作为依赖的更新
这里$(OBJECT_DIR)/$(TARGET)/%.o与$(TARGET_OBJS)其实相同,都为./obj/main/AT32F437DEV及其递归目录下所有的.o文件,只是为了依次更新.o文件才如此写。(%表示文件名匹配,实测可以为/drivers/dma_at32f43x等递归目录下文件名)
综上所述,除(2)中%.c文件的更新会引起(2)中$(OBJECT_DIR)/$(TARGET)/%.o目标的更新命令外,(1)中Makefile的变更也会引起相同的更新命令(即(2)规则中的更新命令)。
该命令为$(TARGET_OBJS)目标命令的第三部分
位于主Makefile 451~456行,将.S文件编译为.o文件并放在.obj相关目录下(源码无.s文件),具体目录在$(TARGET_OBJS)变量中已经指定。
- $(OBJECT_DIR)/$(TARGET)/%.o: %.s
- $(V1) mkdir -p $(dir $@)
- @echo "%% $(notdir $<)" "$(STDOUT)"
- $(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
-
- $(OBJECT_DIR)/$(TARGET)/%.o: %.S
- $(V1) mkdir -p $(dir $@)
- @echo "%% $(notdir $<)" "$(STDOUT)"
- $(V1) $(CROSS_CC) -c -o $@ $(ASFLAGS) $<
其中,$(ASFLAGS)为.s、.S文件的搜索目录,具体值参考《Makefile中各变量值》文件
该命令为$(TARGET_OBJS)目标命令的第二部分
433~447行会将所有源文件中的.c文件编译为.o文件,并放在.obj的相关目录下,具体目录在$(TARGET_OBJS)变量中已经指定。
- $(OBJECT_DIR)/$(TARGET)/%.o: %.c
- $(V1) mkdir -p $(dir $@)
- $(V1) $(if $(findstring $<,$(NOT_OPTIMISED_SRC)), \
- $(call compile_file,not optimised,$(CC_NO_OPTIMISATION)) \
- , \
- $(if $(findstring $(subst ./src/main/,,$<),$(SPEED_OPTIMISED_SRC)), \
- $(call compile_file,speed optimised,$(CC_SPEED_OPTIMISATION)) \
- , \
- $(if $(findstring $(subst ./src/main/,,$<),$(SIZE_OPTIMISED_SRC)), \
- $(call compile_file,size optimised,$(CC_SIZE_OPTIMISATION)) \
- , \
- $(call compile_file,optimised,$(CC_DEFAULT_OPTIMISATION)) \
- ) \
- ) \
- )
该段Makefile中每个选择语句最后都调用了call函数,并对compile_file函数传入两个参数($(1) $(2) ?):
$(call compile_file, 参数1, 参数2)
compile_file函数位于418~422行:
- define compile_file
- echo "%% ($(1)) $<" "$(STDOUT)" && \
- $(CROSS_CC) -c -o $@ $(CFLAGS) $(2) $<
- endef
其中, $(CFLAGS)为.c文件的搜索目录,具体值参考《Makefile中各变量值》文件
411行, $(TARGET_ELF) 目标的命令会将所有已经编译的.o文件链接为obj/main/betaflight_AT32F437DEV.elf 文件。
- $(TARGET_ELF): $(TARGET_OBJS) $(LD_SCRIPT) $(LD_SCRIPTS)
- @echo "Linking $(TARGET)" "$(STDOUT)"
- $(V1) $(CROSS_CC) -o $@ $(filter-out %.ld,$^) $(LD_FLAGS)
- $(V1) $(SIZE) $(TARGET_ELF)
其中$(LD_FLAGS)为链接参数(具体值参考《Makefile中各变量值》文件), 参数中 -T./src/link/at32_flash_f43xM.ld 表明使用./src/link/at32_flash_f43xM.ld作为链接过程的链接脚本
由于变量$(EXST)的值为no,ifeq ($(EXST),no)判断为真,$(TARGET_HEX) 目标执行353行所在的命令,即:
- $(TARGET_HEX): $(TARGET_ELF)
- @echo "Creating HEX $(TARGET_HEX)" "$(STDOUT)"
- $(V1) $(OBJCOPY) -O ihex --set-start 0x8000000 $< $@
该命令使用objcopy格式转换工具将.elf转化为.hex格式文件。
ihex 表式生成.hex文件
--set-start 0x8000000 设置链接文件首地址为0x8000000
至此.hex编译完成
本文参考:
Betaflight 的Makefile 体系与移植 - 哔哩哔哩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。