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 "common/axis.h"
25 #include "common/color.h"
26 #include "common/atomic.h"
27 #include "common/maths.h"
29 #include "drivers/nvic.h"
31 #include "drivers/sensor.h"
32 #include "drivers/system.h"
33 #include "drivers/gpio.h"
34 #include "drivers/light_led.h"
35 #include "drivers/sound_beeper.h"
36 #include "drivers/timer.h"
37 #include "drivers/serial.h"
38 #include "drivers/serial_softserial.h"
39 #include "drivers/serial_uart.h"
40 #include "drivers/accgyro.h"
41 #include "drivers/compass.h"
42 #include "drivers/pwm_mapping.h"
43 #include "drivers/pwm_rx.h"
44 #include "drivers/adc.h"
45 #include "drivers/bus_i2c.h"
46 #include "drivers/bus_spi.h"
47 #include "drivers/inverter.h"
48 #include "drivers/flash_m25p16.h"
49 #include "drivers/sonar_hcsr04.h"
50 #include "drivers/gyro_sync.h"
54 #include "io/beeper.h"
55 #include "io/serial.h"
56 #include "io/flashfs.h"
58 #include "io/escservo.h"
59 #include "io/rc_controls.h"
60 #include "io/gimbal.h"
61 #include "io/ledstrip.h"
62 #include "io/display.h"
64 #include "scheduler/scheduler.h"
66 #include "sensors/sensors.h"
67 #include "sensors/barometer.h"
68 #include "sensors/compass.h"
69 #include "sensors/acceleration.h"
70 #include "sensors/gyro.h"
71 #include "sensors/battery.h"
72 #include "sensors/boardalignment.h"
73 #include "sensors/initialisation.h"
75 #include "telemetry/telemetry.h"
76 #include "blackbox/blackbox.h"
78 #include "flight/pid.h"
79 #include "flight/imu.h"
80 #include "flight/mixer.h"
81 #include "flight/failsafe.h"
82 #include "flight/navigation_rewrite.h"
84 #include "config/runtime_config.h"
85 #include "config/config.h"
86 #include "config/config_profile.h"
87 #include "config/config_master.h"
89 #ifdef USE_HARDWARE_REVISION_DETECTION
90 #include "hardware_revision.h"
93 #include "build_config.h"
96 extern uint8_t motorControlEnable
;
98 #ifdef SOFTSERIAL_LOOPBACK
99 serialPort_t
*loopbackPort
;
102 void printfSupportInit(void);
103 void timerInit(void);
104 void telemetryInit(void);
105 void serialInit(serialConfig_t
*initialSerialConfig
, bool softserialEnabled
);
107 void cliInit(serialConfig_t
*serialConfig
);
108 void failsafeInit(rxConfig_t
*intialRxConfig
, uint16_t deadband3d_throttle
);
109 pwmIOConfiguration_t
*pwmInit(drv_pwm_config_t
*init
);
111 void mixerInit(mixerMode_e mixerMode
, motorMixer_t
*customMotorMixers
, servoMixer_t
*customServoMixers
);
113 void mixerInit(mixerMode_e mixerMode
, motorMixer_t
*customMotorMixers
);
115 void mixerUsePWMIOConfiguration(void);
116 void rxInit(rxConfig_t
*rxConfig
, modeActivationCondition_t
*modeActivationConditions
);
117 void gpsPreInit(gpsConfig_t
*initialGpsConfig
);
118 void gpsInit(serialConfig_t
*serialConfig
, gpsConfig_t
*initialGpsConfig
);
120 void displayInit(rxConfig_t
*intialRxConfig
);
121 void ledStripInit(ledConfig_t
*ledConfigsToUse
, hsvColor_t
*colorsToUse
, modeColorIndexes_t
*modeColorsToUse
, specialColorIndexes_t
*specialColorsToUse
);
122 void spektrumBind(rxConfig_t
*rxConfig
);
123 const sonarHcsr04Hardware_t
*sonarGetHardwareConfiguration(currentSensor_e currentSensor
);
126 // from system_stm32f30x.c
127 void SetSysClock(void);
130 // from system_stm32f10x.c
131 void SetSysClock(bool overclock
);
135 SYSTEM_STATE_INITIALISING
= 0,
136 SYSTEM_STATE_CONFIG_LOADED
= (1 << 0),
137 SYSTEM_STATE_SENSORS_READY
= (1 << 1),
138 SYSTEM_STATE_MOTORS_READY
= (1 << 2),
139 SYSTEM_STATE_READY
= (1 << 7)
142 static uint8_t systemState
= SYSTEM_STATE_INITIALISING
;
144 void flashLedsAndBeep(void)
148 for (uint8_t i
= 0; i
< 10; i
++) {
152 if (!(getPreferredBeeperOffMask() & (1 << (BEEPER_SYSTEM_INIT
- 1))))
167 ensureEEPROMContainsValidData();
170 systemState
|= SYSTEM_STATE_CONFIG_LOADED
;
172 // initialize IO (needed for all IO operations)
177 SCB
->CPACR
= (0x3 << (10*2)) | (0x3 << (11*2));
184 // Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers
185 // Configure the Flash Latency cycles and enable prefetch buffer
186 SetSysClock(masterConfig
.emf_avoidance
);
188 i2cSetOverclock(masterConfig
.i2c_overclock
);
190 #ifdef USE_HARDWARE_REVISION_DETECTION
191 detectHardwareRevision();
196 // Latch active features to be used for feature() in the remainder of init().
197 latchActiveFeatures();
200 ledInit(hardwareRevision
== AFF3_REV_1
? false : true);
206 if (feature(FEATURE_RX_SERIAL
)) {
207 switch (masterConfig
.rxConfig
.serialrx_provider
) {
208 case SERIALRX_SPEKTRUM1024
:
209 case SERIALRX_SPEKTRUM2048
:
210 // Spektrum satellite binding if enabled on startup.
211 // Must be called before that 100ms sleep so that we don't lose satellite's binding window after startup.
212 // The rest of Spektrum initialization will happen later - via spektrumInit()
213 spektrumBind(&masterConfig
.rxConfig
);
221 timerInit(); // timer must be initialized before any channel is allocated
223 serialInit(&masterConfig
.serialConfig
, feature(FEATURE_SOFTSERIAL
));
226 mixerInit(masterConfig
.mixerMode
, masterConfig
.customMotorMixer
, masterConfig
.customServoMixer
);
228 mixerInit(masterConfig
.mixerMode
, masterConfig
.customMotorMixer
);
231 drv_pwm_config_t pwm_params
;
232 memset(&pwm_params
, 0, sizeof(pwm_params
));
235 sonarGPIOConfig_t sonarGPIOConfig
;
236 if (feature(FEATURE_SONAR
)) {
237 const sonarHcsr04Hardware_t
*sonarHardware
= sonarGetHardwareConfiguration(masterConfig
.batteryConfig
.currentMeterType
);
239 sonarGPIOConfig
.gpio
= sonarHardware
->echo_gpio
;
240 sonarGPIOConfig
.triggerPin
= sonarHardware
->echo_pin
;
241 sonarGPIOConfig
.echoPin
= sonarHardware
->trigger_pin
;
242 pwm_params
.sonarGPIOConfig
= &sonarGPIOConfig
;
243 pwm_params
.useSonar
= true;
248 // when using airplane/wing mixer, servo/motor outputs are remapped
249 if (masterConfig
.mixerMode
== MIXER_AIRPLANE
|| masterConfig
.mixerMode
== MIXER_FLYING_WING
|| masterConfig
.mixerMode
== MIXER_CUSTOM_AIRPLANE
)
250 pwm_params
.airplane
= true;
252 pwm_params
.airplane
= false;
253 #if defined(USE_USART2) && defined(STM32F10X)
254 pwm_params
.useUART2
= doesConfigurationUsePort(SERIAL_PORT_USART2
);
257 pwm_params
.useUART3
= doesConfigurationUsePort(SERIAL_PORT_USART3
);
259 pwm_params
.useVbat
= feature(FEATURE_VBAT
);
260 pwm_params
.useSoftSerial
= feature(FEATURE_SOFTSERIAL
);
261 pwm_params
.useParallelPWM
= feature(FEATURE_RX_PARALLEL_PWM
);
262 pwm_params
.useRSSIADC
= feature(FEATURE_RSSI_ADC
);
263 pwm_params
.useCurrentMeterADC
= feature(FEATURE_CURRENT_METER
)
264 && masterConfig
.batteryConfig
.currentMeterType
== CURRENT_SENSOR_ADC
;
265 pwm_params
.useLEDStrip
= feature(FEATURE_LED_STRIP
);
266 pwm_params
.usePPM
= feature(FEATURE_RX_PPM
);
267 pwm_params
.useSerialRx
= feature(FEATURE_RX_SERIAL
);
270 pwm_params
.useServos
= isServoOutputEnabled();
271 pwm_params
.useChannelForwarding
= feature(FEATURE_CHANNEL_FORWARDING
);
272 pwm_params
.servoCenterPulse
= masterConfig
.escAndServoConfig
.servoCenterPulse
;
273 pwm_params
.servoPwmRate
= masterConfig
.servo_pwm_rate
;
276 pwm_params
.useOneshot
= feature(FEATURE_ONESHOT125
);
277 pwm_params
.motorPwmRate
= masterConfig
.motor_pwm_rate
;
278 pwm_params
.idlePulse
= masterConfig
.escAndServoConfig
.mincommand
;
279 if (feature(FEATURE_3D
))
280 pwm_params
.idlePulse
= masterConfig
.flight3DConfig
.neutral3d
;
281 if (pwm_params
.motorPwmRate
> 500)
282 pwm_params
.idlePulse
= 0; // brushed motors
284 #ifndef SKIP_RX_PWM_PPM
285 pwmRxInit(masterConfig
.inputFilteringMode
);
288 // pwmInit() needs to be called as soon as possible for ESC compatibility reasons
289 pwmInit(&pwm_params
);
291 mixerUsePWMIOConfiguration();
293 if (!feature(FEATURE_ONESHOT125
))
294 motorControlEnable
= true;
296 systemState
|= SYSTEM_STATE_MOTORS_READY
;
299 beeperConfig_t beeperConfig
= {
300 .ioTag
= IO_TAG(BEEPER
),
301 #ifdef BEEPER_INVERTED
310 if (hardwareRevision
>= NAZE32_REV5
) {
311 // naze rev4 and below used opendrain to PNP for buzzer. Rev5 and above use PP to NPN.
312 beeperConfig
.isOD
= false;
313 beeperConfig
.isInverted
= true;
317 beeperInit(&beeperConfig
);
330 #ifdef USE_HARDWARE_REVISION_DETECTION
331 updateHardwareRevision();
335 if (hardwareRevision
== NAZE32_SP
) {
336 serialRemovePort(SERIAL_PORT_SOFTSERIAL2
);
338 serialRemovePort(SERIAL_PORT_USART3
);
342 #if defined(SPRACINGF3) && defined(SONAR) && defined(USE_SOFTSERIAL2)
343 if (feature(FEATURE_SONAR
) && feature(FEATURE_SOFTSERIAL
)) {
344 serialRemovePort(SERIAL_PORT_SOFTSERIAL2
);
348 #if defined(FURYF3) && defined(SONAR) && defined(USE_SOFTSERIAL1)
349 if (feature(FEATURE_SONAR
) && feature(FEATURE_SOFTSERIAL
)) {
350 serialRemovePort(SERIAL_PORT_SOFTSERIAL1
);
356 if (hardwareRevision
!= NAZE32_SP
) {
359 if (!doesConfigurationUsePort(SERIAL_PORT_USART3
)) {
364 if (!doesConfigurationUsePort(SERIAL_PORT_USART3
)) {
373 drv_adc_config_t adc_params
;
375 adc_params
.enableVBat
= feature(FEATURE_VBAT
);
376 adc_params
.enableRSSI
= feature(FEATURE_RSSI_ADC
);
377 adc_params
.enableCurrentMeter
= feature(FEATURE_CURRENT_METER
);
378 adc_params
.enableExternal1
= false;
380 adc_params
.enableExternal1
= true;
383 // optional ADC5 input on rev.5 hardware
384 adc_params
.enableExternal1
= (hardwareRevision
>= NAZE32_REV5
);
387 adcInit(&adc_params
);
390 initBoardAlignment(&masterConfig
.boardAlignment
);
393 if (feature(FEATURE_DISPLAY
)) {
394 displayInit(&masterConfig
.rxConfig
);
399 if (feature(FEATURE_GPS
)) {
400 gpsPreInit(&masterConfig
.gpsConfig
);
404 // Set gyro sampling rate divider before initialization
405 gyroSetSampleRate(masterConfig
.looptime
, masterConfig
.gyro_lpf
, masterConfig
.gyroSync
, masterConfig
.gyroSyncDenominator
);
407 if (!sensorsAutodetect(&masterConfig
.sensorAlignmentConfig
,
408 masterConfig
.gyro_lpf
,
409 masterConfig
.acc_hardware
,
410 masterConfig
.mag_hardware
,
411 masterConfig
.baro_hardware
,
412 currentProfile
->mag_declination
)) {
414 // if gyro was not detected due to whatever reason, we give up now.
415 failureMode(FAILURE_MISSING_ACC
);
418 systemState
|= SYSTEM_STATE_SENSORS_READY
;
422 for (int i
= 0; i
< 10; i
++) {
434 if (sensors(SENSOR_MAG
))
440 mspInit(&masterConfig
.serialConfig
);
443 cliInit(&masterConfig
.serialConfig
);
446 failsafeInit(&masterConfig
.rxConfig
, masterConfig
.flight3DConfig
.deadband3d_throttle
);
448 rxInit(&masterConfig
.rxConfig
, currentProfile
->modeActivationConditions
);
451 if (feature(FEATURE_GPS
)) {
453 &masterConfig
.serialConfig
,
454 &masterConfig
.gpsConfig
461 &masterConfig
.navConfig
,
462 ¤tProfile
->pidProfile
,
463 ¤tProfile
->rcControlsConfig
,
464 &masterConfig
.rxConfig
,
465 &masterConfig
.flight3DConfig
,
466 &masterConfig
.escAndServoConfig
471 ledStripInit(masterConfig
.ledConfigs
, masterConfig
.colors
, masterConfig
.modeColors
, &masterConfig
.specialColors
);
473 if (feature(FEATURE_LED_STRIP
)) {
479 if (feature(FEATURE_TELEMETRY
)) {
486 if (hardwareRevision
== NAZE32_REV5
) {
489 #elif defined(USE_FLASH_M25P16)
500 gyroSetCalibrationCycles(CALIBRATING_GYRO_CYCLES
);
502 baroSetCalibrationCycles(CALIBRATING_BARO_CYCLES
);
506 // TODO - not implemented yet
509 ENABLE_STATE(SMALL_ANGLE
);
510 DISABLE_ARMING_FLAG(PREVENT_ARMING
);
512 #ifdef SOFTSERIAL_LOOPBACK
513 // FIXME this is a hack, perhaps add a FUNCTION_LOOPBACK to support it properly
514 loopbackPort
= (serialPort_t
*)&(softSerialPorts
[0]);
515 if (!loopbackPort
->vTable
) {
516 loopbackPort
= openSoftSerial(0, NULL
, 19200, SERIAL_NOT_INVERTED
);
518 serialPrint(loopbackPort
, "LOOPBACK\r\n");
521 // Now that everything has powered up the voltage and cell count be determined.
523 if (feature(FEATURE_VBAT
| FEATURE_CURRENT_METER
))
524 batteryInit(&masterConfig
.batteryConfig
);
530 // Latch active features AGAIN since some may be modified by init().
531 latchActiveFeatures();
532 motorControlEnable
= true;
534 systemState
|= SYSTEM_STATE_READY
;
537 #ifdef SOFTSERIAL_LOOPBACK
538 void processLoopback(void) {
540 uint8_t bytesWaiting
;
541 while ((bytesWaiting
= serialRxBytesWaiting(loopbackPort
))) {
542 uint8_t b
= serialRead(loopbackPort
);
543 serialWrite(loopbackPort
, b
);
548 #define processLoopback()
555 /* Setup scheduler */
558 rescheduleTask(TASK_GYROPID
, targetLooptime
);
559 setTaskEnabled(TASK_GYROPID
, true);
561 setTaskEnabled(TASK_SERIAL
, true);
563 setTaskEnabled(TASK_BEEPER
, true);
565 setTaskEnabled(TASK_BATTERY
, feature(FEATURE_VBAT
) || feature(FEATURE_CURRENT_METER
));
566 setTaskEnabled(TASK_RX
, true);
568 setTaskEnabled(TASK_GPS
, feature(FEATURE_GPS
));
571 setTaskEnabled(TASK_COMPASS
, sensors(SENSOR_MAG
));
574 setTaskEnabled(TASK_BARO
, sensors(SENSOR_BARO
));
577 setTaskEnabled(TASK_SONAR
, sensors(SENSOR_SONAR
));
580 setTaskEnabled(TASK_DISPLAY
, feature(FEATURE_DISPLAY
));
583 setTaskEnabled(TASK_TELEMETRY
, feature(FEATURE_TELEMETRY
));
586 setTaskEnabled(TASK_LEDSTRIP
, feature(FEATURE_LED_STRIP
));
595 void HardFault_Handler(void)
597 // fall out of the sky
598 uint8_t requiredState
= SYSTEM_STATE_CONFIG_LOADED
| SYSTEM_STATE_MOTORS_READY
;
599 if ((systemState
& requiredState
) == requiredState
) {