PX4Bootloader解析
1 引⾔
半年前⼊⼿了Pixhawk V2全套硬件,编译好的开源固件也下了,四轴也飞了,⼀直想对这套开源飞控进⾏⼀个系统地解析,由于⼯作原因⼀直没时间。最近翻开了PX4飞控源代码,它基于NUTTX操作系统,在github上更新⼗分迅速。为了能够全⾯地掌握这套软硬件设计思想,同时对硬件系统有全⾯的认识,我决定对PX4 Bootloader进⾏详细解析。凡涉及到硬件相关的部分,本⽂以Pixhawk V2的主控
STM32F427和IO协处理器STM32F100为基础进⾏解析,其他硬件可参照此⽅法进⾏类⽐,基本结构都是相似的。
感谢韦东⼭⽼师u-boot视频,我⽤同样的⽅法对PX4 Bootloader采⽤类似的⽅法进⾏了分析。针对我解析中存在的问题,希望同⾏和前辈们能够不吝赐教,谢谢。
2 PX4 Bootloader系统架构
从github上之后,打开Bootloader⽂件夹,可以看到libopencm3和Tools共2个⽂件夹和⼀共30个⽂件。
libopencm3和Tools这两个⽂件夹的主要功能如下:
Tools⽂件夹主要⽤于coding style和git submodule的检查,不需要太注意。
libopencm3是github上针对STM32系列芯⽚的,Bootloader使⽤其中的库函数对相应型号的芯⽚进⾏操作,⽤到的地⽅将对库函数功能作简要说明,这⾥并不展开讨论。
其余30个⽂件主要功能如下:
⼯程⽂件:包括Bootloader.sublime-project共1个⽂件,为sublime编辑器的⼯程⽂件。
Readme:包括Readme.md⽂件共1个,⾃⼰看,都能看懂。
License:包括LISENCE.md⽂件1个,权限⽂件,⾃⼰看。
Makefile⽂件:包括Makefile、Makefile.f1、Makefile.f2、Makefile.f3、Makefile.f4、Makefile.f7共5个⽂件,为系统的编译过程提供了依据。
Jtag配置⽂件:以.cfg结尾,包括jig_px4fmu.cfg、stm32f1x.cfg、stm32f3x.cfg、stm32f4x.cfg、stm32f102.cfg共5个⽂件,分别对应不同的Jtag烧写器、不同芯⽚使⽤openocd进⾏烧写时的配置。根据可知,PX4 Bootloader可以使⽤Jtag接⼝进⾏程序烧写,某宝上买的Pixhawk V2拆开后在板上可以看到两个Jtag接⼝(分别对应主控STM32F427和协处理STM32F100),但是没有焊接出来,如需烧写bootloader程序可⾃⾏焊接。
硬件配置头函数:包括hw_config.h共1个⽂件,规定了各类可运⾏PX4开源飞控程序的硬件配置,可与原理图对应查看。
通⽤bootloader调⽤函数集:包括bl.h和bl.c共2个⽂件。提供了bootloader的main函数中需要调⽤的通⽤函数,这些函数与具体硬件⽆关,属顶层调⽤函数。
USB调试接⼝函数集:包括cdcacm.h和cdcacm.c共2个⽂件。提供了bootloader程序基于USB接⼝进⾏调试时所需的输⼊输出函数。
串⼝调试接⼝集:包括usart.h和usart.c共2个⽂件。提供了bootloader程序基于串⼝进⾏调试时所需的输⼊输出函数。
main函数:包括main_f1.c、main_f3.c、main_f4.c、main_f7.c共4个⽂件。分别对应STM32F1、STM32F3、STM32F4和STM32F7芯⽚上运⾏的Bootloader的主函数。
链接⽂件:以.ld结尾,包括stm32f1.ld、stm32f3.ld、stm32f4.ld、stm32f7.ld共4个⽂件。分别对应STM32F1、STM32F3、STM32F4和STM32F7芯⽚上Bootloader程序的链接⽅式。
PX固件⽣成脚本:包括px_mkfw.py共1个⽂件。根据⽂件说明,PX4固件为基于JSON编码的python对象,此脚本⽤于⽣成包含额外编码域的压缩⽂件固件,类似于u-boot中mkimage程序,⽣成的固件上
传前需要⽤此脚本进⾏打包。PX4的固件本⾝已经具有这项功能,这个脚本应该不再需要了,应该很快会被丢弃。
PX固件上传脚本:包括px_uploader.py共1个⽂件。根据说明,此⽂件不再使⽤,已被固件中的取代。
综上所述,这⾥需要重点分析的⽂件包括Makefile⽂件,链接⽂件,main函数⽂件,硬件配置头⽂件(hw_config.h),通⽤bootloader 调⽤函数集⽂件(bl.h和bl.c),USB虚拟串⼝函数集⽂件(cdcacm.h和cdcacm.c),串⼝函数集⽂件(包括usart.h和usart.c)。
3 Makefile⽂件解析
PX4 Bootloader⼯程包含5个Makefile⽂件。其中Makefile是make命令的⼊⼝⽂件,将根据不同的编译对象,调⽤不同的Makefile.*⽂件。为了更清晰地了解Bootloader的编译过程,本节将对⼯程的Makefile进⾏详细注释。
3.1 主Makefile⽂件注释
Bootloader编译的make命令⼊⼝为根⽬录下的Makefile,这是所有编译命令开始的⽂件。
Makefile
#
# Paths to common dependencies
#
export BL_BASE  ?= $(wildcard .)              #获取Bootloader本地⼯程所在⽬录,并赋给变量BL_BASE
export LIBOPENCM3 ?= $(wildcard libopencm3)    #获取开源库libopencm3所在⽬录,并赋给变量LIBOPENCM3
#
# Tools
#
export CC    = arm-none-eabi-gcc              #定义交叉编译⼯具链变量CC
export OBJCOPY  = arm-none-eabi-objcopy      #定义⼆进制⽣成⼯具链变量OBJCOPY
#
# Common configuration
#
export FLAGS  =  -std=gnu99 \                      #使⽤GNU99的优化C语⾔标准
-Os \                            #专门针对⽣成⽬标⽂件⼤⼩进⾏
-g \                              #⽣成调试信息
-Wundef \                        #当没有定义的符号出现在#if中时警告
-Wall \                          #打开⼀些有⽤的警告选项
-fno-builtin \                    #不接受没有__buildin__前缀的函数作为内建函数
-I$(LIBOPENCM3)/include \        #包含开源库libopencm3的头⽂件
-ffunction-sections \            #要求编译器为每个function分配独⽴的section
-nostartfiles \                  #链接时不使⽤标准的启动⽂件
-
lnosys \                        #链接libnosys.a⽂件
-Wl,-gc-sections \                #传递-gc-sections给连接器,删除没有使⽤的section
-Wl,-g \                          #传递-g选项给链接器,兼容其他⼯具
-Werror                          #把警告当错误,出现警告就放弃编译
export COMMON_SRCS  = bl.c cdcacm.c  usart.c    #定义通⽤源⽂件变量COMMON_SRCS
#
# Bootloaders to build
#
TARGETS = \            #定义编译⽬标
aerofcv1_bl \
auavx2v1_bl \
crazyflie_bl \
mindpxv2_bl \
px4aerocore_bl \
px4discovery_bl \
px4flow_bl \
px4fmu_bl \
px4fmuv2_bl \
px4fmuv4_bl \
px4fmuv4pro_bl \
px4fmuv5_bl \
px4io_bl \
px4iov3_bl \
tapv1_bl
all: $(TARGETS)    #编译⽬标all=$(TARGETS)
clean:      #定义清理⼯程的操作(即make clean)
cd libopencm3 && make --no-print-directory clean && cd ..  # 从Bootloader本地⼯程⽬录进⼊libopencm3⽂件夹,执⾏make clean清理命令,然后回到上⼀级⽬录。 rm -f *.elf *.bin      #删除.efl和.bin⽂件
#
# Specific bootloader targets.
# 各编译⽬标的具体操作,主要规定了编译需要使⽤的Makefile⽂件,硬件⽬标TARGET_HW,链接脚本LINKER_FILE,编译⽬标TARGET_FILE_NAME
#
auavx2v1_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=AUAV_X2V1  LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
px4fmu_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=PX4_FMU_V1 LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
px4fmuv2_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=PX4_FMU_V2  LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
px4fmuv4_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=PX4_FMU_V4  LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
px4fmuv4pro_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=PX4_FMU_V4_PRO LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@ EXTRAFLAGS=-DSTM32F469
px4fmuv5_bl:$(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f7 TARGET_HW=PX4_FMU_V5 LINKER_FILE=stm32f7.ld TARGET_FILE_NAME=$@
mindpxv2_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=MINDPX_V2 LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
px4discovery_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)makefile phony
make -f Makefile.f4 TARGET_HW=PX4_DISCOVERY_V1  LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
px4flow_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=PX4_FLOW_V1  LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
px4aerocore_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=PX4_AEROCORE_V1 LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
crazyflie_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=CRAZYFLIE LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
# Default bootloader delay is *very* short, just long enough to catch
# the board for recovery but not so long as to make restarting after a
# brownout problematic.
#
px4io_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f1 TARGET_HW=PX4_PIO_V1 LINKER_FILE=stm32f1.ld TARGET_FILE_NAME=$@
px4iov3_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f3 TARGET_HW=PX4_PIO_V3 LINKER_FILE=stm32f3.ld TARGET_FILE_NAME=$@
tapv1_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=TAP_V1 LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
aerofcv1_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=AEROFC_V1 LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
#
# Binary management
# ⼆进制⽂件压缩操作:deploy命令
#
.PHONY: deploy
deploy:
zip Bootloader.zip *.bin
zip Bootloader.zip *.bin
#
# Submodule management
# ⼦模块libopencm3操作与管理,进⾏的操作如下:
# 1. 更新git⼦⼯程libopencm3。
# 2. 调⽤Tools/check_submodules.sh检查当前libopencm3的版本信息是否正确。
# 3. 编译libopencm3⼯程,⽣成库⽂件,供bootloader使⽤。
#
$(LIBOPENCM3): checksubmodules
make -C $(LIBOPENCM3) lib
.PHONY: checksubmodules
checksubmodules: updatesubmodules
$(Q) ($(BL_BASE)/Tools/check_submodules.sh)
.PHONY: updatesubmodules
updatesubmodules:
$(Q) (git submodule init)
$(Q) (git submodule update)
3.2 主控Makefile.f4⽂件注释
由主Makefile中⽬标⽣成语句可以看出,Pixhawk V2硬件系统的主控stm32f427对应的bootloader调⽤了如下语句:
Makefile
px4fmuv2_bl: $(MAKEFILE_LIST) $(LIBOPENCM3)
make -f Makefile.f4 TARGET_HW=PX4_FMU_V2  LINKER_FILE=stm32f4.ld TARGET_FILE_NAME=$@
因此,⽬标px4fmuv2_bl⽣成的Makefile脚本为Makefile.f4,同时,它还定义了如下变量
硬件⽬标:$(TARGET_HW)=PX4_FMU_V2
链接⽂件:$(LINKER_FILE)=stm32f4.ld
⽬标名称:$(TARGET_FILE_NAME)=$@=px4fmuv2_bl
同时,在主Makefile中规定的全局变量BL_BASE、LIBOPENCM3、CC、OBJCOPY、FLAGS、COMMON_SRCS在Makefile.f4中同样有效。下⾯将对Makefile.f4进⾏详细注释。
Makefile.f4
OPENOCD  ?= openocd    #定义OPENOCD命令
JTAGCONFIG ?= interface/olimex-jtag-tiny.cfg        #定义openocd对应的jtag烧写器配置⽂件
#JTAGCONFIG ?= interface/jtagkey-tiny.cfg
# 5 seconds / 5000 ms default delay
PX4_BOOTLOADER_DELAY ?= 5000            #定义启动变量PX4_BOOTLOADER_DELAY为5000ms
SRCS  = $(COMMON_SRCS) main_f4.c  #定义编译源⽂件为bl.c cdcacm.c usart.c和main_f4.c
FLAGS  += -mthumb\                  #使⽤thumb指令集
-mcpu=cortex-m4\                  #使⽤cortex m4对应的CPU指令
-mfloat-abi=hard\                #浮点为硬件浮点运算
-mfpu=fpv4-sp-d16 \              #浮点运算协处理器为fpv4-sp-d16
-DTARGET_HW_$(TARGET_HW) \        #定义变量TARGET_HW_PX4_FMU_V2为1
-DSTM32F4 \                      #定义变量STM32F4为1
-T$(LINKER_FILE) \                #使⽤链接⽂件stm32f4.ld
-L$(LIBOPENCM3)/lib \            #添加库⽂件搜索⽬录libopencm3/lib
-lopencm3_stm32f4 \              #链接库⽂件libopencm3_stm32f4.a
$(EXTRAFLAGS)
ELF  = $(TARGET_FILE_NAME).elf          #定义⽬标变量ELF=px4fmuv2_bl.elf
BINARY  = $(TARGET_FILE_NAME).bin      #定义⽬标⼆进制变量BINARY=px4fmuv2_bl.bin
all:  $(ELF) $(BINARY)                  #定义⽬标all,为px4fmuv2_bl.elf和px4fmuv2_bl.bin
#px4fmuv2_bl.elf的⽣成规则:
#px4fmuv2_bl.elf: bl.c cdcacm.c usart.c main_f4.c Makefile
#    arm-none-eabi-gcc -o px4fmuv2_bl.elf bl.c cdcacm.c usart.c main_f4.c $(FLAGS)
$(ELF):  $(SRCS) $(MAKEFILE_LIST)
$(CC) -o $@ $(SRCS) $(FLAGS)
#px4fmuv2_bl.bin的⽣成规则:
#px4fmuv2_bl.bin: px4fmuv2_bl.elf
#  arm-none-eabi-objcopy -O binary px4fmuv2_bl.elf px4fmuv2_bl.bin
$(BINARY): $(ELF)
$(OBJCOPY) -O binary $(ELF) $(BINARY)
#upload: all flash flash-bootloader
#定义upload⽬标,依赖于all flash-bootloader
upload: all flash-bootloader
#定义flash-bootloader⽬标的命令规则
#执⾏openocd命令,查与本⼯程⽬录平⾏的px4_bootloader⽬录中interface/olimex-jtag-tiny.cfg⽂件作为jtag烧写器的配置⽂件,以stm32f4x.cfg作为主控stm32f42 flash-bootloader:
$(OPENOCD) --search ../px4_bootloader -f $(JTAGCONFIG) -f stm32f4x.cfg -c init -c "reset halt" -c "flash write_image erase $(BINARY) 0x08000000" -c "reset r
# Use to upload to a stm32f4-discovery devboard, requires the latest version of openocd (from git)
# build openocd with "cd openocd; ./bootstrap; ./configure --enable-maintainer-mode --enable-stlink"
#定义upload-discovery⽬标的命令规则
#执⾏openocd命令,默认使⽤stlink烧写器及其配置⽂件,查board/stm32f4discovery.cfg配置⽂件,在openocd环境下依次执⾏init, reset halt, flash probe 0, stm32 upload-discovery:
$(OPENOCD) --search ../px4_bootloader -f board/stm32f4discovery.cfg -c init -c "reset halt" -c "flash probe 0" -c "stm32f2x mass_erase 0" -c "flash write_image
3.3 IO协处理器Makefile.f1⽂件注释
由主Makefile中⽬标⽣成语句可以看出,Pixhawk V2硬件系统的IO协处理器stm32f100对应的bootloader调⽤了如下语句:
Makefile

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。