2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
24 #include "blackbox/blackbox.h"
26 #include "common/axis.h"
27 #include "common/color.h"
28 #include "common/maths.h"
29 #include "common/printf.h"
31 #include "config/config_eeprom.h"
32 #include "config/feature.h"
33 #include "config/parameter_group.h"
34 #include "config/parameter_group_ids.h"
37 #include "cms/cms_types.h"
39 #include "drivers/nvic.h"
40 #include "drivers/sensor.h"
41 #include "drivers/system.h"
42 #include "drivers/dma.h"
43 #include "drivers/io.h"
44 #include "drivers/light_led.h"
45 #include "drivers/sound_beeper.h"
46 #include "drivers/timer.h"
47 #include "drivers/serial.h"
48 #include "drivers/serial_softserial.h"
49 #include "drivers/serial_uart.h"
50 #include "drivers/accgyro.h"
51 #include "drivers/compass.h"
52 #include "drivers/pwm_esc_detect.h"
53 #include "drivers/rx_pwm.h"
54 #include "drivers/pwm_output.h"
55 #include "drivers/adc.h"
56 #include "drivers/bus_i2c.h"
57 #include "drivers/bus_spi.h"
58 #include "drivers/buttons.h"
59 #include "drivers/inverter.h"
60 #include "drivers/flash_m25p16.h"
61 #include "drivers/sonar_hcsr04.h"
62 #include "drivers/sdcard.h"
63 #include "drivers/usb_io.h"
64 #include "drivers/transponder_ir.h"
65 #include "drivers/exti.h"
66 #include "drivers/max7456.h"
67 #include "drivers/vtx_rtc6705.h"
68 #include "drivers/vtx_common.h"
70 #include "fc/config.h"
71 #include "fc/fc_init.h"
72 #include "fc/fc_msp.h"
73 #include "fc/fc_tasks.h"
74 #include "fc/rc_controls.h"
75 #include "fc/runtime_config.h"
78 #include "msp/msp_serial.h"
81 #include "rx/spektrum.h"
83 #include "io/beeper.h"
84 #include "io/displayport_max7456.h"
85 #include "io/serial.h"
86 #include "io/flashfs.h"
88 #include "io/motors.h"
89 #include "io/servos.h"
90 #include "io/gimbal.h"
91 #include "io/ledstrip.h"
92 #include "io/dashboard.h"
93 #include "io/asyncfatfs/asyncfatfs.h"
94 #include "io/transponder_ir.h"
96 #include "io/osd_slave.h"
97 #include "io/displayport_msp.h"
98 #include "io/vtx_rtc6705.h"
99 #include "io/vtx_control.h"
100 #include "io/vtx_smartaudio.h"
101 #include "io/vtx_tramp.h"
103 #include "scheduler/scheduler.h"
105 #include "sensors/acceleration.h"
106 #include "sensors/barometer.h"
107 #include "sensors/battery.h"
108 #include "sensors/boardalignment.h"
109 #include "sensors/compass.h"
110 #include "sensors/esc_sensor.h"
111 #include "sensors/gyro.h"
112 #include "sensors/initialisation.h"
113 #include "sensors/sensors.h"
114 #include "sensors/sonar.h"
116 #include "telemetry/telemetry.h"
118 #include "flight/failsafe.h"
119 #include "flight/imu.h"
120 #include "flight/mixer.h"
121 #include "flight/navigation.h"
122 #include "flight/pid.h"
123 #include "flight/servos.h"
126 #ifdef USE_HARDWARE_REVISION_DETECTION
127 #include "hardware_revision.h"
130 #include "build/build_config.h"
131 #include "build/debug.h"
133 #ifdef TARGET_PREINIT
134 void targetPreInit(void);
137 #ifdef TARGET_BUS_INIT
138 void targetBusInit(void);
141 extern uint8_t motorControlEnable
;
143 #ifdef SOFTSERIAL_LOOPBACK
144 serialPort_t
*loopbackPort
;
147 uint8_t systemState
= SYSTEM_STATE_INITIALISING
;
149 void processLoopback(void)
151 #ifdef SOFTSERIAL_LOOPBACK
153 uint8_t bytesWaiting
;
154 while ((bytesWaiting
= serialRxBytesWaiting(loopbackPort
))) {
155 uint8_t b
= serialRead(loopbackPort
);
156 serialWrite(loopbackPort
, b
);
164 bool canUpdateVTX(void)
166 #if defined(MAX7456_SPI_INSTANCE) && defined(RTC6705_SPI_INSTANCE) && defined(SPI_SHARED_MAX7456_AND_RTC6705)
167 if (feature(FEATURE_OSD
)) {
168 return !max7456DmaInProgress();
175 #ifdef BUS_SWITCH_PIN
176 void busSwitchInit(void)
178 static IO_t busSwitchResetPin
= IO_NONE
;
180 busSwitchResetPin
= IOGetByTag(IO_TAG(BUS_SWITCH_PIN
));
181 IOInit(busSwitchResetPin
, OWNER_SYSTEM
, 0);
182 IOConfigGPIO(busSwitchResetPin
, IOCFG_OUT_PP
);
185 IOLo(busSwitchResetPin
);
191 #ifdef USE_HAL_DRIVER
199 // initialize IO (needed for all IO operations)
202 #ifdef USE_HARDWARE_REVISION_DETECTION
203 detectHardwareRevision();
206 #ifdef BRUSHED_ESC_AUTODETECT
212 ensureEEPROMContainsValidData();
215 systemState
|= SYSTEM_STATE_CONFIG_LOADED
;
217 //i2cSetOverclock(masterConfig.i2c_overclock);
219 debugMode
= systemConfig()->debug_mode
;
221 // Latch active features to be used for feature() in the remainder of init().
222 latchActiveFeatures();
224 #ifdef TARGET_PREINIT
228 ledInit(statusLedConfig());
239 // Check status of bind plug and exit if not active
240 delayMicroseconds(10); // allow configuration to settle
242 if (!isMPUSoftReset()) {
243 #if defined(BUTTON_A_PIN) && defined(BUTTON_B_PIN)
244 // two buttons required
245 uint8_t secondsRemaining
= 5;
246 bool bothButtonsHeld
;
248 bothButtonsHeld
= buttonAPressed() && buttonBPressed();
249 if (bothButtonsHeld
) {
250 if (--secondsRemaining
== 0) {
257 } while (bothButtonsHeld
);
262 #ifdef SPEKTRUM_BIND_PIN
263 if (feature(FEATURE_RX_SERIAL
)) {
264 switch (rxConfig()->serialrx_provider
) {
265 case SERIALRX_SPEKTRUM1024
:
266 case SERIALRX_SPEKTRUM2048
:
267 // Spektrum satellite binding if enabled on startup.
268 // Must be called before that 100ms sleep so that we don't lose satellite's binding window after startup.
269 // The rest of Spektrum initialization will happen later - via spektrumInit()
270 spektrumBind(rxConfigMutable());
278 timerInit(); // timer must be initialized before any channel is allocated
280 #ifdef BUS_SWITCH_PIN
284 #if defined(AVOID_UART1_FOR_PWM_PPM)
285 serialInit(feature(FEATURE_SOFTSERIAL
),
286 feature(FEATURE_RX_PPM
) || feature(FEATURE_RX_PARALLEL_PWM
) ? SERIAL_PORT_USART1
: SERIAL_PORT_NONE
);
287 #elif defined(AVOID_UART2_FOR_PWM_PPM)
288 serialInit(feature(FEATURE_SOFTSERIAL
),
289 feature(FEATURE_RX_PPM
) || feature(FEATURE_RX_PARALLEL_PWM
) ? SERIAL_PORT_USART2
: SERIAL_PORT_NONE
);
290 #elif defined(AVOID_UART3_FOR_PWM_PPM)
291 serialInit(feature(FEATURE_SOFTSERIAL
),
292 feature(FEATURE_RX_PPM
) || feature(FEATURE_RX_PARALLEL_PWM
) ? SERIAL_PORT_USART3
: SERIAL_PORT_NONE
);
294 serialInit(feature(FEATURE_SOFTSERIAL
), SERIAL_PORT_NONE
);
297 mixerInit(mixerConfig()->mixerMode
);
302 uint16_t idlePulse
= motorConfig()->mincommand
;
303 if (feature(FEATURE_3D
)) {
304 idlePulse
= flight3DConfig()->neutral3d
;
307 if (motorConfig()->dev
.motorPwmProtocol
== PWM_TYPE_BRUSHED
) {
308 featureClear(FEATURE_3D
);
309 idlePulse
= 0; // brushed motors
312 mixerConfigureOutput();
313 motorDevInit(&motorConfig()->dev
, idlePulse
, getMotorCount());
316 servoConfigureOutput();
317 if (isMixerUsingServos()) {
318 //pwm_params.useChannelForwarding = feature(FEATURE_CHANNEL_FORWARDING);
319 servoDevInit(&servoConfig()->dev
);
325 else if (feature(FEATURE_RX_PPM
)) {
326 ppmRxInit(ppmConfig(), motorConfig()->dev
.motorPwmProtocol
);
330 else if (feature(FEATURE_RX_PARALLEL_PWM
)) {
331 pwmRxInit(pwmConfig());
335 systemState
|= SYSTEM_STATE_MOTORS_READY
;
338 beeperInit(beeperDevConfig());
340 /* temp until PGs are implemented. */
345 #ifdef TARGET_BUS_INIT
350 #ifdef USE_SPI_DEVICE_1
353 #ifdef USE_SPI_DEVICE_2
356 #ifdef USE_SPI_DEVICE_3
359 #ifdef USE_SPI_DEVICE_4
365 #ifdef USE_I2C_DEVICE_1
368 #ifdef USE_I2C_DEVICE_2
371 #ifdef USE_I2C_DEVICE_3
374 #ifdef USE_I2C_DEVICE_4
379 #endif /* TARGET_BUS_INIT */
381 #ifdef USE_HARDWARE_REVISION_DETECTION
382 updateHardwareRevision();
389 #if defined(SONAR_SOFTSERIAL2_EXCLUSIVE) && defined(SONAR) && defined(USE_SOFTSERIAL2)
390 if (feature(FEATURE_SONAR
) && feature(FEATURE_SOFTSERIAL
)) {
391 serialRemovePort(SERIAL_PORT_SOFTSERIAL2
);
395 #if defined(SONAR_SOFTSERIAL1_EXCLUSIVE) && defined(SONAR) && defined(USE_SOFTSERIAL1)
396 if (feature(FEATURE_SONAR
) && feature(FEATURE_SOFTSERIAL
)) {
397 serialRemovePort(SERIAL_PORT_SOFTSERIAL1
);
402 adcConfigMutable()->vbat
.enabled
= (batteryConfig()->voltageMeterSource
== VOLTAGE_METER_ADC
);
403 adcConfigMutable()->current
.enabled
= (batteryConfig()->currentMeterSource
== CURRENT_METER_ADC
);
405 adcConfigMutable()->rssi
.enabled
= feature(FEATURE_RSSI_ADC
);
406 adcInit(adcConfig());
409 initBoardAlignment(boardAlignment());
411 if (!sensorsAutodetect()) {
412 // if gyro was not detected due to whatever reason, we give up now.
413 failureMode(FAILURE_MISSING_ACC
);
416 systemState
|= SYSTEM_STATE_SENSORS_READY
;
422 for (int i
= 0; i
< 10; i
++) {
426 if (!(getBeeperOffMask() & (1 << (BEEPER_SYSTEM_INIT
- 1)))) BEEP_ON
;
433 // gyro.targetLooptime set in sensorsAutodetect(), so we are ready to call pidInit()
434 pidInit(currentPidProfile
);
442 cliInit(serialConfig());
450 * CMS, display devices and OSD
456 #if (defined(OSD) || (defined(USE_MSP_DISPLAYPORT) && defined(CMS)) || defined(USE_OSD_SLAVE))
457 displayPort_t
*osdDisplayPort
= NULL
;
460 #if defined(OSD) && !defined(USE_OSD_SLAVE)
461 //The OSD need to be initialised after GYRO to avoid GYRO initialisation failure on some targets
463 if (feature(FEATURE_OSD
)) {
464 #if defined(USE_MAX7456)
465 // If there is a max7456 chip for the OSD then use it
466 osdDisplayPort
= max7456DisplayPortInit(vcdProfile());
467 #elif defined(USE_OSD_OVER_MSP_DISPLAYPORT) // OSD over MSP; not supported (yet)
468 osdDisplayPort
= displayPortMspInit();
470 // osdInit will register with CMS by itself.
471 osdInit(osdDisplayPort
);
475 #if defined(USE_OSD_SLAVE) && !defined(OSD)
476 #if defined(USE_MAX7456)
477 // If there is a max7456 chip for the OSD then use it
478 osdDisplayPort
= max7456DisplayPortInit(vcdProfile());
479 // osdInit will register with CMS by itself.
480 osdSlaveInit(osdDisplayPort
);
484 #if defined(CMS) && defined(USE_MSP_DISPLAYPORT)
485 // If BFOSD is not active, then register MSP_DISPLAYPORT as a CMS device.
487 cmsDisplayPortRegister(displayPortMspInit());
491 // Dashbord will register with CMS by itself.
492 if (feature(FEATURE_DASHBOARD
)) {
499 if (feature(FEATURE_GPS
)) {
508 if (feature(FEATURE_LED_STRIP
)) {
514 if (feature(FEATURE_TELEMETRY
)) {
519 #ifdef USE_ESC_SENSOR
520 if (feature(FEATURE_ESC_SENSOR
)) {
525 #ifdef USB_DETECT_PIN
526 usbCableDetectInit();
530 if (feature(FEATURE_TRANSPONDER
)) {
532 transponderStartRepeating();
533 systemState
|= SYSTEM_STATE_TRANSPONDER_ENABLED
;
538 #if defined(USE_FLASH_M25P16)
539 m25p16_init(flashConfig());
545 if (blackboxConfig()->device
== BLACKBOX_DEVICE_SDCARD
) {
546 sdcardInsertionDetectInit();
547 sdcard_init(sdcardConfig()->useDma
);
556 if (mixerConfig()->mixerMode
== MIXER_GIMBAL
) {
557 accSetCalibrationCycles(CALIBRATING_ACC_CYCLES
);
559 gyroSetCalibrationCycles();
561 baroSetCalibrationCycles(CALIBRATING_BARO_CYCLES
);
569 #ifdef VTX_SMARTAUDIO
578 #ifdef VTX_RTC6705OPTIONAL
579 if (!vtxCommonDeviceRegistered()) // external VTX takes precedence when configured.
586 #endif // VTX_CONTROL
589 // TODO - not implemented yet
592 ENABLE_STATE(SMALL_ANGLE
);
593 DISABLE_ARMING_FLAG(PREVENT_ARMING
);
595 #ifdef SOFTSERIAL_LOOPBACK
596 // FIXME this is a hack, perhaps add a FUNCTION_LOOPBACK to support it properly
597 loopbackPort
= (serialPort_t
*)&(softSerialPorts
[0]);
598 if (!loopbackPort
->vTable
) {
599 loopbackPort
= openSoftSerial(0, NULL
, 19200, SERIAL_NOT_INVERTED
);
601 serialPrint(loopbackPort
, "LOOPBACK\r\n");
604 batteryInit(); // always needs doing, regardless of features.
607 if (feature(FEATURE_DASHBOARD
)) {
608 #ifdef USE_OLED_GPS_DEBUG_PAGE_ONLY
609 dashboardShowFixedPage(PAGE_GPS
);
611 dashboardResetPageCycling();
612 dashboardEnablePageCycling();
621 // Latch active features AGAIN since some may be modified by init().
622 latchActiveFeatures();
623 motorControlEnable
= true;
630 systemState
|= SYSTEM_STATE_READY
;