2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
28 #include "blackbox/blackbox.h"
30 #include "build/build_config.h"
31 #include "build/debug.h"
32 #include "build/debug_pin.h"
35 #include "cms/cms_types.h"
37 #include "common/axis.h"
38 #include "common/color.h"
39 #include "common/maths.h"
40 #include "common/printf_serial.h"
42 #include "config/config.h"
43 #include "config/config_eeprom.h"
44 #include "config/feature.h"
46 #include "drivers/accgyro/accgyro.h"
47 #include "drivers/adc.h"
48 #include "drivers/bus.h"
49 #include "drivers/bus_i2c.h"
50 #include "drivers/bus_octospi.h"
51 #include "drivers/bus_quadspi.h"
52 #include "drivers/bus_spi.h"
53 #include "drivers/buttons.h"
54 #include "drivers/camera_control_impl.h"
55 #include "drivers/compass/compass.h"
56 #include "drivers/dma.h"
57 #include "drivers/dshot.h"
58 #include "drivers/exti.h"
59 #include "drivers/flash/flash.h"
60 #include "drivers/inverter.h"
61 #include "drivers/io.h"
62 #include "drivers/light_led.h"
63 #include "drivers/mco.h"
64 #include "drivers/nvic.h"
65 #include "drivers/persistent.h"
66 #include "drivers/pin_pull_up_down.h"
67 #include "drivers/pwm_output.h"
68 #include "drivers/rx/rx_pwm.h"
69 #include "drivers/sensor.h"
70 #include "drivers/serial.h"
71 #include "drivers/serial_softserial.h"
72 #include "drivers/serial_uart.h"
73 #include "drivers/sdcard.h"
74 #include "drivers/sdio.h"
75 #include "drivers/sound_beeper.h"
76 #include "drivers/system.h"
77 #include "drivers/time.h"
78 #include "drivers/timer.h"
79 #include "drivers/transponder_ir.h"
80 #include "drivers/usb_io.h"
82 #include "drivers/usb_msc.h"
84 #include "drivers/vtx_common.h"
85 #include "drivers/vtx_rtc6705.h"
86 #include "drivers/vtx_table.h"
88 #include "fc/board_info.h"
89 #include "fc/dispatch.h"
90 #include "fc/gps_lap_timer.h"
92 #include "fc/rc_controls.h"
93 #include "fc/runtime_config.h"
97 #include "flight/alt_hold.h"
98 #include "flight/autopilot.h"
99 #include "flight/failsafe.h"
100 #include "flight/imu.h"
101 #include "flight/mixer.h"
102 #include "flight/gps_rescue.h"
103 #include "flight/pid.h"
104 #include "flight/pid_init.h"
105 #include "flight/position.h"
106 #include "flight/servos.h"
108 #include "io/asyncfatfs/asyncfatfs.h"
109 #include "io/beeper.h"
110 #include "io/dashboard.h"
111 #include "io/displayport_frsky_osd.h"
112 #include "io/displayport_max7456.h"
113 #include "io/displayport_msp.h"
114 #include "io/flashfs.h"
115 #include "io/gimbal.h"
116 #include "io/gimbal_control.h"
118 #include "io/ledstrip.h"
119 #include "io/pidaudio.h"
120 #include "io/piniobox.h"
121 #include "io/rcdevice_cam.h"
122 #include "io/serial.h"
123 #include "io/transponder_ir.h"
125 #include "io/vtx_control.h"
126 #include "io/vtx_msp.h"
127 #include "io/vtx_rtc6705.h"
128 #include "io/vtx_smartaudio.h"
129 #include "io/vtx_tramp.h"
131 #include "msc/emfat_file.h"
132 #ifdef USE_PERSISTENT_MSC_RTC
133 #include "msc/usbd_storage.h"
137 #include "msp/msp_serial.h"
142 #include "pg/beeper.h"
143 #include "pg/beeper_dev.h"
144 #include "pg/bus_i2c.h"
145 #include "pg/bus_spi.h"
146 #include "pg/bus_quadspi.h"
147 #include "pg/flash.h"
149 #include "pg/motor.h"
150 #include "pg/pinio.h"
151 #include "pg/piniobox.h"
152 #include "pg/pin_pull_up_down.h"
155 #include "pg/rx_pwm.h"
156 #include "pg/rx_spi.h"
157 #include "pg/sdcard.h"
159 #include "pg/vtx_io.h"
162 #include "rx/spektrum.h"
164 #include "scheduler/scheduler.h"
166 #include "sensors/acceleration.h"
167 #include "sensors/barometer.h"
168 #include "sensors/battery.h"
169 #include "sensors/boardalignment.h"
170 #include "sensors/compass.h"
171 #include "sensors/esc_sensor.h"
172 #include "sensors/gyro.h"
173 #include "sensors/gyro_init.h"
174 #include "sensors/initialisation.h"
176 #include "telemetry/telemetry.h"
178 #ifdef USE_HARDWARE_REVISION_DETECTION
179 #include "hardware_revision.h"
182 #ifdef TARGET_PREINIT
183 void targetPreInit(void);
186 uint8_t systemState
= SYSTEM_STATE_INITIALISING
;
188 #ifdef BUS_SWITCH_PIN
189 void busSwitchInit(void)
191 IO_t busSwitchResetPin
= IO_NONE
;
193 busSwitchResetPin
= IOGetByTag(IO_TAG(BUS_SWITCH_PIN
));
194 IOInit(busSwitchResetPin
, OWNER_SYSTEM
, 0);
195 IOConfigGPIO(busSwitchResetPin
, IOCFG_OUT_PP
);
198 IOLo(busSwitchResetPin
);
202 static void configureSPIBusses(void)
205 spiPinConfigure(spiPinConfig(0));
213 #ifdef USE_SPI_DEVICE_1
216 #ifdef USE_SPI_DEVICE_2
219 #ifdef USE_SPI_DEVICE_3
222 #ifdef USE_SPI_DEVICE_4
225 #ifdef USE_SPI_DEVICE_5
228 #ifdef USE_SPI_DEVICE_6
234 static void configureQuadSPIBusses(void)
237 quadSpiPinConfigure(quadSpiConfig(0));
239 #ifdef USE_QUADSPI_DEVICE_1
240 quadSpiInit(QUADSPIDEV_1
);
242 #endif // USE_QUADSPI
245 static void configureOctoSPIBusses(void)
248 #ifdef USE_OCTOSPI_DEVICE_1
249 octoSpiInit(OCTOSPIDEV_1
);
255 static void sdCardAndFSInit(void)
257 sdcard_init(sdcardConfig());
264 #if SERIAL_PORT_COUNT > 0
270 // Initialize task data as soon as possible. Has to be done before tasksInit(),
271 // and any init code that may try to modify task behaviour before tasksInit().
274 // initialize IO (needed for all IO operations)
277 #ifdef USE_HARDWARE_REVISION_DETECTION
278 detectHardwareRevision();
281 #if defined(USE_TARGET_CONFIG)
282 // Call once before the config is loaded for any target specific configuration required to support loading the config
283 targetConfiguration();
287 FLASH_INIT_ATTEMPTED
= (1 << 0),
288 SD_INIT_ATTEMPTED
= (1 << 1),
289 SPI_BUSSES_INIT_ATTEMPTED
= (1 << 2),
290 QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED
= (1 << 3),
292 uint8_t initFlags
= 0;
294 #ifdef CONFIG_IN_SDCARD
297 // Config in sdcard presents an issue with pin configuration since the pin and sdcard configs for the
298 // sdcard are in the config which is on the sdcard which we can't read yet!
300 // FIXME For now, users must NOT change flash/pin configs needed for the system to boot and/or to save the config.
301 // One possible solution is to lock the pins for the flash chip so they cannot be modified post-boot.
303 // note that target specific SDCARD/SDIO/SPI/QUADSPI/OCTOSPI configs are
304 // also not supported in USE_TARGET_CONFIG/targetConfigure() when using CONFIG_IN_SDCARD.
308 // IMPORTANT: all default flash and pin configurations must be valid for the target after pgResetAll() is called.
309 // Target designers must ensure other devices connected the same SPI/QUADSPI/OCTOSPI interface as the flash chip do not
310 // cause communication issues with the flash chip. e.g. use external pullups on SPI/QUADSPI/OCTOSPI CS lines.
313 #ifdef TARGET_BUS_INIT
314 #error "CONFIG_IN_SDCARD and TARGET_BUS_INIT are mutually exclusive"
319 #ifdef USE_SDCARD_SPI
320 configureSPIBusses();
321 initFlags
|= SPI_BUSSES_INIT_ATTEMPTED
;
325 initFlags
|= SD_INIT_ATTEMPTED
;
327 if (!sdcard_isInserted()) {
328 failureMode(FAILURE_SDCARD_REQUIRED
);
331 while (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY
) {
334 if (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_FATAL
) {
335 failureMode(FAILURE_SDCARD_INITIALISATION_FAILED
);
339 #endif // CONFIG_IN_SDCARD
341 #if defined(CONFIG_IN_EXTERNAL_FLASH) || defined(CONFIG_IN_MEMORY_MAPPED_FLASH)
343 // Config on external flash presents an issue with pin configuration since the pin and flash configs for the
344 // external flash are in the config which is on a chip which we can't read yet!
346 // FIXME For now, users must NOT change flash/pin configs needed for the system to boot and/or to save the config.
347 // One possible solution is to lock the pins for the flash chip so they cannot be modified post-boot.
349 // note that target specific FLASH/SPI/QUADSPI/OCTOSPI configs are
350 // also not supported in USE_TARGET_CONFIG/targetConfigure() when using CONFIG_IN_EXTERNAL_FLASH/CONFIG_IN_MEMORY_MAPPED_FLASH.
354 // IMPORTANT: all default flash and pin configurations must be valid for the target after pgResetAll() is called.
355 // Target designers must ensure other devices connected the same SPI/QUADSPI/OCTOSPI interface as the flash chip do not
356 // cause communication issues with the flash chip. e.g. use external pullups on SPI/QUADSPI/OCTOSPI CS lines.
360 #ifdef TARGET_BUS_INIT
361 #error "CONFIG_IN_EXTERNAL_FLASH/CONFIG_IN_MEMORY_MAPPED_FLASH and TARGET_BUS_INIT are mutually exclusive"
364 #if defined(CONFIG_IN_EXTERNAL_FLASH)
365 configureSPIBusses();
366 initFlags
|= SPI_BUSSES_INIT_ATTEMPTED
;
369 #if defined(CONFIG_IN_MEMORY_MAPPED_FLASH) || defined(CONFIG_IN_EXTERNAL_FLASH)
370 configureQuadSPIBusses();
371 configureOctoSPIBusses();
372 initFlags
|= QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED
;
375 #ifndef USE_FLASH_CHIP
376 #error "CONFIG_IN_EXTERNAL_FLASH/CONFIG_IN_MEMORY_MAPPED_FLASH requires USE_FLASH_CHIP to be defined."
379 bool haveFlash
= flashInit(flashConfig());
382 failureMode(FAILURE_EXTERNAL_FLASH_INIT_FAILED
);
384 initFlags
|= FLASH_INIT_ATTEMPTED
;
386 #endif // CONFIG_IN_EXTERNAL_FLASH || CONFIG_IN_MEMORY_MAPPED_FLASH
390 ensureEEPROMStructureIsValid();
392 bool readSuccess
= readEEPROM();
394 #if defined(USE_BOARD_INFO)
395 initBoardInformation();
398 if (!readSuccess
|| !isEEPROMVersionValid() || strncasecmp(systemConfig()->boardIdentifier
, TARGET_BOARD_IDENTIFIER
, sizeof(TARGET_BOARD_IDENTIFIER
))) {
402 systemState
|= SYSTEM_STATE_CONFIG_LOADED
;
408 debugMode
= systemConfig()->debug_mode
;
410 #ifdef TARGET_PREINIT
414 #if !defined(USE_VIRTUAL_LED)
415 ledInit(statusLedConfig());
419 #if !defined(SIMULATOR_BUILD)
423 #if defined(USE_BUTTONS)
427 delayMicroseconds(10); // allow configuration to settle // XXX Could be removed, too?
429 // Allow EEPROM reset with two-button-press without power cycling in DEBUG build
431 #define EEPROM_RESET_PRECONDITION true
433 #define EEPROM_RESET_PRECONDITION (!isMPUSoftReset())
436 if (EEPROM_RESET_PRECONDITION
) {
437 #if defined(BUTTON_A_PIN) && defined(BUTTON_B_PIN)
438 // two buttons required
439 uint8_t secondsRemaining
= 5;
440 bool bothButtonsHeld
;
442 bothButtonsHeld
= buttonAPressed() && buttonBPressed();
443 if (bothButtonsHeld
) {
444 if (--secondsRemaining
== 0) {
446 #ifdef USE_PERSISTENT_OBJECTS
447 persistentObjectWrite(PERSISTENT_OBJECT_RESET_REASON
, RESET_NONE
);
454 } while (bothButtonsHeld
);
458 #undef EEPROM_RESET_PRECONDITION
460 #endif // USE_BUTTONS
462 // Note that spektrumBind checks if a call is immediately after
463 // hard reset (including power cycle), so it should be called before
464 // systemClockSetHSEValue and OverclockRebootIfNecessary, as these
465 // may cause soft reset which will prevent spektrumBind not to execute
466 // the bind procedure.
468 #if defined(USE_SPEKTRUM_BIND)
469 if (featureIsEnabled(FEATURE_RX_SERIAL
)) {
470 switch (rxConfig()->serialrx_provider
) {
471 case SERIALRX_SPEKTRUM1024
:
472 case SERIALRX_SPEKTRUM2048
:
474 // Spektrum satellite binding if enabled on startup.
475 // Must be called before that 100ms sleep so that we don't lose satellite's binding window after startup.
476 // The rest of Spektrum initialization will happen later - via spektrumInit()
477 spektrumBind(rxConfigMutable());
483 #if defined(STM32F4) || defined(STM32G4) || defined(APM32F4)
484 // F4 has non-8MHz boards
485 // G4 for Betaflight allow 24 or 27MHz oscillator
486 systemClockSetHSEValue(systemConfig()->hseMhz
* 1000000U);
490 OverclockRebootIfNecessary(systemConfig()->cpu_overclock
);
493 // Configure MCO output after config is stable
495 // Note that mcoConfigure must be augmented with an additional argument to
496 // indicate which device instance to configure when MCO and MCO2 are both supported
498 #if defined(STM32F4) || defined(STM32F7) || defined(APM32F4)
499 // F4 and F7 support MCO on PA8 and MCO2 on PC9, but only MCO2 is supported for now
500 mcoConfigure(MCODEV_2
, mcoConfig(MCODEV_2
));
501 #elif defined(STM32G4)
502 // G4 only supports one MCO on PA8
503 mcoConfigure(MCODEV_1
, mcoConfig(MCODEV_1
));
505 #error Unsupported MCU
510 timerInit(); // timer must be initialized before any channel is allocated
513 #ifdef BUS_SWITCH_PIN
517 #if defined(USE_UART) && !defined(SIMULATOR_BUILD)
518 uartPinConfigure(serialPinConfig());
521 #if defined(AVOID_UART1_FOR_PWM_PPM)
522 # define SERIALPORT_TO_AVOID SERIAL_PORT_USART1
523 #elif defined(AVOID_UART2_FOR_PWM_PPM)
524 # define SERIALPORT_TO_AVOID SERIAL_PORT_USART2
525 #elif defined(AVOID_UART3_FOR_PWM_PPM)
526 # define SERIALPORT_TO_AVOID SERIAL_PORT_USART3
529 serialPortIdentifier_e serialPortToAvoid
= SERIAL_PORT_NONE
;
530 #if defined(SERIALPORT_TO_AVOID)
531 if (featureIsEnabled(FEATURE_RX_PPM
) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM
)) {
532 serialPortToAvoid
= SERIALPORT_TO_AVOID
;
535 serialInit(featureIsEnabled(FEATURE_SOFTSERIAL
), serialPortToAvoid
);
538 mixerInit(mixerConfig()->mixerMode
);
540 uint16_t idlePulse
= motorConfig()->mincommand
;
541 if (featureIsEnabled(FEATURE_3D
)) {
542 idlePulse
= flight3DConfig()->neutral3d
;
544 if (motorConfig()->dev
.motorPwmProtocol
== PWM_TYPE_BRUSHED
) {
545 idlePulse
= 0; // brushed motors
548 /* Motors needs to be initialized soon as posible because hardware initialization
549 * may send spurious pulses to esc's causing their early initialization. Also ppm
550 * receiver may share timer with motors so motors MUST be initialized here. */
551 motorDevInit(&motorConfig()->dev
, idlePulse
, getMotorCount());
552 systemState
|= SYSTEM_STATE_MOTORS_READY
;
558 #if defined(USE_RX_PPM)
559 else if (featureIsEnabled(FEATURE_RX_PPM
)) {
560 ppmRxInit(ppmConfig());
563 #if defined(USE_RX_PWM)
564 else if (featureIsEnabled(FEATURE_RX_PARALLEL_PWM
)) {
565 pwmRxInit(pwmConfig());
570 beeperInit(beeperDevConfig());
572 /* temp until PGs are implemented. */
573 #if defined(USE_INVERTER) && !defined(SIMULATOR_BUILD)
574 initInverters(serialPinConfig());
577 #ifdef TARGET_BUS_INIT
582 // Depending on compilation options SPI/QSPI/OSPI initialisation may already be done.
583 if (!(initFlags
& SPI_BUSSES_INIT_ATTEMPTED
)) {
584 configureSPIBusses();
585 initFlags
|= SPI_BUSSES_INIT_ATTEMPTED
;
588 if (!(initFlags
& QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED
)) {
589 configureQuadSPIBusses();
590 configureOctoSPIBusses();
591 initFlags
|= QUAD_OCTO_SPI_BUSSES_INIT_ATTEMPTED
;
594 #if defined(USE_SDCARD_SDIO) && !defined(CONFIG_IN_SDCARD) && defined(STM32H7)
600 /* MSC mode will start after init, but will not allow scheduler to run,
601 * so there is no bottleneck in reading and writing data */
603 if (mscCheckBootAndReset() || mscCheckButton()) {
604 ledInit(statusLedConfig());
607 if (blackboxConfig()->device
== BLACKBOX_DEVICE_SDCARD
) {
608 if (sdcardConfig()->mode
) {
609 if (!(initFlags
& SD_INIT_ATTEMPTED
)) {
611 initFlags
|= SD_INIT_ATTEMPTED
;
617 #if defined(USE_FLASHFS)
618 // If the blackbox device is onboard flash, then initialize and scan
619 // it to identify the log files *before* starting the USB device to
620 // prevent timeouts of the mass storage device.
621 if (blackboxConfig()->device
== BLACKBOX_DEVICE_FLASH
) {
625 // There's no more initialisation to be done, so enable DMA where possible for SPI
629 if (mscStart() == 0) {
632 systemResetFromMsc();
637 #ifdef USE_PERSISTENT_MSC_RTC
638 // if we didn't enter MSC mode then clear the persistent RTC value
639 persistentObjectWrite(PERSISTENT_OBJECT_RTC_HIGH
, 0);
640 persistentObjectWrite(PERSISTENT_OBJECT_RTC_LOW
, 0);
644 i2cHardwareConfigure(i2cConfig(0));
646 // Note: Unlike UARTs which are configured when client is present,
647 // I2C buses are initialized unconditionally if they are configured.
649 #ifdef USE_I2C_DEVICE_1
652 #ifdef USE_I2C_DEVICE_2
655 #ifdef USE_I2C_DEVICE_3
658 #ifdef USE_I2C_DEVICE_4
663 #endif // TARGET_BUS_INIT
665 #ifdef USE_HARDWARE_REVISION_DETECTION
666 updateHardwareRevision();
669 #ifdef USE_VTX_RTC6705
670 bool useRTC6705
= rtc6705IOInit(vtxIOConfig());
673 #ifdef USE_CAMERA_CONTROL
678 adcInit(adcConfig());
681 initBoardAlignment(boardAlignment());
683 if (!sensorsAutodetect()) {
684 // if gyro was not detected due to whatever reason, notify and don't arm.
685 if (isSystemConfigured()) {
686 indicateFailure(FAILURE_MISSING_ACC
, 2);
688 setArmingDisabled(ARMING_DISABLED_NO_GYRO
);
691 systemState
|= SYSTEM_STATE_SENSORS_READY
;
693 // Set the targetLooptime based on the detected gyro sampleRateHz and pid_process_denom
694 gyroSetTargetLooptime(pidConfig()->pid_process_denom
);
696 // Validate and correct the gyro config or PID loop time if needed
697 validateAndFixGyroConfig();
699 // Now reset the targetLooptime as it's possible for the validation to change the pid_process_denom
700 gyroSetTargetLooptime(pidConfig()->pid_process_denom
);
702 #if defined(USE_DSHOT_TELEMETRY) || defined(USE_ESC_SENSOR)
703 // Initialize the motor frequency filter now that we have a target looptime
704 initDshotTelemetry(gyro
.targetLooptime
);
707 // Finally initialize the gyro filtering
710 pidInit(currentPidProfile
);
720 if (isMixerUsingServos()) {
721 //pwm_params.useChannelForwarding = featureIsEnabled(FEATURE_CHANNEL_FORWARDING);
722 servoDevInit(&servoConfig()->dev
);
728 pinioInit(pinioConfig());
731 #ifdef USE_PIN_PULL_UP_DOWN
732 pinPullupPulldownInit();
736 pinioBoxInit(pinioBoxConfig());
743 for (int i
= 0; i
< 10; i
++) {
746 #if defined(USE_BEEPER)
748 if (!(beeperConfig()->beeper_off_flags
& BEEPER_GET_FLAG(BEEPER_SYSTEM_INIT
))) {
767 if (featureIsEnabled(FEATURE_GPS
)) {
769 #ifdef USE_GPS_LAP_TIMER
771 #endif // USE_GPS_LAP_TIMER
778 if (featureIsEnabled(FEATURE_LED_STRIP
)) {
783 #ifdef USE_ESC_SENSOR
784 if (featureIsEnabled(FEATURE_ESC_SENSOR
)) {
789 #ifdef USE_USB_DETECT
790 usbCableDetectInit();
793 #ifdef USE_TRANSPONDER
794 if (featureIsEnabled(FEATURE_TRANSPONDER
)) {
796 transponderStartRepeating();
797 systemState
|= SYSTEM_STATE_TRANSPONDER_ENABLED
;
801 #ifdef USE_FLASH_CHIP
802 if (!(initFlags
& FLASH_INIT_ATTEMPTED
)) {
803 flashInit(flashConfig());
804 initFlags
|= FLASH_INIT_ATTEMPTED
;
812 if (sdcardConfig()->mode
) {
813 if (!(initFlags
& SD_INIT_ATTEMPTED
)) {
815 initFlags
|= SD_INIT_ATTEMPTED
;
824 if (mixerConfig()->mixerMode
== MIXER_GIMBAL
) {
825 accStartCalibration();
828 gyroStartCalibration(false);
830 baroStartCalibration();
834 autopilotInit(autopilotConfig());
836 #if defined(USE_VTX_COMMON) || defined(USE_VTX_CONTROL)
840 #ifdef USE_VTX_CONTROL
843 #if defined(USE_VTX_COMMON)
851 #ifdef USE_VTX_SMARTAUDIO
859 #ifdef USE_VTX_RTC6705
860 if (!vtxCommonDevice() && useRTC6705
) { // external VTX takes precedence when configured.
865 #endif // VTX_CONTROL
871 batteryInit(); // always needs doing, regardless of features.
875 #endif // USE_RCDEVICE
877 #ifdef USE_PERSISTENT_STATS
886 * CMS, display devices and OSD
892 #if (defined(USE_OSD) || (defined(USE_MSP_DISPLAYPORT) && defined(USE_CMS)))
893 displayPort_t
*osdDisplayPort
= NULL
;
897 osdDisplayPortDevice_e osdDisplayPortDevice
= OSD_DISPLAYPORT_DEVICE_NONE
;
899 //The OSD need to be initialised after GYRO to avoid GYRO initialisation failure on some targets
901 if (featureIsEnabled(FEATURE_OSD
)) {
902 osdDisplayPortDevice_e device
;
904 if (vcdProfile()->video_system
== VIDEO_SYSTEM_HD
) {
905 device
= OSD_DISPLAYPORT_DEVICE_MSP
;
907 device
= osdConfig()->displayPortDevice
;
912 case OSD_DISPLAYPORT_DEVICE_AUTO
:
915 #if defined(USE_FRSKYOSD)
916 // Test OSD_DISPLAYPORT_DEVICE_FRSKYOSD first, since an FC could
917 // have a builtin MAX7456 but also an FRSKYOSD connected to an
919 case OSD_DISPLAYPORT_DEVICE_FRSKYOSD
:
920 osdDisplayPort
= frskyOsdDisplayPortInit(vcdProfile()->video_system
);
921 if (osdDisplayPort
|| device
== OSD_DISPLAYPORT_DEVICE_FRSKYOSD
) {
922 osdDisplayPortDevice
= OSD_DISPLAYPORT_DEVICE_FRSKYOSD
;
928 #if defined(USE_MAX7456)
929 case OSD_DISPLAYPORT_DEVICE_MAX7456
:
930 // If there is a max7456 chip for the OSD configured and detected then use it.
931 if (max7456DisplayPortInit(vcdProfile(), &osdDisplayPort
) || device
== OSD_DISPLAYPORT_DEVICE_MAX7456
) {
932 osdDisplayPortDevice
= OSD_DISPLAYPORT_DEVICE_MAX7456
;
938 #if defined(USE_CMS) && defined(USE_MSP_DISPLAYPORT) && defined(USE_OSD_OVER_MSP_DISPLAYPORT)
939 case OSD_DISPLAYPORT_DEVICE_MSP
:
940 osdDisplayPort
= displayPortMspInit();
941 if (osdDisplayPort
|| device
== OSD_DISPLAYPORT_DEVICE_MSP
) {
942 osdDisplayPortDevice
= OSD_DISPLAYPORT_DEVICE_MSP
;
948 // Other device cases can be added here
950 case OSD_DISPLAYPORT_DEVICE_NONE
:
955 // osdInit will register with CMS by itself.
956 osdInit(osdDisplayPort
, osdDisplayPortDevice
);
958 if (osdDisplayPortDevice
== OSD_DISPLAYPORT_DEVICE_NONE
) {
959 featureDisableImmediate(FEATURE_OSD
);
964 #if defined(USE_CMS) && defined(USE_MSP_DISPLAYPORT)
965 // If BFOSD is not active, then register MSP_DISPLAYPORT as a CMS device.
966 if (!osdDisplayPort
) {
967 cmsDisplayPortRegister(displayPortMspInit());
972 // Dashbord will register with CMS by itself.
973 if (featureIsEnabled(FEATURE_DASHBOARD
)) {
975 #ifdef USE_OLED_GPS_DEBUG_PAGE_ONLY
976 dashboardShowFixedPage(PAGE_GPS
);
978 dashboardResetPageCycling();
979 dashboardEnablePageCycling();
985 // Telemetry will initialise displayport and register with CMS by itself.
986 if (featureIsEnabled(FEATURE_TELEMETRY
)) {
991 setArmingDisabled(ARMING_DISABLED_BOOT_GRACE_TIME
);
993 // allocate SPI DMA streams before motor timers
994 #if defined(USE_SPI) && defined(USE_SPI_DMA_ENABLE_EARLY)
995 // Attempt to enable DMA on all SPI busses
1004 // allocate SPI DMA streams after motor timers as SPI DMA allocate will always be possible
1005 #if defined(USE_SPI) && defined(USE_SPI_DMA_ENABLE_LATE) && !defined(USE_SPI_DMA_ENABLE_EARLY)
1006 // Attempt to enable DMA on all SPI busses
1010 // autopilot must be initialised before modes that require the autopilot pids
1011 #ifdef USE_ALT_HOLD_MODE
1015 #ifdef USE_GPS_RESCUE
1016 if (featureIsEnabled(FEATURE_GPS
)) {
1027 systemState
|= SYSTEM_STATE_READY
;