【Betaflight源码学习】之初始化函数(init.c)

Betaflight源码学习

  • Betaflight/src/main/fc/init.c
        1. 初始化串口 (Serial Port Initialization)
        1. 系统全局初始化 (System Global Initialization)
        1. 初始化任务数据 (Initialize Task Data)
        1. 初始化输入输出 (Initialize IO)
        1. 目标配置初始化 (Target Configuration Initialization)
        1. 配置目标特定的预初始化 (Target Specific Pre-Initialization)
        1. 初始化标志 (Initialization Flags)
        1. 根据配置初始化存储与文件系统 (Initialize Storage and File System Based on Configuration)
        • 如果配置存储在SD卡上 (Config in SD Card)
        • 如果配置存储在外置闪存或内存映射闪存上 (Config in External Flash or Memory Mapped Flash)
        1. 初始化EEPROM (Initialize EEPROM)
        1. 初始化板载信息 (Initialize Board Information)
        1. 检查并设置系统状态 (Check and Set System State)
        1. 调试引脚初始化 (Debug Pin Initialization)
        1. 设置调试模式 (Set Debug Mode)
        1. 目标特定的预初始化 (Target Specific Pre-Initialization)
        1. 初始化LED (Initialize LED)
        1. 初始化外部中断 (Initialize External Interrupts)
        1. 初始化按钮 (Initialize Buttons)
        1. 绑定Spektrum接收机 (Bind Spektrum Receiver)
        1. 设置系统时钟 (Set System Clock)
        1. 处理CPU超频 (Handle CPU Overclocking)
        1. 初始化MCO输出 (Initialize MCO Output)
        1. 初始化定时器 (Initialize Timer)
        1. 初始化总线切换引脚 (Initialize Bus Switch Pin)
        1. 配置UART引脚 (Configure UART Pins)
        1. 初始化串口通信 (Initialize Serial Communication)
        1. 初始化混合器 (Initialize Mixer)
        1. 初始化电机 (Initialize Motors)
        1. 初始化接收机 (Initialize Receiver)
        1. 初始化蜂鸣器 (Initialize Beeper)
        1. 初始化倒相器 (Initialize Inverters)
        1. 根据目标配置初始化总线 (Initialize Buses Based on Target Configuration)
        1. 初始化USB MSC (Initialize USB Mass Storage)
        1. 处理持久化RTC值 (Handle Persistent RTC Value)
        1. 初始化I2C总线 (Initialize I2C Bus)
        1. 检测硬件版本 (Detect Hardware Revision)
        1. 初始化VTX (Initialize VTX)
        1. 初始化相机控制 (Initialize Camera Control)
        1. 初始化ADC (Initialize ADC)
        1. 初始化板载对齐 (Initialize Board Alignment)
        1. 自动检测传感器 (Auto-Detect Sensors)
        1. 设置目标循环时间 (Set Target Loop Time)
        1. 初始化传感器校准 (Initialize Sensor Calibration)
        1. 初始化飞行控制模块 (Initialize Flight Control Modules)
        1. 初始化VTX控制 (Initialize VTX Control)
        1. 初始化云台 (Initialize Gimbal)
        1. 初始化电池监控 (Initialize Battery Monitoring)
        1. 初始化RC设备 (Initialize RC Devices)
        1. 初始化持久化统计数据 (Initialize Persistent Statistics)
        1. 初始化MSP (Initialize MSP)
        1. 初始化CMS、显示设备和OSD (Initialize CMS, Display Devices and OSD)
        1. 设置启动保护时间 (Set Boot Grace Time)
        1. 启用SPI DMA (Enable SPI DMA)
        1. 初始化自动驾驶模式 (Initialize Autopilot Modes)
        1. 初始化GPS救援 (Initialize GPS Rescue)
        1. 初始化调试模块 (Initialize Debug Module)
        1. 初始化未使用的引脚 (Initialize Unused Pins)
        1. 初始化任务调度器 (Initialize Task Scheduler)
        1. 设置系统状态为准备就绪 (Set System State to Ready)
      • 总结

Betaflight/src/main/fc/init.c

betaflight/src/main/fc/init.c

这段代码是Betaflight固件中负责系统初始化的核心部分。它通过一系列的初始化步骤,确保飞行控制器的各个硬件组件和功能模块能够正确启动和运作。下面是对这段代码的逐步分解与详细解释:

1. 初始化串口 (Serial Port Initialization)

c 复制代码
#if SERIAL_PORT_COUNT > 0
    printfSerialInit();
#endif

如果编译配置中定义了串口数量大于0,则初始化串口,使得可以通过串口输出调试信息。

2. 系统全局初始化 (System Global Initialization)

c 复制代码
systemInit();

进行系统全局的初始化工作,这通常包括时钟设置、中断配置等基本操作。

3. 初始化任务数据 (Initialize Task Data)

c 复制代码
tasksInitData();

初始化任务数据,这是必要的步骤,因为在任务初始化前任何试图修改任务行为的代码都可能无法达到预期效果。

4. 初始化输入输出 (Initialize IO)

c 复制代码
IOInitGlobal();

初始化全局输入输出(IO),这是所有IO操作的基础。

5. 目标配置初始化 (Target Configuration Initialization)

c 复制代码
#if defined(USE_TARGET_CONFIG)
    targetConfiguration();
#endif

如果编译配置中定义了USE_TARGET_CONFIG,则进行目标特定的配置。这部分代码通常用于在配置数据加载之前进行必要的硬件设置,以便正确加载配置。

6. 配置目标特定的预初始化 (Target Specific Pre-Initialization)

c 复制代码
#if defined(USE_CONFIG_TARGET_PREINIT)
    configTargetPreInit();
#endif

如果编译配置中定义了USE_CONFIG_TARGET_PREINIT,则调用目标特定的预初始化函数。这部分代码处理一些在配置加载之前的初始化需求。

7. 初始化标志 (Initialization Flags)

c 复制代码
enum {
    FLASH_INIT_ATTEMPTED                = (1 << 0),
    SD_INIT_ATTEMPTED                   = (1 << 1),
    SPI_BUSSES_INIT_ATTEMPTED           = (1 << 2),
    QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED = (1 << 3),
};
uint8_t initFlags = 0;

定义一组初始化标志,用于记录和检查哪些初始化步骤已经执行。这些标志用于避免重复初始化,或者在某些情况下进行必要的检查。

8. 根据配置初始化存储与文件系统 (Initialize Storage and File System Based on Configuration)

如果配置存储在SD卡上 (Config in SD Card)
c 复制代码
#ifdef CONFIG_IN_SDCARD
    pgResetAll();
    if (defined(USE_SDCARD_SPI)) {
        configureSPIBusses();
        initFlags |= SPI_BUSSES_INIT_ATTEMPTED;
    }
    sdCardAndFSInit();
    initFlags |= SD_INIT_ATTEMPTED;

    if (!sdcard_isInserted()) {
        failureMode(FAILURE_SDCARD_REQUIRED);
    }

    while (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) {
        afatfs_poll();
        if (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_FATAL) {
            failureMode(FAILURE_SDCARD_INITIALISATION_FAILED);
        }
    }
#endif

如果配置存储在SD卡上,则首先初始化SPI总线(如果需要),然后初始化SD卡和文件系统。如果SD卡没有插入,或者文件系统初始化失败,则进入故障模式。

如果配置存储在外置闪存或内存映射闪存上 (Config in External Flash or Memory Mapped Flash)
c 复制代码
#if defined(CONFIG_IN_EXTERNAL_FLASH) || defined(CONFIG_IN_MEMORY_MAPPED_FLASH)
    pgResetAll();
    if (defined(CONFIG_IN_EXTERNAL_FLASH)) {
        configureSPIBusses();
        initFlags |= SPI_BUSSES_INIT_ATTEMPTED;
    }
    if (defined(CONFIG_IN_MEMORY_MAPPED_FLASH) || defined(CONFIG_IN_EXTERNAL_FLASH)) {
        configureQuadSPIBusses();
        configureOctoSPIBusses();
        initFlags |= QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED;
    }
    bool haveFlash = flashInit(flashConfig());
    if (!haveFlash) {
        failureMode(FAILURE_EXTERNAL_FLASH_INIT_FAILED);
    }
    initFlags |= FLASH_INIT_ATTEMPTED;
#endif

如果配置存储在外置闪存或内存映射闪存上,则初始化SPI、QSPI、OSPI总线(如果需要),然后初始化外置闪存。如果闪存初始化失败,则进入故障模式。

9. 初始化EEPROM (Initialize EEPROM)

c 复制代码
initEEPROM();
ensureEEPROMStructureIsValid();
bool readSuccess = readEEPROM();

初始化EEPROM,并确保其结构有效,然后尝试从EEPROM读取配置。如果读取失败或者配置版本无效,则重置EEPROM。

10. 初始化板载信息 (Initialize Board Information)

c 复制代码
#if defined(USE_BOARD_INFO)
    initBoardInformation();
#endif

如果编译配置中定义了USE_BOARD_INFO,则初始化板载信息。

11. 检查并设置系统状态 (Check and Set System State)

c 复制代码
systemState |= SYSTEM_STATE_CONFIG_LOADED;

设置系统状态为配置已加载。

12. 调试引脚初始化 (Debug Pin Initialization)

c 复制代码
#ifdef USE_DEBUG_PIN
    dbgPinInit();
#endif

如果编译配置中定义了USE_DEBUG_PIN,则初始化调试引脚。

13. 设置调试模式 (Set Debug Mode)

c 复制代码
debugMode = systemConfig()->debug_mode;

根据配置设置调试模式。

14. 目标特定的预初始化 (Target Specific Pre-Initialization)

c 复制代码
#ifdef TARGET_PREINIT
    targetPreInit();
#endif

如果编译配置中定义了TARGET_PREINIT,则调用目标特定的预初始化函数。

15. 初始化LED (Initialize LED)

c 复制代码
#if !defined(USE_VIRTUAL_LED)
    ledInit(statusLedConfig());
#endif
LED2_ON;

如果编译配置中没有定义USE_VIRTUAL_LED,则初始化LED。设置状态LED为亮。

16. 初始化外部中断 (Initialize External Interrupts)

c 复制代码
#if !defined(SIMULATOR_BUILD)
    EXTIInit();
#endif

如果这不是一个模拟器构建,则初始化外部中断。

17. 初始化按钮 (Initialize Buttons)

c 复制代码
#if defined(USE_BUTTONS)
    buttonsInit();
    delayMicroseconds(10);
    // 允许EEPROM重置通过双按钮按下实现(不需电源重启)
    #ifdef DEBUG
    #define EEPROM_RESET_PRECONDITION true
    #else
    #define EEPROM_RESET_PRECONDITION (!isMPUSoftReset())
    #endif

    if (EEPROM_RESET_PRECONDITION) {
        if (defined(BUTTON_A_PIN) && defined(BUTTON_B_PIN)) {
            uint8_t secondsRemaining = 5;
            bool bothButtonsHeld;
            do {
                bothButtonsHeld = buttonAPressed() && buttonBPressed();
                if (bothButtonsHeld) {
                    if (--secondsRemaining == 0) {
                        resetEEPROM();
                        #ifdef USE_PERSISTENT_OBJECTS
                        persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON, RESET_NONE);
                        #endif
                        systemReset();
                    }
                    delay(1000);
                    LED0_TOGGLE;
                }
            } while (bothButtonsHeld);
        }
    }
    #undef EEPROM_RESET_PRECONDITION
#endif

如果编译配置中定义了USE_BUTTONS,则初始化按钮。允许用户通过双按钮按下重置EEPROM,这在调试模式下始终是可能的,而在普通运行模式下仅在不是软重启的情况下允许。

18. 绑定Spektrum接收机 (Bind Spektrum Receiver)

c 复制代码
#if defined(USE_SPEKTRUM_BIND)
    if (featureIsEnabled(FEATURE_RX_SERIAL)) {
        switch (rxConfig()->serialrx_provider) {
            case SERIALRX_SPEKTRUM1024:
            case SERIALRX_SPEKTRUM2048:
            case SERIALRX_SRXL:
                spektrumBind(rxConfigMutable());
                break;
        }
    }
#endif

如果编译配置中定义了USE_SPEKTRUM_BIND,并且接收机提供者是Spektrum系列,则绑定Spektrum接收机。

19. 设置系统时钟 (Set System Clock)

c 复制代码
#if PLATFORM_TRAIT_CONFIG_HSE
    systemClockSetHSEValue(systemConfig()->hseMhz * 1000000U);
#endif

根据配置设置系统时钟频率。

20. 处理CPU超频 (Handle CPU Overclocking)

c 复制代码
#ifdef USE_OVERCLOCK
    OverclockRebootIfNecessary(systemConfig()->cpu_overclock);
#endif

如果编译配置中定义了USE_OVERCLOCK,则根据配置进行CPU超频处理。

21. 初始化MCO输出 (Initialize MCO Output)

c 复制代码
#ifdef USE_MCO
    mcoInit();
#endif

如果编译配置中定义了USE_MCO,则初始化MCO(主时钟输出)。

22. 初始化定时器 (Initialize Timer)

c 复制代码
#ifdef USE_TIMER
    timerInit();
#endif

如果编译配置中定义了USE_TIMER,则初始化定时器。

23. 初始化总线切换引脚 (Initialize Bus Switch Pin)

c 复制代码
#ifdef BUS_SWITCH_PIN
    busSwitchInit();
#endif

如果编译配置中定义了BUS_SWITCH_PIN,则初始化总线切换引脚。

24. 配置UART引脚 (Configure UART Pins)

c 复制代码
#if defined(USE_UART) && !defined(SIMULATOR_BUILD)
    uartPinConfigure(serialPinConfig());
#endif

如果编译配置中定义了USE_UART,并且这不是一个模拟器构建,则配置UART引脚。

25. 初始化串口通信 (Initialize Serial Communication)

c 复制代码
serialInit(featureIsEnabled(FEATURE_SOFTSERIAL));

初始化串口通信,如果编译配置中定义了FEATURE_SOFTSERIAL,则启用软串口。

26. 初始化混合器 (Initialize Mixer)

c 复制代码
mixerInit(mixerConfig()->mixerMode);

初始化混合器,混合器用于混合输入通道的控制信号以驱动电机和其他输出设备。

27. 初始化电机 (Initialize Motors)

c 复制代码
#ifdef USE_MOTOR
    motorDevInit(getMotorCount());
    systemState |= SYSTEM_STATE_MOTORS_READY;
#endif

如果编译配置中定义了USE_MOTOR,则初始化电机。设置系统状态为电机已准备好。

28. 初始化接收机 (Initialize Receiver)

c 复制代码
do {
#if defined(USE_RX_PPM)
    if (featureIsEnabled(FEATURE_RX_PPM)) {
        ppmRxInit(ppmConfig());
        break;
    }
#endif
#if defined(USE_RX_PWM)
    if (featureIsEnabled(FEATURE_RX_PARALLEL_PWM)) {
        pwmRxInit(pwmConfig());
        break;
    }
#endif
} while (false);

根据接收机类型初始化接收机。如果接收机类型为PPM或PWM,则分别初始化。

29. 初始化蜂鸣器 (Initialize Beeper)

c 复制代码
#ifdef USE_BEEPER
    beeperInit(beeperDevConfig());
#endif

如果编译配置中定义了USE_BEEPER,则初始化蜂鸣器。

30. 初始化倒相器 (Initialize Inverters)

c 复制代码
#if defined(USE_INVERTER) && !defined(SIMULATOR_BUILD)
    initInverters(serialPinConfig());
#endif

如果编译配置中定义了USE_INVERTER,则初始化倒相器。倒相器用于反转某些输出信号的极性。

31. 根据目标配置初始化总线 (Initialize Buses Based on Target Configuration)

c 复制代码
#ifdef TARGET_BUS_INIT
    targetBusInit();
#else
    // 根据编译选项,SPI/QSPI/OSPI初始化可能已被执行。
    if (!(initFlags & SPI_BUSSES_INIT_ATTEMPTED)) {
        configureSPIBusses();
        initFlags |= SPI_BUSSES_INIT_ATTEMPTED;
    }
    if (!(initFlags & QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED)) {
        configureQuadSPIBusses();
        configureOctoSPIBusses();
        initFlags |= QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED;
    }
    #if defined(USE_SDCARD_SDIO) && !defined(CONFIG_IN_SDCARD) && PLATFORM_TRAIT_SDIO_INIT
    sdioPinConfigure();
    SDIO_GPIO_Init();
    #endif
#endif

根据目标配置初始化总线。如果编译配置中定义了TARGET_BUS_INIT,则调用目标特定的总线初始化函数;否则,根据配置初始化SPI、QSPI、OSPI总线。

32. 初始化USB MSC (Initialize USB Mass Storage)

c 复制代码
#ifdef USE_USB_MSC
    mscInit();
    if (mscCheckBootAndReset() || mscCheckButton()) {
        ledInit(statusLedConfig());
        if (blackboxConfig()->device == BLACKBOX_DEVICE_SDCARD) {
            if (sdcardConfig()->mode) {
                if (!(initFlags & SD_INIT_ATTEMPTED)) {
                    sdCardAndFSInit();
                    initFlags |= SD_INIT_ATTEMPTED;
                }
            }
        }
        if (defined(USE_FLASHFS)) {
            if (blackboxConfig()->device == BLACKBOX_DEVICE_FLASH) {
                emfat_init_files();
            }
        }
        // 尽可能启用SPI DMA
        #ifdef USE_SPI
        spiInitBusDMA();
        #endif
        if (mscStart() == 0) {
            mscWaitForButton();
        } else {
            systemResetFromMsc();
        }
    }
#endif

如果编译配置中定义了USE_USB_MSC,则初始化USB MSC(Mass Storage Control)。如果检测到USB设备插入或按钮按下,则初始化SD卡或外部闪存,并启动MSC模式。

33. 处理持久化RTC值 (Handle Persistent RTC Value)

c 复制代码
#ifdef USE_PERSISTENT_MSC_RTC
    persistentObjectWrite(PERSISTENT_OBJECT_RTC_HIGH, 0);
    persistentObjectWrite(PERSISTENT_OBJECT_RTC_LOW, 0);
#endif

如果编译配置中定义了USE_PERSISTENT_MSC_RTC,则清空持久化的RTC值。

34. 初始化I2C总线 (Initialize I2C Bus)

c 复制代码
#ifdef USE_I2C
    i2cPinConfigure(i2cConfig(0));
    #ifdef USE_I2C_DEVICE_0
    i2cInit(I2CDEV_0);
    #endif
    // 更多I2C设备初始化...
#endif

如果编译配置中定义了USE_I2C,则配置并初始化I2C总线。

35. 检测硬件版本 (Detect Hardware Revision)

c 复制代码
#ifdef USE_HARDWARE_REVISION_DETECTION
    updateHardwareRevision();
#endif

如果编译配置中定义了USE_HARDWARE_REVISION_DETECTION,则检测并更新硬件版本信息。

36. 初始化VTX (Initialize VTX)

c 复制代码
#ifdef USE_VTX_RTC6705
    bool useRTC6705 = rtc6705IOInit(vtxIOConfig());
#endif

如果编译配置中定义了USE_VTX_RTC6705,则初始化VTX(视频传输模块)。

37. 初始化相机控制 (Initialize Camera Control)

c 复制代码
#ifdef USE_CAMERA_CONTROL
    cameraControlInit();
#endif

如果编译配置中定义了USE_CAMERA_CONTROL,则初始化相机控制模块。

38. 初始化ADC (Initialize ADC)

c 复制代码
#ifdef USE_ADC
    adcInit(adcConfig());
#endif

如果编译配置中定义了USE_ADC,则初始化ADC(模拟数字转换器)。

39. 初始化板载对齐 (Initialize Board Alignment)

c 复制代码
initBoardAlignment(boardAlignment());

初始化板载对齐,用于校准飞行控制器的姿态传感器(如加速度计和陀螺仪)。

40. 自动检测传感器 (Auto-Detect Sensors)

c 复制代码
if (!sensorsAutodetect()) {
    if (isSystemConfigured()) {
        indicateFailure(FAILURE_MISSING_ACC, 2);
    }
    setArmingDisabled(ARMING_DISABLED_NO_GYRO);
}

自动检测传感器(如加速度计和陀螺仪)。如果检测失败,则禁用武装,并通过LED指示错误。

41. 设置目标循环时间 (Set Target Loop Time)

c 复制代码
systemState |= SYSTEM_STATE_SENSORS_READY;
gyroSetTargetLooptime(pidConfig()->pid_process_denom);
validateAndFixGyroConfig();
gyroSetTargetLooptime(pidConfig()->pid_process_denom);

设置系统状态为传感器已准备好,并根据PID配置设置目标循环时间。校验并修正陀螺仪配置,然后再次设置目标循环时间。

42. 初始化传感器校准 (Initialize Sensor Calibration)

c 复制代码
#ifdef USE_ACC
    accStartCalibration();
#endif
gyroStartCalibration(false);
#ifdef USE_BARO
    baroStartCalibration();
#endif

根据传感器类型初始化校准过程。如果编译配置中定义了USE_ACCUSE_BARO,则分别初始化加速度计和气压计的校准。

43. 初始化飞行控制模块 (Initialize Flight Control Modules)

c 复制代码
positionInit();
autopilotInit();
// 更多飞行控制模块初始化...

初始化飞行控制器的各种模块,包括位置初始化、自动驾驶仪初始化等。

44. 初始化VTX控制 (Initialize VTX Control)

c 复制代码
#ifdef USE_VTX_CONTROL
    vtxControlInit();
    // 更多VTX模块初始化...
#endif

如果编译配置中定义了USE_VTX_CONTROL,则初始化VTX控制模块。

45. 初始化云台 (Initialize Gimbal)

c 复制代码
#ifdef USE_GIMBAL
    gimbalInit();
#endif

如果编译配置中定义了USE_GIMBAL,则初始化云台模块。

46. 初始化电池监控 (Initialize Battery Monitoring)

c 复制代码
batteryInit();

初始化电池监控模块,用于监测电池电压和电流等信息。

47. 初始化RC设备 (Initialize RC Devices)

c 复制代码
#ifdef USE_RCDEVICE
    rcdeviceInit();
#endif

如果编译配置中定义了USE_RCDEVICE,则初始化RC设备。

48. 初始化持久化统计数据 (Initialize Persistent Statistics)

c 复制代码
#ifdef USE_PERSISTENT_STATS
    statsInit();
#endif

如果编译配置中定义了USE_PERSISTENT_STATS,则初始化持久化统计数据模块。

49. 初始化MSP (Initialize MSP)

c 复制代码
mspInit();
mspSerialInit();

初始化MSP(MultiWii Serial Protocol),这是用于与地面站软件进行通信的主要协议。

50. 初始化CMS、显示设备和OSD (Initialize CMS, Display Devices and OSD)

c 复制代码
#ifdef USE_CMS
    cmsInit();
#endif

#if (defined(USE_OSD) || (defined(USE_MSP_DISPLAYPORT) && defined(USE_CMS)))
    displayPort_t *osdDisplayPort = NULL;
#endif

#if defined(USE_OSD)
    osdDisplayPortDevice_e osdDisplayPortDevice = OSD_DISPLAYPORT_DEVICE_NONE;
    // 根据配置选择OSD设备
    if (featureIsEnabled(FEATURE_OSD)) {
        osdDisplayPortDevice_e device;
        // 根据视频系统选择设备
        if (vcdProfile()->video_system == VIDEO_SYSTEM_HD) {
            device = OSD_DISPLAYPORT_DEVICE_MSP;
        } else {
            device = osdConfig()->displayPortDevice;
        }
        // 初始化OSD设备
        switch(device) {
            case OSD_DISPLAYPORT_DEVICE_AUTO:
                FALLTHROUGH;
            case OSD_DISPLAYPORT_DEVICE_FRSKYOSD:
                osdDisplayPort = frskyOsdDisplayPortInit(vcdProfile()->video_system);
                if (osdDisplayPort || device == OSD_DISPLAYPORT_DEVICE_FRSKYOSD) {
                    osdDisplayPortDevice = OSD_DISPLAYPORT_DEVICE_FRSKYOSD;
                    break;
                }
                FALLTHROUGH;
            case OSD_DISPLAYPORT_DEVICE_MAX7456:
                if (max7456DisplayPortInit(vcdProfile(), &osdDisplayPort) || device == OSD_DISPLAYPORT_DEVICE_MAX7456) {
                    osdDisplayPortDevice = OSD_DISPLAYPORT_DEVICE_MAX7456;
                    break;
                }
                FALLTHROUGH;
            case OSD_DISPLAYPORT_DEVICE_MSP:
                osdDisplayPort = displayPortMspInit();
                if (osdDisplayPort || device == OSD_DISPLAYPORT_DEVICE_MSP) {
                    osdDisplayPortDevice = OSD_DISPLAYPORT_DEVICE_MSP;
                    break;
                }
                FALLTHROUGH;
            case OSD_DISPLAYPORT_DEVICE_NONE:
            default:
                break;
        }
        // 初始化OSD
        osdInit(osdDisplayPort, osdDisplayPortDevice);
        if (osdDisplayPortDevice == OSD_DISPLAYPORT_DEVICE_NONE) {
            featureDisableImmediate(FEATURE_OSD);
        }
    }
#endif

#if defined(USE_CMS) && defined(USE_MSP_DISPLAYPORT)
    if (!osdDisplayPort) {
        cmsDisplayPortRegister(displayPortMspInit());
    }
#endif

#ifdef USE_DASHBOARD
    if (featureIsEnabled(FEATURE_DASHBOARD)) {
        dashboardInit();
        // 根据配置显示固定页面或启用页面循环
        #ifdef USE_OLED_GPS_DEBUG_PAGE_ONLY
        dashboardShowFixedPage(PAGE_GPS);
        #else
        dashboardResetPageCycling();
        dashboardEnablePageCycling();
        #endif
    }
#endif

#ifdef USE_TELEMETRY
    if (featureIsEnabled(FEATURE_TELEMETRY)) {
        telemetryInit();
    }
#endif

初始化CMS(Configuration Management System)、显示设备和OSD(On-Screen Display)。根据配置选择合适的OSD设备,并初始化。

51. 设置启动保护时间 (Set Boot Grace Time)

c 复制代码
setArmingDisabled(ARMING_DISABLED_BOOT_GRACE_TIME);

设置启动保护时间,在此期间飞行控制器不会允许武装,以防止启动时的误操作。

52. 启用SPI DMA (Enable SPI DMA)

c 复制代码
#if defined(USE_SPI) && defined(USE_SPI_DMA_ENABLE_EARLY)
    spiInitBusDMA();
#endif
#ifdef USE_MOTOR
    motorPostInit();
    motorEnable();
#endif
#if defined(USE_SPI) && defined(USE_SPI_DMA_ENABLE_LATE) && !defined(USE_SPI_DMA_ENABLE_EARLY)
    spiInitBusDMA();
#endif

根据编译配置启用SPI DMA(直接内存访问)。DMA可以提高数据传输效率。电机的后初始化和启用也需要在此期间进行。

53. 初始化自动驾驶模式 (Initialize Autopilot Modes)

c 复制代码
#ifdef USE_ALTITUDE_HOLD
    altHoldInit();
#endif
#ifdef USE_POSITION_HOLD
    posHoldInit();
#endif

如果编译配置中定义了USE_ALTITUDE_HOLDUSE_POSITION_HOLD,则分别初始化高度保持和位置保持模块。

54. 初始化GPS救援 (Initialize GPS Rescue)

c 复制代码
#ifdef USE_GPS_RESCUE
    if (featureIsEnabled(FEATURE_GPS)) {
        gpsRescueInit();
    }
#endif

如果编译配置中定义了USE_GPS_RESCUE,并且GPS功能已启用,则初始化GPS救援模块。

55. 初始化调试模块 (Initialize Debug Module)

c 复制代码
debugInit();

初始化调试模块,用于在调试模式下提供更多信息。

56. 初始化未使用的引脚 (Initialize Unused Pins)

c 复制代码
unusedPinsInit();

初始化未使用的引脚,将其设置为默认状态,避免误操作。

57. 初始化任务调度器 (Initialize Task Scheduler)

c 复制代码
tasksInit();

初始化任务调度器,用于管理飞行控制器中的各种任务。

58. 设置系统状态为准备就绪 (Set System State to Ready)

c 复制代码
systemState |= SYSTEM_STATE_READY;

设置系统状态为准备就绪,表示飞行控制器已经成功启动并准备好执行任务。

总结

这段代码的主要功能是对Betaflight飞行控制器进行初始化。它涵盖了从基本的系统配置到各种硬件设备和功能模块的初始化,确保飞行控制器能够正确地读取配置、检测传感器、初始化接收机、电机和其他外设,并准备好在飞行过程中执行各种控制任务。代码中的条件编译宏使得可以根据不同的硬件配置和编译选项启用或禁用相应的初始化逻辑。

相关推荐
Eiceblue5 小时前
Python 快速提取扫描件 PDF 中的文本:OCR 实操教程
vscode·python·ocr·1024程序员节
APIshop5 小时前
淘宝/天猫 API 接口深度解析:商品详情获取与按图搜索商品(拍立淘)实战指南
python·1024程序员节
hazy1k6 小时前
51单片机基础-ADC模数转换
stm32·单片机·嵌入式硬件·51单片机·1024程序员节
eddy-原6 小时前
运维自动化与监控体系综合实践作业
运维·自动化·1024程序员节
瀚高PG实验室8 小时前
Linux环境下编译C语言使用libpq连接瀚高数据库
1024程序员节·瀚高数据库
minji...9 小时前
算法题 逆波兰表达式/计算器
数据结构·c++·算法·1024程序员节
koo36415 小时前
李宏毅机器学习笔记31
1024程序员节
开发者小天15 小时前
调整为 dart-sass 支持的语法,将深度选择器/deep/调整为::v-deep
开发语言·前端·javascript·vue.js·uni-app·sass·1024程序员节
fruge15 小时前
前端Sass完全指南:从入门到精通
1024程序员节