0


(一~)Betaflight开源AT32飞控Makefile详解

betaflight 代码结构参考:

betaflight 代码结构 - 哔哩哔哩 (bilibili.com)

Betaflight 的Makefile 体系与移植参考:

Betaflight 的Makefile 体系与移植 - 哔哩哔哩 (bilibili.com)

一、平台简介

AT32国产飞控最近比较火,佬儿出了一些关于BF飞控移植的文章,但不太详细。这里记录了本人学习BF飞控时关于Makefile部分的总结,留待参照。

AT32飞控实物:

https://item.taobao.com/item.htm?spm=a21n57.1.0.0.4a67523cLjtnSO&id=703550743029&ns=1&abbucket=19#detail

**1.1 **AT32飞控参数

CPU: AT32VMT7

主频: 288MHz

引脚: 100 Pin(“V”)

Flash: 4032 KB(“M”)

RAM: 384 KB

内核:32位ARM® Cortex®-M4内核

*1.2 BF飞控运行*参考参数:

1、系统计算能力,主频在140mhz 以上(对比stm32f405)

2、系统内存在 128kb 以上,flash在 512kb 及以上,如果是spi集成外部flash,执行效率会下降2-3倍

**1.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,从头开始,主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 ~ )

3.1 子makefile文件的引用与前置变量设置:

**3.1.1 **前置变量(~55)

默认构建目标

19: TARGET ?= AT32F437DEV

源目录

68: SRC_DIR := $(ROOT)/src/main

3.1.2 **** ./make/build_verbosity.mk

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"

3.1.3 **** ./make/system-id.mk

include $(ROOT)/make/system-id.mk (84)

设置系统类型与电脑CPU架构

(1)引用变量:

UNAME: 操作系统名

ARCH: 电脑CPU架构

OSFAMILY: 操作系统名(小写)

3.1.4 **** ./make/checks.mk

include $(ROOT)/make/checks.mk (90)

代码检查

(1)目标:

checks

(2)变量:

VALID_TARGETS ?

**3.1.5 ****./make/linux.mk**

include $(ROOT)/make/$(OSFAMILY).mk (99)

配置系统环境

(1)如果有python3

PYTHON:=python3

(2)否则:

PYTHON_VERSION_ python版本号

PYTHON_MAJOR_VERSION_ python主版本号

PYTHON =python

(3)export PYTHON

**3.1.6 ****./make/tools.mk (?)**

(102)

安装编译工具?gcc-arm-none-eabi-10.3-2021.10

(1)变量:

命令行变量:

  1. TOOLS_DIR

编译工具所在位置

  1. ARM_SDK_PREFIX

SDK(软件开发工具)前缀

创建变量:

  1. ARM_SDK_DIR

  2. GCC_REQUIRED_VERSION

版本号

3.1.7 **** ./make/targets.mk

include $(ROOT)/make/targets.mk(122)

  1. 命令行变量

TARGET 对应的芯片(此处使用TARGET=AT32F437DEV)

**3.1.**8 ./src/main/target/AT32F437DEV/AT32F437DEV.mk

-include $(ROOT)/src/main/target/$(BASE_TARGET)/$(TARGET).mk (./make/targets.mk 12)

**3.1.**9 ./make/mcu/AT32F43x.mk

include $(ROOT)/make/mcu/$(TARGET_MCU).mk (173)

**3.1.**10 ./make/source.mk

include $(ROOT)/make/source.mk (224)

3.2 设置默认目标:

.DEFAULT_GOAL := hex (201)

注:

.DEFAULT_GOAL内置变量用来设置Makefile中的默认目标。 在所有的目标中,Makefile会首先执行“终极目标”,而若make命令中没有指定目标的话,.DEFAULT_GOAL指定的默认目标就是终极目标

3.3 执行hex默认目标(577)

hex:
    @echo "make .hex have run"
    $(V0) $(MAKE) -j $(TARGET_HEX)

3.4 make[1]: 进入目录“/home/embedfire/5_Projects/1_betaflight/4_read”

为执行$(V0) $(MAKE) -j $(TARGET_HEX)时寻找$(TARGET_HEX)目标所在Makefile的目录。

其后会依次对目标

$(TARGET_HEX) 353行 -》

$(TARGET_ELF) 411行 -》

$(TARGET_OBJS)

进行递归检测与更新, 其中 $(TARGET_OBJS)较为特殊

3.5 $(TARGET_OBJS)目标

对$(TARGET_OBJS)目标的更新的规则包括三部分。

(1)其一位于主Makefile 末尾705行,如下

$(TARGET_OBJS): Makefile $(TARGET_DIR)/target.mk $(wildcard make/*)

该规则表示是当Makefile(就是批主Makefile)、$(TARGET_DIR)/target.mk、$(wildcard make/*) 三部分文件更新时更新$(TARGET_OBJS)。(虽然这里没有关于$(TARGET_OBJS)目标更新的命令,但由于下面这一部分$(TARGET_OBJS)目标规则的存在,此处的规则并非没有意义。)

(2)其二位于主Makefile 433行,如下(在判断语句中$(DEBUG)为空)

$(OBJECT_DIR)/$(TARGET)/%.o: %.c
    $(V1) mkdir -p $(dir $@)
……

(3)其三位于主Makefile 451、456行

$(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)规则中的更新命令)。

3.6 将.S汇编文件编译为.o文件

该命令为$(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中各变量值》文件

3.7 将所有.c文件编译为.o文件

该命令为$(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中各变量值》文件

3.8 $(TARGET_ELF) 目标链接文件

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作为链接过程的链接脚本

3.9 $(TARGET_HEX) 目标命令生成.hex文件

由于变量$(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 体系与移植 - 哔哩哔哩

arm 交叉编译器各种gcc_arm-linux-gnueabihf-gcc_HKTK-CWW的博客-CSDN博客

STM32高级开发(5)-gcc-arm-none-eabi-CSDN博客

标签: 开源 无人机 linux

本文转载自: https://blog.csdn.net/qq_53043199/article/details/133547574
版权归原作者 清月阁 所有, 如有侵权,请联系我们删除。

“(一~)Betaflight开源AT32飞控Makefile详解”的评论:

还没有评论