PX4学习No.3—启动流程(从上电开始)

1. 上电后先是bootloader(引导程序,负责引导进入Nuttx系统)

理解:bootloader(BL)其实就是一个引导程序,stm芯片的引导程序是STM32 BootROM之类的,和PX4的BL不是同一样东西。BOOT0是一个键位,如果是0那么进入DFU模式,如果是1,那么默认进入PX4 的BL中。NuttX 是一个类为 POSIX 的实时操作系统(RTOS),PX4 在 STM32H7 等 MCU 上就是跑的它

bootloader阶段流程:

上电后,FMU 的BL和IO的BL都并行跑:初始化最基本的时钟/USB/LED;

打开一个几秒钟的“等待更新”窗口(USB 会枚举成 Bootloader 设备);

这时用 QGC/make … upload 能直接刷固件;

如果窗口期没被“抓住”,且检测到应用固件有效,就跳转到应用(NuttX+PX4)。
大概流程如下:
在这里插入图片描述
先分别烧写 IO 和 FMU 的 Bootloader;随后用地面站把 FMU 应用固件(.px4,内含 IO 固件镜像)刷入 FMU。上电后,FMU 通过 PX4 Bootloader 跳转运行 NuttX + PX4 应用;应用启动过程中会检测 IO(STM32F103)上的固件,若版本不匹配或缺失,则让 IO 进入其 Bootloader 并自动下发更新,完成后 IO 启动应用,整机进入正常工作。

src/modules/px4iofirmware这里会有IO的操作和安全开关的操作。他会在编译飞控固件的时候,一起被编译成为.bin,放在Nuttx文件系统中,在主处理器运行的时候把这个固件烧写进入协处理器。具体的烧写到单片机的FLASH由src/drivers/px4io/px4io.cpp文件设置,一般是0x80000000这个初始为位置。

2. 跳入 NuttX 内核:__start → nx_start → nx_bringup → 启动用户入口任务(CONFIG_INIT_ENTRYPOINT,如 nsh_main),随后执行 /etc/init.d/rcS

2.1 platforms/nuttx/NuttX/nuttx/arch/arm/src/stm32/stm32_start.c

复位后 CPU 跑的第一段 C 代码,把最底层的内存、时钟、外设最小化初始化好,然后才把控制权交给 NuttX 内核nx_start()

复位入口 __start():下面我放核心代码

 stm32_clockconfig();  // 配置系统时钟树(HSE/PLL/分频),极其关键
  arm_fpuconfig();      // 使能 FPU(Cortex-M4/M7 等)
  stm32_lowsetup();     // 早期串口初始化(为 showprogress 和崩溃输出服务)
  stm32_gpioinit();     // 基础 GPIO 初始化(如默认上拉/片选/LED)
  showprogress('A');
  stm32_boardinitialize();
  showprogress('F');
 /* Then start NuttX */

  showprogress('\r');
  showprogress('\n');

  nx_start();

2.2 platforms/nuttx/NuttX/nuttx/sched/init/nx_start.c

此时会初始化内核各子系统,随后由以下代码跳入nx_bringup :

  /* Create initial tasks and bring-up the system */

  DEBUGVERIFY(nx_bringup());

2.3 platforms/nuttx/NuttX/nuttx/sched/init/nx_bringup.c

在nx_bringup.c中会进行基本进程的启动和用户进程的启动,在改函数中重点关注:

  nx_create_initthread();
static inline void nx_create_initthread(void)
{
#ifdef CONFIG_BOARD_LATE_INITIALIZE
  int pid;

  /* Do the board/application initialization on a separate thread of
   * execution.
   */

  pid = kthread_create("AppBringUp", CONFIG_BOARD_INITTHREAD_PRIORITY,
                      CONFIG_BOARD_INITTHREAD_STACKSIZE,
                      (main_t)nx_start_task, (FAR char * const *)NULL);
  DEBUGASSERT(pid > 0);
  UNUSED(pid);
#else
  /* Do the board/application initialization on this thread of execution. */

  nx_start_application();
#endif
}
  nx_start_application();
static inline void nx_start_application(void)
{
#ifdef CONFIG_INIT_ARGS
  FAR char *const argv[] =
  {
    CONFIG_INIT_ARGS,
    NULL,
  };
#else
  FAR char *const *argv = NULL;
#endif
  int ret;
#ifdef CONFIG_INIT_FILE
  posix_spawnattr_t attr;
#endif

#ifdef CONFIG_BOARD_LATE_INITIALIZE
  /* Perform any last-minute, board-specific initialization, if so
   * configured.
   */

  board_late_initialize();
#endif

#if defined(CONFIG_INIT_ENTRY)

  /* Start the application initialization task.  In a flat build, this is
   * entrypoint is given by the definitions, CONFIG_INIT_ENTRYPOINT.  In
   * the protected build, however, we must get the address of the
   * entrypoint from the header at the beginning of the user-space blob.
   */

  sinfo("Starting init thread\n");

#ifdef CONFIG_BUILD_PROTECTED
  DEBUGASSERT(USERSPACE->us_entrypoint != NULL);
  ret = nxtask_create(CONFIG_INIT_ENTRYNAME, CONFIG_INIT_PRIORITY,
                      CONFIG_INIT_STACKSIZE,
                      USERSPACE->us_entrypoint, argv);
#else
  ret = nxtask_create(CONFIG_INIT_ENTRYNAME, CONFIG_INIT_PRIORITY,
                      CONFIG_INIT_STACKSIZE,
                      (main_t)CONFIG_INIT_ENTRYPOINT, argv);
#endif
  DEBUGASSERT(ret > 0);

#elif defined(CONFIG_INIT_FILE)

#ifdef CONFIG_INIT_MOUNT
  /* Mount the file system containing the init program. */

  ret = nx_mount(CONFIG_INIT_MOUNT_SOURCE, CONFIG_INIT_MOUNT_TARGET,
                 CONFIG_INIT_MOUNT_FSTYPE, CONFIG_INIT_MOUNT_FLAGS,
                 CONFIG_INIT_MOUNT_DATA);
  DEBUGASSERT(ret >= 0);
#endif

  /* Start the application initialization program from a program in a
   * mounted file system.  Presumably the file system was mounted as part
   * of the board_late_initialize() operation.
   */

  sinfo("Starting init task: %s\n", CONFIG_INIT_FILEPATH);

  posix_spawnattr_init(&attr);

  attr.priority  = CONFIG_INIT_PRIORITY;
#ifndef CONFIG_ARCH_ADDRENV
  attr.stacksize = CONFIG_INIT_STACKSIZE;
#endif
  ret = exec_spawn(CONFIG_INIT_FILEPATH, argv, NULL,
                   CONFIG_INIT_SYMTAB, CONFIG_INIT_NEXPORTS, &attr);
  DEBUGASSERT(ret >= 0);
#endif

  UNUSED(ret);
}
  ret = nxtask_create(CONFIG_INIT_ENTRYNAME, CONFIG_INIT_PRIORITY,
                      CONFIG_INIT_STACKSIZE,
                      (main_t)CONFIG_INIT_ENTRYPOINT, argv);

CONFIG_INIT_ENTRYPOINT 正是主处理器的用户入口
CONFIG_INIT_ENTRYPOINT指向的是nsh_main函数(platforms/nuttx/NuttX/apps/system/nsh/nsh_main.c)
在这里插入图片描述

2.4 platforms/nuttx/NuttX/apps/system/nsh/nsh_main.c

在nsh_main.c中回调用platforms/nuttx/NuttX/apps/nshlib/nsh_consolemain.c这个函数,然后这个函数又调用platforms/nuttx/NuttX/apps/nshlib/nsh_script.c这个函数,最后这个script就是启动脚本rcS的启动函数

#if defined(CONFIG_NSH_ROMFSETC) && !defined(CONFIG_NSH_DISABLESCRIPT)
  /* Execute the start-up script */

  nsh_initscript(&pstate->cn_vtbl);
int nsh_initscript(FAR struct nsh_vtbl_s *vtbl)
{
  static bool initialized;
  bool already;
  int ret = OK;

  /* Atomic test and set of the initialized flag */

  sched_lock();
  already     = initialized;
  initialized = true;
  sched_unlock();

  /* If we have not already executed the init script, then do so now */

  if (!already)
    {
      ret = nsh_script_redirect(vtbl, "init", NSH_INITPATH);
#ifndef CONFIG_NSH_DISABLESCRIPT
      /* Reset the option flags */

      vtbl->np.np_flags = NSH_NP_SET_OPTIONS_INIT;
#endif
    }

  return ret;
}

在这里会用到一个一个常量是一个常量,已经配置好地址了,指向的就是FMU的启动脚本rcS

#  ifndef CONFIG_NSH_INITSCRIPT
#    define CONFIG_NSH_INITSCRIPT "init.d/rcS"

位于PX4-Autopilot/ROMFS/px4fmu_common/init.d/rcS

3. 用户入口总结

上述说的只是FMU主处理器的的用户入口。
IO的用户入口在
src/modules/px4iofirmware/px4io.cpp 中有一个user_start函数

extern "C" __EXPORT int user_start(int argc, char *argv[])

4. rcS 启动脚本(全代码解释)

通过rcS脚本来设定需要启动的程序,比如设备驱动、控制模块、数据通信等。rcS脚本在项目中的文件位置PX4-Autopilot/ROMFS/px4fmu_common/init.d/rcS

4.1 头部与全局变量

set +e                               # 出错不中断执行(便于尽量把系统拉起来) // 调试期更容易看到整体进度
# set -x                             # 打开后逐行打印执行命令 // 强烈建议调试时启用

set R /                              # ROMFS 根路径变量 // 后面拼接 etc/init.d/...
set FCONFIG /fs/microsd/etc/config.txt  # SD卡用户覆盖参数脚本 // “软改参数”的常用入口
set FEXTRAS /fs/microsd/etc/extras.txt  # SD卡用户附加启动脚本 // 追加启动步骤
set FRC /fs/microsd/etc/rc.txt          # SD卡完全自定义 rc 脚本 // 存在时会跳过默认自动启动
set IOFW "/etc/extras/px4_io-v2_default.bin"  # IO 协处理器固件路径 // 有IO才会用到
set LOGGER_ARGS ""                   # 日志模块附加参数 // 空表示默认
set LOGGER_BUF 8                     # 日志环形缓冲区大小(KiB) // 小内存板子常调
set PARAM_FILE ""                    # 参数主文件路径占位 // 后面根据存储介质设置
set PARAM_BACKUP_FILE ""             # 参数备份文件 // 导入失败时回退
set RC_INPUT_ARGS ""                 # rc_input 附加参数 // 例如选择输入源
set STORAGE_AVAILABLE no             # 是否有可用存储(SD或MTD) // 默认无
set SDCARD_EXT_PATH /fs/microsd/ext_autostart  # 外部自动启动目录 // 支持打包拷贝
set SDCARD_FORMAT no                 # 是否需要格式化SD // 由标记文件触发
set STARTUP_TUNE 1                   # 启动提示音编号 // 1=默认,错误时会改成2
set VEHICLE_TYPE none                # 机型类型(多旋翼/固定翼/VTOL等) // 由 airframe 决定

set PARAM_DEFAULTS_VER 1             # 机型参数版本号 // 变更时触发“重置到机型默认”
ver all                              # 打印固件/硬件/版本信息 // 第一处健康检查输出

4.2 SD卡挂载与初始化

if [ -b "/dev/mmcsd0" ]              # 检测SD块设备是否存在 // 有无卡/硬件连通
then
    if mount -t vfat /dev/mmcsd0 /fs/microsd  # 挂载为 FAT32 到 /fs/microsd // 成功则可读写
    then
        if [ -f "/fs/microsd/.format" ]      # 特殊文件触发格式化 // 手动放置用于一键清卡
        then
            set SDCARD_FORMAT yes            # 标记需要格式化 // 避免误删后继续
            rm /fs/microsd/.format           # 清理触发文件 // 防止下次再触发
            umount /fs/microsd               # 先卸载再格式化 // 必须步骤
        else
            set STORAGE_AVAILABLE yes        # 正常挂载完成 // 后续可读写参数
        fi
    fi

    if [ $STORAGE_AVAILABLE = no -o $SDCARD_FORMAT = yes ]  # 未挂载成功或需要格式化
    then
        set STARTUP_TUNE 15                  # 先切到SD错误提示音(后面成功会改回) // 声音反馈
        if mkfatfs -F 32 /dev/mmcsd0         # 格式化为 FAT32 // 常用于新卡或损坏卡
        then
            if mount -t vfat /dev/mmcsd0 /fs/microsd  # 格式化后再挂载
            then
                set STORAGE_AVAILABLE yes
                set STARTUP_TUNE 14          # SD初始化成功提示音 // 声音确认
            else
                echo "ERROR [init] card mount failed"  # 挂载失败日志 // 排查卡/座/供电
            fi
        else
            echo "ERROR [init] format failed"         # 格式化失败 // 可能卡坏或只读
        fi
    fi
else
    if mft query -q -k MTD -s MTD_PARAMETERS -v /mnt/microsd  # 使用板载MTD分区替代SD
    then
        set STORAGE_AVAILABLE yes            # 将 /mnt/microsd 当作存储根 // 工厂/无卡场景
    fi
fi

4.3 存储就绪后的维护动作

if [ $STORAGE_AVAILABLE = yes ]
then
    if hardfault_log check                 # 检查上次崩溃/硬错日志 // 若存在则上报并清理
    then
        set STARTUP_TUNE 2                 # 错误提示音 // 告知上电有错误记录
        if hardfault_log commit; then hardfault_log reset; fi  # 提交并复位日志
    fi

    if [ -e /fs/microsd/ext_autostart_new ]   # 检查是否有新外部启动包
    then
        rm -r $SDCARD_EXT_PATH               # 删除旧的 ext_autostart
        mv /fs/microsd/ext_autostart_new $SDCARD_EXT_PATH  # 替换为新包
    fi

    set PARAM_FILE /fs/microsd/params        # 设置参数主文件路径 // 后续 param import 用
    set PARAM_BACKUP_FILE "/fs/microsd/parameters_backup.bson"  # 备份路径
fi

4.4 外部完全自定义 rc(若存在则优先)

if [ -f $FRC ]                       # /fs/microsd/etc/rc.txt 是否存在
then
    . $FRC                           # 直接执行外部 rc // 将跳过默认自动启动全流程
else
    . ${R}etc/init.d/rc.filepaths    # 加载路径配置 // 由固件生成的标准路径集

4.5 参数加载与重置机制

if ! bsondump docsize /fs/mtd_caldata    # 检查工厂校准BSON文件结构 // 非致命
then
    bsondump docsize /fs/mtd_caldata     # 打印新大小信息 // 便于你核对
fi

if mft query -q -k MTD -s MTD_CALDATA -v /fs/mtd_caldata  # 若存在校准分区
then
    param load /fs/mtd_caldata           # 先加载校准参数 // 保证校准最先生效
fi

param select $PARAM_FILE                 # 选择主参数文件
if ! param import                        # 尝试导入参数
then
    set STARTUP_TUNE 2                   # 参数导入失败,鸣错音
    bsondump $PARAM_FILE                 # dump 内容协助排错
    if [ -d "/fs/microsd" ]
    then
        cp $PARAM_FILE /fs/microsd/param_import_fail.bson  # 备份坏文件
        if [ -f $PARAM_BACKUP_FILE ]     # 尝试从备份导入
        then
            bsondump $PARAM_BACKUP_FILE  # 打印备份用于对比
            param import $PARAM_BACKUP_FILE
            cp $PARAM_BACKUP_FILE $PARAM_FILE  # 用备份覆盖坏的主文件
        fi
        param status                     # 打印参数状态
        dmesg >> /fs/microsd/param_import_fail.txt &  # 记录内核日志方便分析
    fi
fi

if [ $STORAGE_AVAILABLE = yes ]
then
    param select-backup $PARAM_BACKUP_FILE  # 开启参数自动备份 // 后续变更会写入备份
fi

if mft query -q -k MFT -s MFT_ETHERNET -v 1   # 若板上有以太网
then
    netman update -i eth0                    # 更新网络配置 // DHCP/静态按板级配置
fi

if param greater SYS_AUTOCONFIG 0         # 若需一次性重置到机型默认
then
    param reset_all SYS_AUTOSTART SYS_PARAM_VER RC* CAL_* COM_FLTMODE* LND_FLIGHT* TC_* COM_FLIGHT*  
    # 重置时保留:机型编号、参数版本、RC校准、传感器校准、飞行模式等关键项 // 防止“白板化”
fi

4.6 板级默认脚本

set BOARD_ARCH_RC_DEFAULTS ${R}etc/init.d/rc.board_arch_defaults  # 架构级默认 // 很少需要改
if [ -f $BOARD_ARCH_RC_DEFAULTS ]; then . $BOARD_ARCH_RC_DEFAULTS; fi

set BOARD_RC_DEFAULTS ${R}etc/init.d/rc.board_defaults            # 板级默认 // 你改以太网/MAV_2_*/INA等
if [ -f $BOARD_RC_DEFAULTS ]; then . $BOARD_RC_DEFAULTS; fi

4.7 机型选择 + 机型参数版本校验

if ! param compare SYS_AUTOSTART 0   # 选择了某个 airframe
then
    . ${R}etc/init.d/rc.autostart    # 按编号执行对应机型脚本(会设置 VEHICLE_TYPE)
    if [ ${VEHICLE_TYPE} == none ]   # 若ROMFS无匹配,尝试SD卡外部机型
    then
        . ${R}etc/init.d/rc.autostart_ext
    fi
    if [ ${VEHICLE_TYPE} == none ]   # 仍未找到,报错并清空SYS_AUTOSTART
    then
        param set SYS_AUTOSTART 0
        tune_control play error
    fi
fi

if ! param compare SYS_PARAM_VER ${PARAM_DEFAULTS_VER}  # 机型参数版本变化
then
    param set SYS_PARAM_VER ${PARAM_DEFAULTS_VER}
    param set SYS_AUTOCONFIG 1       # 标记下一次重启重置到机型默认
    param save
    reboot                           # 立即重启 // 防止“param set”与机型默认冲突
fi

4.8 基础服务与LED、用户覆盖脚本

tone_alarm start                     # 蜂鸣器/提示音驱动 // 需在加载完参数后启动
# dataman 后端(航点/任务存储)
if param compare -s SYS_DM_BACKEND 1; then dataman start -r; 
elif param compare SYS_DM_BACKEND 0; then dataman start; fi

send_event start                     # 事件发送器(socket接口) // 内部监控/事件上报
load_mon start                       # 资源负载监控 // CPU/内存/栈
rgbled start -X -q                   # 板载/外部RGB LED驱动(多种型号) // -X外设口,-q静默
rgbled_ncp5623c start -X -q
rgbled_lp5562 start -X -q
rgbled_is31fl3195 start -X -q

if [ -f $FCONFIG ]; then . $FCONFIG; fi  # SD卡自定义参数覆盖 // 便于现场调参

4.9 传感器系统(HITL/真实硬件两条路)

if param greater SYS_HITL 0
then
    sensors start -h                 # 以HITL模式启动传感器框架 // 仿真输入
    param set GPS_1_CONFIG 0         # 关闭真实GPS // 防止冲突
    if param compare SYS_HITL 2      # 2=SIH仿真
    then
        simulator_sih start
        sensor_baro_sim start
        sensor_mag_sim start
        sensor_gps_sim start
        sensor_agp_sim start
    fi
else
    set BOARD_RC_SENSORS ${R}etc/init.d/rc.board_sensors  # 板级传感器清单(你要改的地方)
    if [ -f $BOARD_RC_SENSORS ]; then . $BOARD_RC_SENSORS; fi
    . ${R}etc/init.d/rc.sensors       # 通用传感器/电池源等
    if param compare -s BAT1_SOURCE 2; then esc_battery start; fi
    if ! param compare BAT1_SOURCE 1; then battery_status start; fi
    sensors start                     # 启动传感器系统(汇总/选主/发布) // 统一入口
fi

4.10 状态估计器选择

if param compare -s EKF2_EN 1; then ekf2 start &; fi        # 标准EKF2 // 后台起
if param compare -s LPE_EN 1; then local_position_estimator start; fi  # LPE可选
if param compare -s ATT_EN 1; then attitude_estimator_q start; fi      # AHRS简化姿态估计

4.11 PX4IO 协处理器

if px4io supported                 # 若硬件支持IO协处理器
then
    if [ -f $IOFW ]                # 有IO固件包
    then
        if ! px4io checkcrc ${IOFW}      # 校验IO固件CRC,不一致则升级
        then
            tune_control play -t 16       # 升级开始提示音
            if px4io update ${IOFW}       # 执行升级
            then
                tune_control stop
                if px4io checkcrc ${IOFW}; then tune_control play -t 17; else tune_control play -t 18; fi
            else
                tune_control stop
            fi
        fi
        if ! px4io start                  # 启动IO驱动失败则报错音
        then
            set STARTUP_TUNE 2
        fi
    fi
fi

4.12 其它设备与手动输入

if param compare -s SENS_EN_THERMAL 1; then heater start; fi  # IMU加热

rc_update start                       # RC通道映射/校准辅助 // Commander前启动
manual_control start                  # 手动控制话题发布 // 支持遥控/手柄
# 相机/时间戳/RPM捕获(按参数启用)
if param greater -s TRIG_MODE 0; then camera_trigger start; camera_feedback start; fi
if param greater -s PPS_CAP_ENABLE 0; then pps_capture start; fi
if param greater -s RPM_CAP_ENABLE 0; then rpm_capture start; fi
if param greater -s CAM_CAP_FBACK 0; then if camera_capture start; then camera_capture on; fi; fi

4.13 Commander 与 PWM/DShot 输出

if param greater SYS_HITL 0
then
    commander start -h                # 仿真模式Commander
    if ! pwm_out_sim start -m hil; then tune_control play error; fi
else
    commander start                   # 实机Commander(状态机/解锁/故障判断)
    dshot start                       # 若使用DShot电调 // 可失败但不致命
    pwm_out start                     # PWM输出驱动 // 电机/舵机核心
fi

. ${R}etc/init.d/rc.vehicle_setup     # 机型特定参数与功能 // 多旋翼/固定翼/VTOL分支
if param compare -s MBE_ENABLE 1; then mag_bias_estimator start; fi  # 起飞前持续磁偏估计

4.14 板级 Mavlink、串口 & RC输入、USB

set BOARD_RC_MAVLINK ${R}etc/init.d/rc.board_mavlink
if [ -f $BOARD_RC_MAVLINK ]; then . $BOARD_RC_MAVLINK; fi   # 板级自定义Mavlink流(如以太网)

. ${R}etc/init.d/rc.serial            # 自动生成串口映射(GPS/RTK/TELEM等)
rc_input start $RC_INPUT_ARGS          # 读取物理RC输入(SBus/DSM/PPM/UAVCAN等)

if param greater -s SYS_USB_AUTO -1    # USB自动枚举与MAVLink
then
    if ! cdcacm_autostart start        # 若失败则回退到 sercon + ttyACM0
    then
        sercon
        mavlink start -d /dev/ttyACM0  # 保障与QGC的基本链路
    fi
fi

4.15 提示音、导航、热校准

param compare CBRK_BUZZER 782090
if [ "$?" != "0" -o "$STARTUP_TUNE" != "1" ]  # 若未禁用蜂鸣或之前设为错误音
then
    tune_control play -t $STARTUP_TUNE        # 播放最终提示音(成功/失败/SD_INIT等)
fi

navigator start                      # 航迹/任务/模式导航模块

set RC_THERMAL_CAL ${R}etc/init.d/rc.thermal_cal
if [ -f ${RC_THERMAL_CAL} ]; then . ${RC_THERMAL_CAL}; fi  # 热校准脚本(可选)

4.16 选择性功能(按需)

if param greater -s MNT_MODE_IN -1; then gimbal start; fi     # 云台
if param compare -s TEL_BST_EN 1; then bst start -X; fi       # BlackSheep 遥测
if param compare -s IMU_GYRO_FFT_EN 1; then gyro_fft start; fi  # 陀螺FFT噪声谱
if param compare -s IMU_GYRO_CAL_EN 1; then gyro_calibration start; fi
if param compare -s SENS_EN_PX4FLOW 1; then px4flow start -X &; fi  # 光流
payload_deliverer start                                       # 载荷投放
if param compare -s ICE_EN 1; then internal_combustion_engine_control start; fi  # 内燃机控制

4.17 板级附加/SD附加/日志/机型后置/引导器升级

set BOARD_RC_EXTRAS ${R}etc/init.d/rc.board_extras
if [ -f $BOARD_RC_EXTRAS ]; then . $BOARD_RC_EXTRAS; fi       # 板厂自定义扩展

if [ -f $FEXTRAS ]; then . $FEXTRAS; fi                       # SD卡 addons:你自己的附加指令

set RC_LOGGING ${R}etc/init.d/rc.logging
if [ -f ${RC_LOGGING} ]; then . ${RC_LOGGING}; fi             # 日志配置(文件/速率/模式等)

if ! param compare SYS_AUTOSTART 0; then . ${R}etc/init.d/rc.autostart.post; fi  # 机型后置修订

set BOARD_BOOTLOADER_UPGRADE ${R}etc/init.d/rc.board_bootloader_upgrade
if [ -f $BOARD_BOOTLOADER_UPGRADE ]; then sh $BOARD_BOOTLOADER_UPGRADE; fi        # 需要时升级bootloader

4.18 UAVCAN / Cyphal / Zenoh

if param greater -s UAVCAN_ENABLE 0
then
    if ! uavcan start; then tune_control play error; fi       # UAVCAN 栈
else
    if param greater -s CYPHAL_ENABLE 0; then cyphal start; fi # Cyphal(UAVCAN v1)
fi
if param greater -s ZENOH_ENABLE 0; then zenoh start; fi       # 分布式中间件(可选)

4.19 清理环境变量 & 启动完成

unset R FCONFIG FEXTRAS FRC IOFW LOGGER_ARGS LOGGER_BUF PARAM_FILE PARAM_BACKUP_FILE  # 统一释放变量 // 省内存
unset PARAM_DEFAULTS_VER RC_INPUT_ARGS STORAGE_AVAILABLE SDCARD_EXT_PATH SDCARD_FORMAT STARTUP_TUNE VEHICLE_TYPE

mavlink boot_complete                 # 通知MAVLink:系统启动完成 // QGC状态会切换为Ready

下面是借用其他博主的图片进行图解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值