文章目录
- 1. 上电后先是bootloader(引导程序,负责引导进入Nuttx系统)
- 2. 跳入 NuttX 内核:__start → nx_start → nx_bringup → 启动用户入口任务(CONFIG_INIT_ENTRYPOINT,如 nsh_main),随后执行 /etc/init.d/rcS
- 2.3 platforms/nuttx/NuttX/nuttx/sched/init/nx_bringup.c
- 3. 用户入口总结
- 4. rcS 启动脚本(全代码解释)
- 4.1 头部与全局变量
- 4.2 SD卡挂载与初始化
- 4.3 存储就绪后的维护动作
- 4.4 外部完全自定义 rc(若存在则优先)
- 4.5 参数加载与重置机制
- 4.6 板级默认脚本
- 4.7 机型选择 + 机型参数版本校验
- 4.8 基础服务与LED、用户覆盖脚本
- 4.9 传感器系统(HITL/真实硬件两条路)
- 4.10 状态估计器选择
- 4.11 PX4IO 协处理器
- 4.12 其它设备与手动输入
- 4.13 Commander 与 PWM/DShot 输出
- 4.14 板级 Mavlink、串口 & RC输入、USB
- 4.15 提示音、导航、热校准
- 4.16 选择性功能(按需)
- 4.17 板级附加/SD附加/日志/机型后置/引导器升级
- 4.18 UAVCAN / Cyphal / Zenoh
- 4.19 清理环境变量 & 启动完成
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
下面是借用其他博主的图片进行图解





3923

被折叠的 条评论
为什么被折叠?



