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"
36 #include "cms/cms_types.h"
38 #include "common/axis.h"
39 #include "common/color.h"
40 #include "common/maths.h"
41 #include "common/printf_serial.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_quadspi.h"
51 #include "drivers/bus_spi.h"
52 #include "drivers/buttons.h"
53 #include "drivers/camera_control.h"
54 #include "drivers/compass/compass.h"
55 #include "drivers/dma.h"
56 #include "drivers/exti.h"
57 #include "drivers/flash.h"
58 #include "drivers/inverter.h"
59 #include "drivers/io.h"
60 #include "drivers/light_led.h"
61 #include "drivers/mco.h"
62 #include "drivers/nvic.h"
63 #include "drivers/persistent.h"
64 #include "drivers/pwm_esc_detect.h"
65 #include "drivers/pwm_output.h"
66 #include "drivers/rx/rx_pwm.h"
67 #include "drivers/sensor.h"
68 #include "drivers/serial.h"
69 #include "drivers/serial_softserial.h"
70 #include "drivers/serial_uart.h"
71 #include "drivers/sdcard.h"
72 #include "drivers/sound_beeper.h"
73 #include "drivers/system.h"
74 #include "drivers/time.h"
75 #include "drivers/timer.h"
76 #include "drivers/transponder_ir.h"
77 #include "drivers/usb_io.h"
79 #include "drivers/usb_msc.h"
81 #include "drivers/vtx_common.h"
82 #include "drivers/vtx_rtc6705.h"
83 #include "drivers/vtx_table.h"
85 #include "fc/board_info.h"
86 #include "fc/config.h"
87 #include "fc/dispatch.h"
89 #include "fc/rc_controls.h"
90 #include "fc/runtime_config.h"
94 #include "flight/failsafe.h"
95 #include "flight/imu.h"
96 #include "flight/mixer.h"
97 #include "flight/pid.h"
98 #include "flight/rpm_filter.h"
99 #include "flight/servos.h"
101 #include "io/asyncfatfs/asyncfatfs.h"
102 #include "io/beeper.h"
103 #include "io/dashboard.h"
104 #include "io/displayport_max7456.h"
105 #include "io/displayport_msp.h"
106 #include "io/displayport_srxl.h"
107 #include "io/flashfs.h"
108 #include "io/gimbal.h"
110 #include "io/ledstrip.h"
111 #include "io/motors.h"
112 #include "io/pidaudio.h"
113 #include "io/piniobox.h"
114 #include "io/rcdevice_cam.h"
115 #include "io/serial.h"
116 #include "io/servos.h"
117 #include "io/transponder_ir.h"
119 #include "io/vtx_control.h"
120 #include "io/vtx_rtc6705.h"
121 #include "io/vtx_smartaudio.h"
122 #include "io/vtx_tramp.h"
124 #ifdef USE_PERSISTENT_MSC_RTC
125 #include "msc/usbd_storage.h"
129 #include "msp/msp_serial.h"
134 #include "pg/beeper.h"
135 #include "pg/beeper_dev.h"
136 #include "pg/bus_i2c.h"
137 #include "pg/bus_spi.h"
138 #include "pg/bus_quadspi.h"
139 #include "pg/flash.h"
141 #include "pg/motor.h"
142 #include "pg/pinio.h"
143 #include "pg/piniobox.h"
146 #include "pg/rx_spi.h"
147 #include "pg/rx_pwm.h"
148 #include "pg/sdcard.h"
150 #include "pg/vtx_io.h"
153 #include "rx/rx_spi.h"
154 #include "rx/spektrum.h"
156 #include "scheduler/scheduler.h"
158 #include "sensors/acceleration.h"
159 #include "sensors/barometer.h"
160 #include "sensors/battery.h"
161 #include "sensors/boardalignment.h"
162 #include "sensors/compass.h"
163 #include "sensors/esc_sensor.h"
164 #include "sensors/gyro.h"
165 #include "sensors/initialisation.h"
166 #include "sensors/sensors.h"
168 #include "telemetry/telemetry.h"
170 #ifdef USE_HARDWARE_REVISION_DETECTION
171 #include "hardware_revision.h"
174 #ifdef TARGET_PREINIT
175 void targetPreInit(void);
178 #ifdef SOFTSERIAL_LOOPBACK
179 serialPort_t
*loopbackPort
;
182 uint8_t systemState
= SYSTEM_STATE_INITIALISING
;
184 void SDIO_GPIO_Init(void);
186 void processLoopback(void)
188 #ifdef SOFTSERIAL_LOOPBACK
190 uint8_t bytesWaiting
;
191 while ((bytesWaiting
= serialRxBytesWaiting(loopbackPort
))) {
192 uint8_t b
= serialRead(loopbackPort
);
193 serialWrite(loopbackPort
, b
);
199 #ifdef BUS_SWITCH_PIN
200 void busSwitchInit(void)
202 static IO_t busSwitchResetPin
= IO_NONE
;
204 busSwitchResetPin
= IOGetByTag(IO_TAG(BUS_SWITCH_PIN
));
205 IOInit(busSwitchResetPin
, OWNER_SYSTEM
, 0);
206 IOConfigGPIO(busSwitchResetPin
, IOCFG_OUT_PP
);
209 IOLo(busSwitchResetPin
);
213 static void configureSPIAndQuadSPI(void)
216 spiPinConfigure(spiPinConfig(0));
224 #ifdef USE_SPI_DEVICE_1
227 #ifdef USE_SPI_DEVICE_2
230 #ifdef USE_SPI_DEVICE_3
233 #ifdef USE_SPI_DEVICE_4
236 #ifdef USE_SPI_DEVICE_5
239 #ifdef USE_SPI_DEVICE_6
245 quadSpiPinConfigure(quadSpiConfig(0));
247 #ifdef USE_QUADSPI_DEVICE_1
248 quadSpiInit(QUADSPIDEV_1
);
250 #endif // USE_QUAD_SPI
253 void sdCardAndFSInit()
255 sdcard_init(sdcardConfig());
262 #ifdef SERIAL_PORT_COUNT
268 // initialize IO (needed for all IO operations)
271 #ifdef USE_HARDWARE_REVISION_DETECTION
272 detectHardwareRevision();
275 #ifdef USE_BRUSHED_ESC_AUTODETECT
276 // Opportunistically use the first motor pin of the default configuration for detection.
277 // We are doing this as with some boards, timing seems to be important, and the later detection will fail.
278 ioTag_t motorIoTag
= timerioTagGetByUsage(TIM_USE_MOTOR
, 0);
281 detectBrushedESC(motorIoTag
);
286 FLASH_INIT_ATTEMPTED
= (1 << 0),
287 SD_INIT_ATTEMPTED
= (1 << 1),
288 SPI_AND_QSPI_INIT_ATTEMPTED
= (1 << 2),
290 uint8_t initFlags
= 0;
293 #ifdef EEPROM_IN_SDCARD
296 // Config in sdcard presents an issue with pin configuration since the pin and sdcard configs for the
297 // sdcard are in the config which is on the sdcard which we can't read yet!
299 // FIXME We need to add configuration somewhere, e.g. bootloader image or reserved flash area, that can be read by the firmware.
300 // it's currently possible for the firmware resource allocation to be wrong after the config is loaded if the user changes the settings.
301 // This would cause undefined behaviour once the config is loaded. so for now, users must NOT change sdio/spi configs needed for
302 // the system to boot and/or to save the config.
304 // note that target specific SDCARD/SDIO/SPI/QUADSPI configs are
305 // also not supported in USE_TARGET_CONFIG/targetConfigure() when using EEPROM_IN_SDCARD.
309 // IMPORTANT: all default flash and pin configurations must be valid for the target after pgResetAll() is called.
310 // Target designers must ensure other devices connected the same SPI/QUADSPI interface as the flash chip do not
311 // cause communication issues with the flash chip. e.g. use external pullups on SPI/QUADSPI CS lines.
314 #ifdef TARGET_BUS_INIT
315 #error "EEPROM_IN_SDCARD and TARGET_BUS_INIT are mutually exclusive"
320 #if defined(STM32H7) && defined(USE_SDCARD_SDIO) // H7 only for now, likely should be applied to F4/F7 too
323 #ifdef USE_SDCARD_SPI
324 configureSPIAndQuadSPI();
325 initFlags
|= SPI_AND_QSPI_INIT_ATTEMPTED
;
329 initFlags
|= SD_INIT_ATTEMPTED
;
331 while (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY
) {
334 if (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_FATAL
) {
335 failureMode(FAILURE_SDCARD_INITIALISATION_FAILED
);
339 #endif // EEPROM_IN_SDCARD
341 #ifdef EEPROM_IN_EXTERNAL_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 We need to add configuration somewhere, e.g. bootloader image or reserved flash area, that can be read by the firmware.
347 // it's currently possible for the firmware resource allocation to be wrong after the config is loaded if the user changes the settings.
348 // This would cause undefined behaviour once the config is loaded. so for now, users must NOT change flash/pin configs needed for
349 // the system to boot and/or to save the config.
351 // note that target specific FLASH/SPI/QUADSPI configs are
352 // also not supported in USE_TARGET_CONFIG/targetConfigure() when using EEPROM_IN_EXTERNAL_FLASH.
356 // IMPORTANT: all default flash and pin configurations must be valid for the target after pgResetAll() is called.
357 // Target designers must ensure other devices connected the same SPI/QUADSPI interface as the flash chip do not
358 // cause communication issues with the flash chip. e.g. use external pullups on SPI/QUADSPI CS lines.
362 #ifdef TARGET_BUS_INIT
363 #error "EEPROM_IN_EXTERNAL_FLASH and TARGET_BUS_INIT are mutually exclusive"
366 configureSPIAndQuadSPI();
367 initFlags
|= SPI_AND_QSPI_INIT_ATTEMPTED
;
370 #ifndef USE_FLASH_CHIP
371 #error "EEPROM_IN_EXTERNAL_FLASH requires USE_FLASH_CHIP to be defined."
374 bool haveFlash
= flashInit(flashConfig());
377 failureMode(FAILURE_EXTERNAL_FLASH_INIT_FAILED
);
379 initFlags
|= FLASH_INIT_ATTEMPTED
;
381 #endif // EEPROM_IN_EXTERNAL_FLASH
385 ensureEEPROMStructureIsValid();
387 bool readSuccess
= readEEPROM();
389 #if defined(USE_BOARD_INFO)
390 initBoardInformation();
393 if (!readSuccess
|| !isEEPROMVersionValid() || strncasecmp(systemConfig()->boardIdentifier
, TARGET_BOARD_IDENTIFIER
, sizeof(TARGET_BOARD_IDENTIFIER
))) {
397 systemState
|= SYSTEM_STATE_CONFIG_LOADED
;
399 #ifdef USE_BRUSHED_ESC_AUTODETECT
400 // Now detect again with the actually configured pin for motor 1, if it is not the default pin.
401 ioTag_t configuredMotorIoTag
= motorConfig()->dev
.ioTags
[0];
403 if (configuredMotorIoTag
&& configuredMotorIoTag
!= motorIoTag
) {
404 detectBrushedESC(configuredMotorIoTag
);
408 debugMode
= systemConfig()->debug_mode
;
410 #ifdef TARGET_PREINIT
414 #if !defined(USE_FAKE_LED)
415 ledInit(statusLedConfig());
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());
484 // Only F4 has non-8MHz boards
485 systemClockSetHSEValue(systemConfig()->hseMhz
* 1000000U);
489 OverclockRebootIfNecessary(systemConfig()->cpu_overclock
);
492 // Configure MCO output after config is stable
494 mcoInit(mcoConfig());
498 timerInit(); // timer must be initialized before any channel is allocated
501 #ifdef BUS_SWITCH_PIN
505 #if defined(USE_UART)
506 uartPinConfigure(serialPinConfig());
509 #if defined(AVOID_UART1_FOR_PWM_PPM)
510 serialInit(featureIsEnabled(FEATURE_SOFTSERIAL
),
511 featureIsEnabled(FEATURE_RX_PPM
) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM
) ? SERIAL_PORT_USART1
: SERIAL_PORT_NONE
);
512 #elif defined(AVOID_UART2_FOR_PWM_PPM)
513 serialInit(featureIsEnabled(FEATURE_SOFTSERIAL
),
514 featureIsEnabled(FEATURE_RX_PPM
) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM
) ? SERIAL_PORT_USART2
: SERIAL_PORT_NONE
);
515 #elif defined(AVOID_UART3_FOR_PWM_PPM)
516 serialInit(featureIsEnabled(FEATURE_SOFTSERIAL
),
517 featureIsEnabled(FEATURE_RX_PPM
) || featureIsEnabled(FEATURE_RX_PARALLEL_PWM
) ? SERIAL_PORT_USART3
: SERIAL_PORT_NONE
);
519 serialInit(featureIsEnabled(FEATURE_SOFTSERIAL
), SERIAL_PORT_NONE
);
522 mixerInit(mixerConfig()->mixerMode
);
523 mixerConfigureOutput();
525 uint16_t idlePulse
= motorConfig()->mincommand
;
526 if (featureIsEnabled(FEATURE_3D
)) {
527 idlePulse
= flight3DConfig()->neutral3d
;
529 if (motorConfig()->dev
.motorPwmProtocol
== PWM_TYPE_BRUSHED
) {
530 idlePulse
= 0; // brushed motors
533 /* Motors needs to be initialized soon as posible because hardware initialization
534 * may send spurious pulses to esc's causing their early initialization. Also ppm
535 * receiver may share timer with motors so motors MUST be initialized here. */
536 motorDevInit(&motorConfig()->dev
, idlePulse
, getMotorCount());
537 systemState
|= SYSTEM_STATE_MOTORS_READY
;
544 else if (featureIsEnabled(FEATURE_RX_PPM
)) {
545 ppmRxInit(ppmConfig());
549 else if (featureIsEnabled(FEATURE_RX_PARALLEL_PWM
)) {
550 pwmRxInit(pwmConfig());
555 beeperInit(beeperDevConfig());
557 /* temp until PGs are implemented. */
558 #if defined(USE_INVERTER) && !defined(SIMULATOR_BUILD)
559 initInverters(serialPinConfig());
563 #ifdef TARGET_BUS_INIT
568 // Depending on compilation options SPI/QSPI initialisation may already be done.
569 if (!(initFlags
& SPI_AND_QSPI_INIT_ATTEMPTED
)) {
570 configureSPIAndQuadSPI();
571 initFlags
|= SPI_AND_QSPI_INIT_ATTEMPTED
;
575 /* MSC mode will start after init, but will not allow scheduler to run,
576 * so there is no bottleneck in reading and writing data */
578 if (mscCheckBoot() || mscCheckButton()) {
579 if (mscStart() == 0) {
582 systemResetFromMsc();
587 #ifdef USE_PERSISTENT_MSC_RTC
588 // if we didn't enter MSC mode then clear the persistent RTC value
589 persistentObjectWrite(PERSISTENT_OBJECT_RTC_HIGH
, 0);
590 persistentObjectWrite(PERSISTENT_OBJECT_RTC_LOW
, 0);
594 i2cHardwareConfigure(i2cConfig(0));
596 // Note: Unlike UARTs which are configured when client is present,
597 // I2C buses are initialized unconditionally if they are configured.
599 #ifdef USE_I2C_DEVICE_1
602 #ifdef USE_I2C_DEVICE_2
605 #ifdef USE_I2C_DEVICE_3
608 #ifdef USE_I2C_DEVICE_4
613 #endif // TARGET_BUS_INIT
615 #ifdef USE_HARDWARE_REVISION_DETECTION
616 updateHardwareRevision();
619 #if defined(STM32H7) && defined(USE_SDCARD_SDIO) // H7 only for now, likely should be applied to F4/F7 too
620 if (!(initFlags
& SD_INIT_ATTEMPTED
)) {
626 #ifdef USE_VTX_RTC6705
627 bool useRTC6705
= rtc6705IOInit(vtxIOConfig());
630 #ifdef USE_CAMERA_CONTROL
634 // XXX These kind of code should goto target/config.c?
635 // XXX And these no longer work properly as FEATURE_RANGEFINDER does control HCSR04 runtime configuration.
636 #if defined(RANGEFINDER_HCSR04_SOFTSERIAL2_EXCLUSIVE) && defined(USE_RANGEFINDER_HCSR04) && defined(USE_SOFTSERIAL2)
637 if (featureIsEnabled(FEATURE_RANGEFINDER
) && featureIsEnabled(FEATURE_SOFTSERIAL
)) {
638 serialRemovePort(SERIAL_PORT_SOFTSERIAL2
);
642 #if defined(RANGEFINDER_HCSR04_SOFTSERIAL1_EXCLUSIVE) && defined(USE_RANGEFINDER_HCSR04) && defined(USE_SOFTSERIAL1)
643 if (featureIsEnabled(FEATURE_RANGEFINDER
) && featureIsEnabled(FEATURE_SOFTSERIAL
)) {
644 serialRemovePort(SERIAL_PORT_SOFTSERIAL1
);
649 adcConfigMutable()->vbat
.enabled
= (batteryConfig()->voltageMeterSource
== VOLTAGE_METER_ADC
);
650 adcConfigMutable()->current
.enabled
= (batteryConfig()->currentMeterSource
== CURRENT_METER_ADC
);
652 // The FrSky D SPI RX sends RSSI_ADC_PIN (if configured) as A2
653 adcConfigMutable()->rssi
.enabled
= featureIsEnabled(FEATURE_RSSI_ADC
);
655 adcConfigMutable()->rssi
.enabled
|= (featureIsEnabled(FEATURE_RX_SPI
) && rxSpiConfig()->rx_spi_protocol
== RX_SPI_FRSKY_D
);
657 adcInit(adcConfig());
660 initBoardAlignment(boardAlignment());
662 if (!sensorsAutodetect()) {
663 // if gyro was not detected due to whatever reason, notify and don't arm.
664 if (isSystemConfigured()) {
665 indicateFailure(FAILURE_MISSING_ACC
, 2);
667 setArmingDisabled(ARMING_DISABLED_NO_GYRO
);
670 systemState
|= SYSTEM_STATE_SENSORS_READY
;
672 // gyro.targetLooptime set in sensorsAutodetect(),
673 // so we are ready to call validateAndFixGyroConfig(), pidInit(), and setAccelerationFilter()
674 validateAndFixGyroConfig();
675 pidInit(currentPidProfile
);
686 servoConfigureOutput();
687 if (isMixerUsingServos()) {
688 //pwm_params.useChannelForwarding = featureIsEnabled(FEATURE_CHANNEL_FORWARDING);
689 servoDevInit(&servoConfig()->dev
);
695 pinioInit(pinioConfig());
699 pinioBoxInit(pinioBoxConfig());
706 for (int i
= 0; i
< 10; i
++) {
709 #if defined(USE_BEEPER)
711 if (!(beeperConfig()->beeper_off_flags
& BEEPER_GET_FLAG(BEEPER_SYSTEM_INIT
))) {
729 cliInit(serialConfig());
737 * CMS, display devices and OSD
743 #if (defined(USE_OSD) || (defined(USE_MSP_DISPLAYPORT) && defined(USE_CMS)))
744 displayPort_t
*osdDisplayPort
= NULL
;
748 //The OSD need to be initialised after GYRO to avoid GYRO initialisation failure on some targets
750 if (featureIsEnabled(FEATURE_OSD
)) {
751 #if defined(USE_MAX7456)
752 // If there is a max7456 chip for the OSD then use it
753 osdDisplayPort
= max7456DisplayPortInit(vcdProfile());
754 #elif defined(USE_CMS) && defined(USE_MSP_DISPLAYPORT) && defined(USE_OSD_OVER_MSP_DISPLAYPORT) // OSD over MSP; not supported (yet)
755 osdDisplayPort
= displayPortMspInit();
757 // osdInit will register with CMS by itself.
758 osdInit(osdDisplayPort
);
762 #if defined(USE_CMS) && defined(USE_MSP_DISPLAYPORT)
763 // If BFOSD is not active, then register MSP_DISPLAYPORT as a CMS device.
765 cmsDisplayPortRegister(displayPortMspInit());
769 // Dashbord will register with CMS by itself.
770 if (featureIsEnabled(FEATURE_DASHBOARD
)) {
775 #if defined(USE_CMS) && defined(USE_SPEKTRUM_CMS_TELEMETRY) && defined(USE_TELEMETRY_SRXL)
776 // Register the srxl Textgen telemetry sensor as a displayport device
777 cmsDisplayPortRegister(displayPortSrxlInit());
781 if (featureIsEnabled(FEATURE_GPS
)) {
789 if (featureIsEnabled(FEATURE_LED_STRIP
)) {
795 if (featureIsEnabled(FEATURE_TELEMETRY
)) {
800 #ifdef USE_ESC_SENSOR
801 if (featureIsEnabled(FEATURE_ESC_SENSOR
)) {
806 #ifdef USE_USB_DETECT
807 usbCableDetectInit();
810 #ifdef USE_TRANSPONDER
811 if (featureIsEnabled(FEATURE_TRANSPONDER
)) {
813 transponderStartRepeating();
814 systemState
|= SYSTEM_STATE_TRANSPONDER_ENABLED
;
818 #ifdef USE_FLASH_CHIP
819 if (!(initFlags
& FLASH_INIT_ATTEMPTED
)) {
820 flashInit(flashConfig());
821 initFlags
|= FLASH_INIT_ATTEMPTED
;
830 if (blackboxConfig()->device
== BLACKBOX_DEVICE_SDCARD
) {
831 if (sdcardConfig()->mode
) {
832 if (!(initFlags
& SD_INIT_ATTEMPTED
)) {
833 initFlags
|= SD_INIT_ATTEMPTED
;
837 blackboxConfigMutable()->device
= BLACKBOX_DEVICE_NONE
;
845 if (mixerConfig()->mixerMode
== MIXER_GIMBAL
) {
846 accSetCalibrationCycles(CALIBRATING_ACC_CYCLES
);
849 gyroStartCalibration(false);
851 baroSetCalibrationCycles(CALIBRATING_BARO_CYCLES
);
854 #if defined(USE_VTX_COMMON) || defined(USE_VTX_CONTROL)
858 #ifdef USE_VTX_CONTROL
861 #if defined(USE_VTX_COMMON)
865 #ifdef USE_VTX_SMARTAUDIO
873 #ifdef USE_VTX_RTC6705
874 if (!vtxCommonDevice() && useRTC6705
) { // external VTX takes precedence when configured.
879 #endif // VTX_CONTROL
883 // TODO - not implemented yet
887 ENABLE_STATE(SMALL_ANGLE
);
889 #ifdef SOFTSERIAL_LOOPBACK
890 // FIXME this is a hack, perhaps add a FUNCTION_LOOPBACK to support it properly
891 loopbackPort
= (serialPort_t
*)&(softSerialPorts
[0]);
892 if (!loopbackPort
->vTable
) {
893 loopbackPort
= openSoftSerial(0, NULL
, 19200, SERIAL_NOT_INVERTED
);
895 serialPrint(loopbackPort
, "LOOPBACK\r\n");
898 batteryInit(); // always needs doing, regardless of features.
901 if (featureIsEnabled(FEATURE_DASHBOARD
)) {
902 #ifdef USE_OLED_GPS_DEBUG_PAGE_ONLY
903 dashboardShowFixedPage(PAGE_GPS
);
905 dashboardResetPageCycling();
906 dashboardEnablePageCycling();
913 #endif // USE_RCDEVICE
919 #ifdef USE_PERSISTENT_STATS
923 setArmingDisabled(ARMING_DISABLED_BOOT_GRACE_TIME
);
927 systemState
|= SYSTEM_STATE_READY
;