arducopter的makefile与运行流程

来源:互联网 发布:知乎无法注册 编辑:程序博客网 时间:2024/06/15 14:19

px4原生固件:

git clone https://github.com/PX4/Firmware.gitAPM:
git clone https://github.com/ArduPilot/ardupilot.git
所以他们时不同的固件,bootload一样

https://dev.px4.io/zh/setup/building_px4.html

下面时ardupilot/APM的编译和启动

Makefile,以ArduCopter为例:

    include ../mk/apm.mk
环境变量定义:  *****提前定义ardupilot为根目录
    MK_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
    MK_DIR=/ardupilot/mk目录

    SRCROOT            :=    $(realpath $(dir $(firstword $(MAKEFILE_LIST))))
    SRCROOT=ArduCopter目录的绝对地址.  = /ardupilot/ArduCopter

    SKETCHBOOK        :=    $(shell cd $(SRCROOT)/.. && pwd)
    SKETCHBOOK=ardupilot目录绝对地址,就是根目录. = /ardupilot

    SKETCH            :=    $(lastword $(subst /, ,$(SRCROOT)))
    SKETCH=ArduCopter字符串

    BUILDROOT        :=    $(SKETCHBOOK)/Build.$(SKETCH)
    BUILDROOT= /ardupilot/Build.ArduCopter

    MESSAGE_DEFINITIONS := $(SKETCHBOOK)/modules/mavlink/message_definitions/v1.0
    MESSAGE_DEFINITIONS=/ardupilot/modules/mavlink/message_definitions/v1.0

    UAVCAN_HEADERS := $(UAVCAN_GEN_INC)/uavcan/Timestamp.hpp $(wildcard $(UAVCAN_GEN_INC),*.hpp)
    UAVCAN_HEADERS= /ardupilot/modules/uavcan/libuavcan/include/dsdlc_generated/*.hpp  /ardupilot/modules/uavcan/libuavcan/include/dsdlc_generated/uavcan/Timestamp.hpp

    PX4FIRMWARE_DIRECTORY ?= $(SKETCHBOOK)/modules/PX4Firmware
    PX4FIRMWARE_DIRECTORY = /ardupilot/modules/PX4Firmware

    PX4NUTTX_DIRECTORY ?= $(SKETCHBOOK)/modules/PX4NuttX
    PX4NUTTX_DIRECTORY = /ardupilot/modules/PX4NuttX

    NUTTX_ROOT := $(shell cd $(PX4NUTTX_DIRECTORY) && pwd)
    NUTTX_ROOT = /ardupilot/modules/PX4NuttX

    NUTTX_SRC := $(NUTTX_ROOT)/nuttx/
    NUTTX_SRC := /ardupilot/modules/PX4NuttX/nuttx/

    PX4_ROOT := $(shell cd $(PX4FIRMWARE_DIRECTORY) && pwd)
    PX4_ROOT = /ardupilot/modules/PX4Firmware

    PX4_MAKE_ARCHIVES = $(MAKE) -C $(PX4_ROOT) -f $(PX4_ROOT)/Makefile.make NUTTX_SRC=$(NUTTX_SRC) CCACHE=$(CCACHE) archives MAXOPTIMIZATION="-Os"
    PX4_MAKE_ARCHIVES = make -C /ardupilot/modules/PX4Firmware -f /ardupilot/modules/PX4Firmware/Makefile.make NUTTX_SRC=/ardupilot/modules/PX4NuttX/nuttx/ CCACHE=(空) archives MAXOPTIMIZATION="-Os"

    PX4_MAKE = $(v)+ GIT_SUBMODULES_ARE_EVIL=1 ARDUPILOT_BUILD=1 $(MAKE) -C $(SKETCHBOOK) -f $(PX4_ROOT)/Makefile.make EXTRADEFINES="$(SKETCHFLAGS) $(WARNFLAGS) $(OPTFLAGS) "'$(EXTRAFLAGS)' APM_MODULE_DIR=$(SKETCHBOOK) SKETCHBOOK=$(SKETCHBOOK) CCACHE=$(CCACHE) PX4_ROOT=$(PX4_ROOT) NUTTX_SRC=$(NUTTX_SRC) MAXOPTIMIZATION="-Os" UAVCAN_DIR=$(UAVCAN_DIR)
    PX4_MAKE = $(v)+ GIT_SUBMODULES_ARE_EVIL=1 ARDUPILOT_BUILD=1 make -C /ardupilot -f /ardupilot/modules/PX4Firmware/Makefile.make EXTRADEFINES="$(SKETCHFLAGS) $(WARNFLAGS) $(OPTFLAGS) "'$(EXTRAFLAGS)' APM_MODULE_DIR=/ardupilot SKETCHBOOK=/ardupilot CCACHE=(空) PX4_ROOT=/ardupilot/modules/PX4Firmware/ NUTTX_SRC=/ardupilot/modules/PX4NuttX/nuttx/ MAXOPTIMIZATION="-Os" UAVCAN_DIR=$(UAVCAN_DIR)

    SKETCHCPP      := $(SRCROOT)/$(SKETCH).cpp
    SKETCHCPP = /ardupilot/ArduCopter/ArduCopter.cpp

    MAKE_INC=$(wildcard $(SRCROOT)/make.inc)
    MAKE_INC = /ardupilot/ArduCopter/make.inc

    SRCSUFFIXES = *.cpp

    LIBRARIES在mk/make.inc与/ardupilot/ArduCopter/make.inc中定义了.其实就是需要编译的libraries中的库目录

    LIBTOKENS := $(LIBRARIES)
    LIBTOKENS += AP_HAL_PX4

    SKETCHLIBS        :=    $(wildcard $(addprefix $(SKETCHBOOK)/libraries/,$(LIBTOKENS)))
    SKETCHLIBS = /ardupilot/libraries/$(LIBTOKENS)包含的目录

    SKETCHLIBSRCDIRS    :=    $(SKETCHLIBS) $(addsuffix /utility,$(SKETCHLIBS))
    SKETCHLIBSRCDIRS = /ardupilot/libraries/$(LIBTOKENS)包含的目录 /ardupilot/libraries/$(LIBTOKENS)包含的目录/utility

    SKETCHLIBSRCS        :=    $(wildcard $(foreach suffix,$(SRCSUFFIXES),$(addsuffix /$(suffix),$(SKETCHLIBSRCDIRS))))
    SKETCHLIBSRCS = /ardupilot/libraries/$(LIBTOKENS)包含的目录 和 /ardupilot/libraries/$(LIBTOKENS)包含的目录/utility目录中*.cpp文件扩展出来

    SKETCHLIBSRCSRELATIVE    :=    $(subst $(SKETCHBOOK)/,,$(SKETCHLIBSRCS))
    SKETCHLIBSRCSRELATIVE = $(SKETCHLIBSRCS) 去掉/ardupilot/部分,得到相对路径.

    PX4_V4_CONFIG_FILE=$(MK_DIR)/PX4/config_px4fmu-v4_APM.mk
    PX4_V4_CONFIG_FILE=/ardupilot/mk/PX4/config_px4fmu-v4_APM.mk


    export PX4_BASE         := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
    PX4_BASE = /ardupilot/modules/PX4Firmware

    export NUTTX_SRC     = $(abspath $(PX4_BASE)/NuttX/nuttx)/
    NUTTX_SRC=/ardupilot/modules/PX4Firmware/NuttX/nuttx/

    export ARCHIVE_DIR     = $(abspath $(PX4_BASE)/Archives)/
    ARCHIVE_DIR = /ardupilot/modules/PX4Firmware/Archives/

    export PX4_MK_DIR     = $(abspath $(PX4_BASE)/makefiles)/
    PX4_MK_DIR = /ardupilot/modules/PX4Firmware/makefiles

    export PX4_TARGET_OS      ?= nuttx
    
    BOARDS="px4fmu-v4"     make时带入
    
    NUTTX_ARCHIVES         = $(foreach board,$(BOARDS),$(ARCHIVE_DIR)$(board).export)
    NUTTX_ARCHIVES = /ardupilot/modules/PX4Firmware/Archives/px4fmu-v4.export

    KNOWN_CONFIGS        := $(subst config_,,$(basename $(notdir $(wildcard $(PX4_MK_DIR)/$(PX4_TARGET_OS)/config_*.mk))))
    KNOWN_CONFIGS = /ardupilot/modules/PX4Firmware/makefiles/nuttx目录下所有:去掉config_和.mk部分内容.如:px4fmu-v2_test, px4fmu-v4_APM等.
    CONFIGS            ?= $(KNOWN_CONFIGS)

    EXPLICIT_CONFIGS    := $(filter $(CONFIGS),$(MAKECMDGOALS))
    EXPLICIT_CONFIGS = px4fmu-v4_APM
    CONFIGS            := $(EXPLICIT_CONFIGS)

    export IMAGE_DIR     = $(abspath $(PX4_BASE)/Images)/
    IMAGE_DIR = /ardupilot/modules/PX4Firmware/Images/

    DESIRED_FIRMWARES      = $(foreach config,$(CONFIGS),$(IMAGE_DIR)$(config).px4)
    DESIRED_FIRMWARES = /ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4

    STAGED_FIRMWARES     = $(foreach config,$(KNOWN_CONFIGS),$(IMAGE_DIR)$(config).px4)
    STAGED_FIRMWARES =  /ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4一系列集合,跟随KNOWN_CONFIGS变化

    export BUILD_DIR     = $(abspath $(PX4_BASE)/Build)/
    BUILD_DIR = /ardupilot/modules/PX4Firmware/Build/

    FIRMWARES         = $(foreach config,$(KNOWN_CONFIGS),$(BUILD_DIR)$(config).build/firmware.px4)
    FIRMWARES = /ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build/firmware.px4等一些列集合对应STAGED_FIRMWARES

=======================================================================================================
makefile第一个目标:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
px4-v4: $(BUILDROOT)/make.flags CHECK_MODULES $(MAVLINK_HEADERS) $(UAVCAN_HEADERS) $(PX4_ROOT)/Archives/px4fmu-v4.export $(SKETCHCPP) module_mk
    $(v) echo Building px4-v4
    $(RULEHDR)
    $(v) cp $(PX4_V4_CONFIG_FILE) $(PX4_ROOT)/makefiles/nuttx/
    下面是编译ArduCopter以及其他模块,下面有介绍
    $(PX4_MAKE) px4fmu-v4_APM
    $(v) arm-none-eabi-size $(PX4_ROOT)/Build/px4fmu-v4_APM.build/firmware.elf
    $(v) cp $(PX4_ROOT)/Images/px4fmu-v4_APM.px4 $(SKETCH)-v4.px4
    $(v) mkdir -p $(MK_DIR)/PX4/ROMFS/bootloader/
    $(v) cp $(SKETCHBOOK)/mk/PX4/bootloader/px4fmuv4_bl.bin $(MK_DIR)/PX4/ROMFS/bootloader/fmu_bl.bin
    $(v) $(SKETCHBOOK)/Tools/scripts/add_git_hashes.py $(HASHADDER_FLAGS) "$(SKETCH)-v4.px4" "$(SKETCH)-v4.px4"
    $(v) echo "PX4 $(SKETCH) Firmware is in $(SKETCH)-v4.px4"

=======================================================================================================
$(BUILDROOT)/make.flags: FORCE    ###FORCE为空目标
    @mkdir -p $(BUILDROOT)      ###创建目录/ardupilot/Build.ArduCopter
    把环境变量的内容输出到make.flags.new
    @echo "// BUILDROOT=$(BUILDROOT) HAL_BOARD=$(HAL_BOARD) HAL_BOARD_SUBTYPE=$(HAL_BOARD_SUBTYPE) TOOLCHAIN=$(TOOLCHAIN) EXTRAFLAGS=$(EXTRAFLAGS)" > $(BUILDROOT)/make.flags.new
    ####判断环境变量变化没,变化了ArduCopter目录需要重新编译.删除了ArduCopter/*.o的话,需要重新编译.
    @cmp $(BUILDROOT)/make.flags $(BUILDROOT)/make.flags.new > /dev/null 2>&1 || rm -f $(SRCROOT)/*.o   
    @cmp $(BUILDROOT)/make.flags $(BUILDROOT)/make.flags.new > /dev/null 2>&1 || mv $(BUILDROOT)/make.flags.new $(BUILDROOT)/make.flags
    @rm -f $(BUILDROOT)/make.flags.new
    @cat $(BUILDROOT)/make.flags
=======================================================================================================
调度shell脚本,git方面的脚本,把各个模块下载完,如果我们已经下完,这里就没啥用了.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CHECK_MODULES:
    $(if $(BUILDSYS_DEPRECATED),$(call echoallwarnings))
    $(v)$(MK_DIR)/check_modules.sh

=======================================================================================================
这个目标就是生成mavlink协议的,使用python生成.如果我们想添加一条mavlink的命令,修改/ardupilot/modules/mavlink/message_definitions/v1.0/ardupilotmega.xml或common.xml,然后编译即可,编译后会生成对应的头文件,调用头文件的xxx_send就好了.mavlink协议解析在gcs_mavlink.cpp;GCS_MAVLINK_Copter::try_send_message发送命令,data_stream_send定时发送,由streamRates控制时间对应命令66设置;GCS_MAVLINK_Copter::handleMessage处理各种下发命令.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(MAVLINK_HEADERS): $(MESSAGE_DEFINITIONS)/ardupilotmega.xml $(MESSAGE_DEFINITIONS)/common.xml
    echo "Generating MAVLink headers..."
    #goto mavlink module directory and run the most recent generator script
    echo "Generating C code using mavgen.py located at" $(SKETCHBOOK)/modules/mavlink/
    PYTHONPATH=$(MAVLINK_DIR) python $(MAVLINK_DIR)/pymavlink/tools/mavgen.py --lang=C --wire-protocol=$(MAVLINK_WIRE_PROTOCOL) --output=$(MAVLINK_OUTPUT_DIR) $(MESSAGE_DEFINITIONS)/ardupilotmega.xml; if [ $$? -le 0 -o $$? -gt 128 ]; then echo "mavgen: success"; exit 0; else echo "mavgen: failed"; exit 1; fi
=======================================================================================================
不明
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(UAVCAN_HEADERS): $(UAVCAN_DSDL_MESSAGE_DEFINITIONS)
    @echo "Generating UAVCAN headers..."

#    PYTHONPATH=$(UAVCAN_DIR)libuavcan/dsdl_compiler/python $(UAVCAN_DIR)libuavcan/dsdl_compiler/setup.py build
#    PYTHONPATH=$(UAVCAN_DIR)libuavcan/dsdl_compiler/ python $(UAVCAN_DIR)libuavcan/dsdl_compiler/setup.py install

    PYTHONPATH=$(UAVCAN_DIRECTORY)/libuavcan/ python $(UAVCAN_DIRECTORY)/libuavcan/dsdl_compiler/libuavcan_dsdlc "$(UAVCAN_DIRECTORY)/dsdl/uavcan" -O"$(UAVCAN_GEN_INC)"

=======================================================================================================
这是编译nuttx系统
其实就是:make -C /ardupilot/modules/PX4Firmware -f /ardupilot/modules/PX4Firmware/Makefile.make NUTTX_SRC=/ardupilot/modules/PX4NuttX/nuttx/ CCACHE=(空) archives MAXOPTIMIZATION="-Os" BOARDS="px4fmu-v4"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(PX4_ROOT)/Archives/px4fmu-v4.export:
    $(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4fmu-v4"

=======================================================================================================
用于生成/ardupilot/module.mk文件,包含了/ardupilot/ArduCopter所有cpp文件,libraries包含路径的所有cpp文件.用于生成一个模块,nuttx脚本启动.
LIBUAVCAN_SRC := $(shell find $(LIBUAVCAN_DIR)src -type f -name '*.cpp') 先不看了.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
module_mk:
    $(v) echo "Building $(SKETCHBOOK)/module.mk"
    $(RULEHDR)
    $(v) echo "# Auto-generated file - do not edit" > $(SKETCHBOOK)/module.mk.new
    $(v) echo "MODULE_COMMAND = ArduPilot" >> $(SKETCHBOOK)/module.mk.new
    $(v) echo "SRCS = $(wildcard $(SRCROOT)/*.cpp) $(SKETCHLIBSRCSRELATIVE) $(LIBUAVCAN_SRC)" >> $(SKETCHBOOK)/module.mk.new
    $(v) echo "MODULE_STACKSIZE = 4096" >> $(SKETCHBOOK)/module.mk.new
    $(v) echo "EXTRACXXFLAGS = -Wframe-larger-than=1300" >> $(SKETCHBOOK)/module.mk.new
    $(v) cmp $(SKETCHBOOK)/module.mk $(SKETCHBOOK)/module.mk.new 2>/dev/null || mv $(SKETCHBOOK)/module.mk.new $(SKETCHBOOK)/module.mk
    $(v) rm -f $(SKETCHBOOK)/module.mk.new
    

=======================================================================================================
=======================================================================================================
=======================================================================================================
在Makefile.make文件中:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
archives:        checksubmodules $(NUTTX_ARCHIVES)
=======================================================================================================
也是检查git
*****
checksubmodules:
    $(Q) ($(PX4_BASE)/Tools/check_submodules.sh)
=======================================================================================================
********$(NUTTX_ARCHIVES):需要依赖$(ARCHIVE_DIR)%.export; 而$(ARCHIVE_DIR)%.export:需要依赖$(NUTTX_SRC)
/ardupilot/modules/PX4Firmware/Archives/%.export什么都没有.
编译nuttx系统,拷贝为/ardupilot/modules/PX4Firmware/Archives/px4fmu-v4.export.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(NUTTX_ARCHIVES): $(ARCHIVE_DIR)%.export: $(NUTTX_SRC)
    @$(ECHO) %% Configuring NuttX for $(board)
    $(Q) (cd $(NUTTX_SRC) && $(RMDIR) nuttx-export)
    $(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) distclean
    $(Q) (cd $(NUTTX_SRC)/configs && $(COPYDIR) $(PX4_BASE)nuttx-configs/$(board) .)
    $(Q) (cd $(NUTTX_SRC)tools && ./configure.sh $(board)/$(configuration))
    @$(ECHO) %% Exporting NuttX for $(board)
    $(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) CONFIG_ARCH_BOARD=$(board) export
    $(Q) $(MKDIR) -p $(dir $@)
    $(Q) $(COPY) $(NUTTX_SRC)nuttx-export.zip $@
    $(Q) (cd $(NUTTX_SRC)/configs && $(RMDIR) $(board))


=======================================================================================================
=======================================================================================================
=======================================================================================================
$(PX4_MAKE) px4fmu-v4_APM
其实就是调用Makefile.make中的:
$(EXPLICIT_CONFIGS):    all
all:    $(DESIRED_FIRMWARES)
$(DESIRED_FIRMWARES)是系列$(STAGED_FIRMWARES)的一个成员.

$(STAGED_FIRMWARES): $(IMAGE_DIR)%.px4: $(BUILD_DIR)%.build/firmware.px4
    @$(ECHO) %% Copying $@
    $(Q) $(COPY) $< $@
    $(Q) $(COPY) $(patsubst %.px4,%.bin,$<) $(patsubst %.px4,%.bin,$@)

就相当于只调用了:
/ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4: /ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4: /ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build/firmware.px4
    ....

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(BUILD_DIR)%.build/firmware.px4: config   = $(patsubst $(BUILD_DIR)%.build/firmware.px4,%,$@)
其中config = px4fmu-v4_APM等系列
$(BUILD_DIR)%.build/firmware.px4: work_dir = $(BUILD_DIR)$(config).build/
其中work_dir= /ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build系列.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generateuorbtopicheaders生成uorb头文件.
$(FIRMWARES): $(BUILD_DIR)%.build/firmware.px4:    generateuorbtopicheaders checksubmodules
    @$(ECHO) %%%%
    @$(ECHO) %%%% Building $(config) in $(work_dir)
    @$(ECHO) %%%%
    创建目录/ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build
    $(Q) $(MKDIR) -p $(work_dir)
    使用文件/ardupilot/modules/PX4Firmware/makefiles/firmware.mk再次mak.其中FIRMWARE_GOAL = firmware
    $(Q)+ $(MAKE) -r -C $(work_dir) \
        -f $(PX4_MK_DIR)firmware.mk \
        CONFIG=$(config) \
        WORK_DIR=$(work_dir) \
        $(FIRMWARE_GOAL)
这个makefile就不说了,他就是编译各个驱动模块的.下面目录定义了MODULES模块定义.
/ardupilot/modules/PX4Firmware/makefiles/nuttx.mk
/ardupilot/modules/PX4Firmware/makefiles/nuttx/config_px4fmu-v4_APM.mk
/ardupilot/mk/PX4/px4_common.mk
在文件Build/px4fmu-v4_APM.build/builtin_commands.c可以看到有哪些模块.



#######################################################################################################
启动过程:
__start(stm32_start.c)
    1-->初始化时钟,早期io口等
    1-->os_start(os_start.c)
        2-->初始化sem,中断向量表,线程,文件系统等
        2-->up_initialize()初始化了串口驱动,usb驱动.
        2-->os_bringup(os_bringup.c)
            3-->开了2个线程用于定时任务采样. 不过3.6版本后,除了uorb,fmu,adc,其他提到应用层做了.
            3-->启动进程CONFIG_USER_ENTRYPOINT-->nsh_main()
                4-->nsh_initialize()
                    5-->nsh_archinitialize()启动各种驱动,IO口,pwm,spi,sd卡
                4-->nsh_consolemain()
                    5-->nsh_initscript()启动脚本/etc/init.d/rcS
                    5-->nsh_session()用于支持终端交互,相应用户的shell命令,跟linux差不多(如busybox)

脚本:    ./mk/PX4/ROMFS/init.d/rcS
    挂载sd卡到文件系统.
    sh /etc/init.d/rc.APM启动另外一个脚本.
脚本1:    ./mk/PX4/ROMFS/init.d/rc.APM
    uorb start启动uorb,uorb其实就是利用文件通讯的通讯工具
    ArduPilot start启动应用程序.
应用程序入口ArduPilot_main()定义在文件AP_HAL_Main.h
    #define AP_HAL_MAIN_CALLBACKS(CALLBACKS) extern "C" { \
    int AP_MAIN(int argc, char* const argv[]); \
    int AP_MAIN(int argc, char* const argv[]) { \
    hal.run(argc, argv, CALLBACKS); \
    return 0; \
    } \
    }
在ArduCopter.cpp中:
    AP_HAL_MAIN_CALLBACKS(&copter);
展开:这种方式便于扩展到直升机等目录
    int ArduPilot_main(int argc, char* const argv[]);
    int ArduPilot_main(int argc, char* const argv[]) {
    hal.run(argc, argv, &copter);
    return 0;
    }
const AP_HAL::HAL& hal = AP_HAL::get_HAL();在copter.c定义.
对应原型在:HAL_PX4_Class.cpp
    const AP_HAL::HAL& AP_HAL::get_HAL() {
        static const HAL_PX4 hal_px4;
        return hal_px4;
    }
主程序跳转到HAL_PX4::run()
    启动主函数main_loop():配置串口;scheduler任务管理器初始化;调用copter.setup(),ArduCopter.cpp这个函数就是初始化px4所有内容;每隔250us循环调度copter.loop()

=======================================================================================================
Copter::setup()-->init_ardupilot
    加载参数;串口管理器初始化;gcs初始化;BoardConfig板级初始化;notify灯和其他通知;battery电池;barometer气压计;init_rc_in遥控器输入初始化;allocate_motors电机对象分配空间,以及初始化参数;init_rc_out电机输出初始化,其中校准电调esc也在这里;gps初始化,gps是自动查询;init_optflow光流传感器;init_precland精准降落,irlock用的比较多;mission是任务,地面站配置航线,保存在飞控的任务;startup_INS_ground初始化ins(惯行传感器,就是角速度计与陀螺仪);init_compass初始化磁罗盘;其他按照其字面意思也能看懂,就不提了.
    ******注意:参数保存格式是4+n个字节,而内存格式是类,参考AP_PARAMDEF(float, Float, AP_PARAM_FLOAT)进一步了解吧.参数结构做的很好,但是遍历是链表形式,比较慢.还有就是在3.4以前,gcs刷参数是一直刷,3.6现在是1m退出.
初始化中:BoardConfig.init()-->px4_setup()
    ******注意一个问题:task_spawn调用进程后,如果该进程完成,再调用waitpid,此时得到的pid为-1,而不是task_spawn创建的pid.这个跟vfork区别开.
    -->px4_setup_peripherals()开个进程给ADC驱动,启动fmu,初始化gpio管理起,rcin遥控器输入初始化,rcout电机输出初始化.
    =====fmu是用来处理gpio驱动,rcin-->sbus,rcout-->pwm输出的.通过/dev/px4fmu系列设备文件通讯
    -->px4_setup_pwm(),配置几轴飞机,也就是几路pwm输出
    -->px4_setup_safety_mask(),初始化pwm输出,并且除了配置的pwm输出,其他pwm不能通过这个文件配置.就是设置保护.
    -->px4_setup_uart不用
    -->px4_setup_sbus暂不用,可以配置sbus输出到rcout,我们用pwm输出
    -->px4_setup_drivers()对fmu进行sensor_reset 20
初始化IMU就说一个,磁罗盘是一样的:startup_INS_ground()-->ins.init(scheduler.get_loop_rate_hz());-->AP_InertialSensor::init()-->_start_backends()-->detect_backends()
板级配置默认:AP_BoardConfig::PX4_BOARD_PIXRACER
    对应添加mpu6000传感器,_add_backend(AP_InertialSensor_Invensense::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME), ROTATION_ROLL_180))
    AP_InertialSensor_Invensense::_init-->_hardware_init去配置寄存器,看这个设备在不在.如果不能获取,说明imu有问题.
    3.4之前mpu6000做在驱动里面的,应用层是通过读取uorb或文件来获得数据,现在使用线程直接读取:
    AP_InertialSensor_Invensense::start-->   _dev->register_periodic_callback(1000, FUNCTOR_BIND_MEMBER(&AP_InertialSensor_Invensense::_poll_data, void));
=======================================================================================================
Copter::loop()
{
    -->Copter::fast_loop()
    {
        -->ins.update();读取加速度和陀螺仪数据.
        计算混合油门(这个值用于飞行时(THR_MIX_MAX)姿态控制占油门的比例大小,降落时(THR_MIX_MIN)着陆判断);pid计算roll,pitch,yaw输出.
        -->attitude_control->rate_controller_run();-->AC_AttitudeControl_Multi::rate_controller_run
        -->motors_output();-->motors->output();-->AP_MotorsMulticopter::output()
        {
            // update throttle filter滤波
            update_throttle_filter();
            // calc filtered battery voltage and lift_max,这个_batt_voltage_max=0;所以直接退出了
            update_lift_max_from_batt_voltage();
            // run spool logic.这是pwm输出的逻辑,解锁时,以_spin_arm带速旋转.
            output_logic();
            // calculate thrust通过roll,pitch,yaw,油门计算每个电机的推力.AP_MotorsMatrix::output_armed_stabilizing
            output_armed_stabilizing();
            // apply any thrust compensation for the frame无用
            thrust_compensation();
            // convert rpy_thrust values to pwm.计算处理的推力转换为pwm到电机上.如果是SHUT_DOWN输出最小值,SPIN_WHEN_ARMED输出带速,其他根据计算出的推力输出.
            output_to_motors();
            // output any booster throttle无用
            output_boost_throttle();
        }
        
        -->read_AHRS();
        {
            copter.h定义:AP_AHRS_NavEKF ahrs;
            这里是姿态解算核心代码
            ahrs.update(true);-->AP_AHRS_NavEKF::update
            {
                AP_AHRS_DCM::update()初步计算陀螺仪的数据,以及漂移
                update_EKF2();-->EKF2.UpdateFilter();-->NavEKF2::UpdateFilter()-->core[i].UpdateFilter(statePredictEnabled[i]);-->NavEKF2_core::UpdateFilter
                这里就是ekf算法核心内容,我也没看懂,不好意思.计算包括roll,pitch,yaw,还有3d位置/速度等
            }
        }

        -->read_inertia();把ekf算出来的数据,转到inertial_nav惯行系统里面,用于后面各个飞行模式使用.

        -->check_ekf_reset();ekf几组计算core对应ins对数组,如果某一core计算数据方差太大,切换至另外一组core计算.这个函数只是上报给gcs和写入日志

        -->update_flight_mode();这里就是飞行控制模块了.
        {
            STABILIZE =     0,  //手动模式,遥控器输入转换为角度,再通过角度->角速度控制飞机.油门直接控制飞机加速度manual airframe angle with manual throttle
            ACRO =          1,  //杂技模式,遥控器输入直接到输出 manual body-frame angular rate with manual throttle
            ALT_HOLD =      2,  //高度保持,油门归中时,高度保持,但水平会有漂移.油门控制飞机速度,roll/pitch控制角度.manual airframe angle with automatic throttle
            AUTO =          3,  //自动模式,mission在此时就用到了,根据配置的任务执行.除yaw其他不可控 fully automatic waypoint control using mission commands
            GUIDED =        4,  //指点模式,飞机飞向自定坐标,除yaw其他不可控  fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands
            LOITER =        5,  //游荡,没用过 automatic horizontal acceleration with automatic throttle
            RTL =           6,  //返航,回到home点,然后降落.油门不可控,roll/pitch转为速度控制 automatic return to launching point
            CIRCLE =        7,  //飞圆圈 automatic circular flight with automatic throttle
            LAND =          9,  //降落 automatic landing with horizontal position control
            DRIFT =        11,  // semi-automous position, yaw and throttle control
            SPORT =        13,  // manual earth-frame angular rate control with manual throttle
            FLIP =         14,  // automatically flip the vehicle on the roll axis
            AUTOTUNE =     15,  // automatically tune the vehicle's roll and pitch gains
            POSHOLD =      16,  //定点模式,3d位置定点loiter,油门转为速度控制,roll/pitch/yaw转为角度控制 automatic position hold with manual override, with automatic throttle
            BRAKE =        17,  // full-brake using inertial/GPS system, no pilot input
            THROW =        18,  // throw to launch mode using inertial/GPS system, no pilot input
            AVOID_ADSB =   19,  // automatic avoidance of obstacles in the macro scale - e.g. full-sized aircraft
            GUIDED_NOGPS = 20,  // guided mode but only accepts attitude and altitude
            油门就是控制飞机垂直方向的动力.手动模式下,油门直接转为加速度,参与pid计算;而在poshold,alt_hold,rtl,land模式下,他们都是通过位置->速度->加速度来控制垂直动力,而油门可用情况下是转换为了请求速度,再通过p->v->a控制.
            roll/pitch.手动模式/poshold下,通过角度->角速度进行pid计算.在poshold/guid/auto模式下,通过位置->速度->加速度控制飞机位置,roll/pitch不可控;rtl与land模式下,roll/pitch换算为请求水平加速度,再添加到pos中,再通过p->v->a控制->角度->角速度.

        }

        -->update_home_from_EKF();计算home的距离

        -->update_land_and_crash_detectors();
    }
    处理其他scheduler_tasks任务.
    scheduler.run(time_available > MAIN_LOOP_MICROS ? 0u : time_available);
}


原创粉丝点击