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/>.
25 #include "common/axis.h"
26 #include "common/color.h"
27 #include "common/atomic.h"
28 #include "common/maths.h"
30 #include "drivers/nvic.h"
32 #include "drivers/sensor.h"
33 #include "drivers/system.h"
34 #include "drivers/gpio.h"
35 #include "drivers/light_led.h"
36 #include "drivers/sound_beeper.h"
37 #include "drivers/timer.h"
38 #include "drivers/serial.h"
39 #include "drivers/serial_softserial.h"
40 #include "drivers/serial_uart.h"
41 #include "drivers/accgyro.h"
42 #include "drivers/compass.h"
43 #include "drivers/pwm_mapping.h"
44 #include "drivers/pwm_rx.h"
45 #include "drivers/adc.h"
46 #include "drivers/bus_i2c.h"
47 #include "drivers/bus_spi.h"
48 #include "drivers/inverter.h"
49 #include "drivers/flash_m25p16.h"
53 #include "io/serial.h"
54 #include "io/flashfs.h"
56 #include "io/escservo.h"
57 #include "io/rc_controls.h"
58 #include "io/gimbal.h"
59 #include "io/ledstrip.h"
60 #include "io/display.h"
62 #include "sensors/sensors.h"
63 #include "sensors/sonar.h"
64 #include "sensors/barometer.h"
65 #include "sensors/compass.h"
66 #include "sensors/acceleration.h"
67 #include "sensors/gyro.h"
68 #include "sensors/battery.h"
69 #include "sensors/boardalignment.h"
71 #include "telemetry/telemetry.h"
72 #include "blackbox/blackbox.h"
74 #include "flight/pid.h"
75 #include "flight/imu.h"
76 #include "flight/mixer.h"
77 #include "flight/failsafe.h"
78 #include "flight/navigation.h"
80 #include "config/runtime_config.h"
81 #include "config/config.h"
82 #include "config/config_profile.h"
83 #include "config/config_master.h"
85 #ifdef USE_HARDWARE_REVISION_DETECTION
86 #include "hardware_revision.h"
89 #include "build_config.h"
91 #ifdef DEBUG_SECTION_TIMES
92 uint32_t sectionTimes
[2][4];
94 extern uint32_t previousTime
;
96 #ifdef SOFTSERIAL_LOOPBACK
97 serialPort_t
*loopbackPort
;
100 failsafe_t
*failsafe
;
102 void printfSupportInit(void);
103 void timerInit(void);
104 void telemetryInit(void);
105 void serialInit(serialConfig_t
*initialSerialConfig
);
106 failsafe_t
* failsafeInit(rxConfig_t
*intialRxConfig
);
107 pwmOutputConfiguration_t
*pwmInit(drv_pwm_config_t
*init
);
108 void mixerInit(mixerMode_e mixerMode
, motorMixer_t
*customMixers
);
109 void mixerUsePWMOutputConfiguration(pwmOutputConfiguration_t
*pwmOutputConfiguration
);
110 void rxInit(rxConfig_t
*rxConfig
, failsafe_t
*failsafe
);
111 void beepcodeInit(failsafe_t
*initialFailsafe
);
112 void gpsInit(serialConfig_t
*serialConfig
, gpsConfig_t
*initialGpsConfig
);
113 void navigationInit(gpsProfile_t
*initialGpsProfile
, pidProfile_t
*pidProfile
);
114 bool sensorsAutodetect(sensorAlignmentConfig_t
*sensorAlignmentConfig
, uint16_t gyroLpf
, uint8_t accHardwareToUse
, int8_t magHardwareToUse
, int16_t magDeclinationFromConfig
);
116 void displayInit(rxConfig_t
*intialRxConfig
);
117 void ledStripInit(ledConfig_t
*ledConfigsToUse
, hsvColor_t
*colorsToUse
, failsafe_t
* failsafeToUse
);
119 void spektrumBind(rxConfig_t
*rxConfig
);
122 // from system_stm32f30x.c
123 void SetSysClock(void);
126 // from system_stm32f10x.c
127 void SetSysClock(bool overclock
);
133 drv_pwm_config_t pwm_params
;
134 bool sensorsOK
= false;
140 ensureEEPROMContainsValidData();
145 SCB
->CPACR
= (0x3 << (10*2)) | (0x3 << (11*2));
152 // Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers
153 // Configure the Flash Latency cycles and enable prefetch buffer
154 SetSysClock(masterConfig
.emf_avoidance
);
157 #ifdef USE_HARDWARE_REVISION_DETECTION
158 detectHardwareRevision();
166 if (feature(FEATURE_RX_SERIAL
)) {
167 switch (masterConfig
.rxConfig
.serialrx_provider
) {
168 case SERIALRX_SPEKTRUM1024
:
169 case SERIALRX_SPEKTRUM2048
:
170 // Spektrum satellite binding if enabled on startup.
171 // Must be called before that 100ms sleep so that we don't lose satellite's binding window after startup.
172 // The rest of Spektrum initialization will happen later - via spektrumInit()
173 spektrumBind(&masterConfig
.rxConfig
);
181 timerInit(); // timer must be initialized before any channel is allocated
183 mixerInit(masterConfig
.mixerMode
, masterConfig
.customMixer
);
185 memset(&pwm_params
, 0, sizeof(pwm_params
));
186 // when using airplane/wing mixer, servo/motor outputs are remapped
187 if (masterConfig
.mixerMode
== MIXER_AIRPLANE
|| masterConfig
.mixerMode
== MIXER_FLYING_WING
)
188 pwm_params
.airplane
= true;
190 pwm_params
.airplane
= false;
191 #if defined(USE_USART2) && defined(STM32F10X)
192 pwm_params
.useUART2
= doesConfigurationUsePort(SERIAL_PORT_USART2
);
194 pwm_params
.useVbat
= feature(FEATURE_VBAT
);
195 pwm_params
.useSoftSerial
= feature(FEATURE_SOFTSERIAL
);
196 pwm_params
.useParallelPWM
= feature(FEATURE_RX_PARALLEL_PWM
);
197 pwm_params
.useRSSIADC
= feature(FEATURE_RSSI_ADC
);
198 pwm_params
.useCurrentMeterADC
= feature(FEATURE_CURRENT_METER
)
199 && masterConfig
.batteryConfig
.currentMeterType
== CURRENT_SENSOR_ADC
;
200 pwm_params
.useLEDStrip
= feature(FEATURE_LED_STRIP
);
201 pwm_params
.usePPM
= feature(FEATURE_RX_PPM
);
202 pwm_params
.useSerialRx
= feature(FEATURE_RX_SERIAL
);
205 pwm_params
.useServos
= isMixerUsingServos();
206 pwm_params
.extraServos
= currentProfile
->gimbalConfig
.gimbal_flags
& GIMBAL_FORWARDAUX
;
207 pwm_params
.servoCenterPulse
= masterConfig
.escAndServoConfig
.servoCenterPulse
;
208 pwm_params
.servoPwmRate
= masterConfig
.servo_pwm_rate
;
211 pwm_params
.useOneshot
= feature(FEATURE_ONESHOT125
);
212 pwm_params
.motorPwmRate
= masterConfig
.motor_pwm_rate
;
213 pwm_params
.idlePulse
= PULSE_1MS
; // standard PWM for brushless ESC (default, overridden below)
214 if (feature(FEATURE_3D
))
215 pwm_params
.idlePulse
= masterConfig
.flight3DConfig
.neutral3d
;
216 if (pwm_params
.motorPwmRate
> 500)
217 pwm_params
.idlePulse
= 0; // brushed motors
219 pwmRxInit(masterConfig
.inputFilteringMode
);
221 pwmOutputConfiguration_t
*pwmOutputConfiguration
= pwmInit(&pwm_params
);
223 mixerUsePWMOutputConfiguration(pwmOutputConfiguration
);
226 beeperConfig_t beeperConfig
= {
228 .gpioPort
= BEEP_GPIO
,
229 .gpioPeripheral
= BEEP_PERIPHERAL
,
230 #ifdef BEEPER_INVERTED
231 .gpioMode
= Mode_Out_PP
,
234 .gpioMode
= Mode_Out_OD
,
239 if (hardwareRevision
>= NAZE32_REV5
) {
240 // naze rev4 and below used opendrain to PNP for buzzer. Rev5 and above use PP to NPN.
241 beeperConfig
.gpioMode
= Mode_Out_PP
;
242 beeperConfig
.isInverted
= true;
246 beeperInit(&beeperConfig
);
259 #ifdef USE_HARDWARE_REVISION_DETECTION
260 updateHardwareRevision();
265 if (hardwareRevision
!= NAZE32_SP
) {
269 if (!doesConfigurationUsePort(SERIAL_PORT_USART3
)) {
278 drv_adc_config_t adc_params
;
280 adc_params
.enableRSSI
= feature(FEATURE_RSSI_ADC
);
281 adc_params
.enableCurrentMeter
= feature(FEATURE_CURRENT_METER
);
282 adc_params
.enableExternal1
= false;
284 adc_params
.enableExternal1
= true;
287 // optional ADC5 input on rev.5 hardware
288 adc_params
.enableExternal1
= (hardwareRevision
>= NAZE32_REV5
);
291 adcInit(&adc_params
);
295 initBoardAlignment(&masterConfig
.boardAlignment
);
298 if (feature(FEATURE_DISPLAY
)) {
299 displayInit(&masterConfig
.rxConfig
);
303 sensorsOK
= sensorsAutodetect(&masterConfig
.sensorAlignmentConfig
, masterConfig
.gyro_lpf
, masterConfig
.acc_hardware
, masterConfig
.mag_hardware
, currentProfile
->mag_declination
);
305 // if gyro was not detected due to whatever reason, we give up now.
311 for (i
= 0; i
< 10; i
++) {
323 if (sensors(SENSOR_MAG
))
329 serialInit(&masterConfig
.serialConfig
);
331 failsafe
= failsafeInit(&masterConfig
.rxConfig
);
332 beepcodeInit(failsafe
);
333 rxInit(&masterConfig
.rxConfig
, failsafe
);
336 if (feature(FEATURE_GPS
)) {
338 &masterConfig
.serialConfig
,
339 &masterConfig
.gpsConfig
342 ¤tProfile
->gpsProfile
,
343 ¤tProfile
->pidProfile
349 if (feature(FEATURE_SONAR
)) {
355 ledStripInit(masterConfig
.ledConfigs
, masterConfig
.colors
, failsafe
);
357 if (feature(FEATURE_LED_STRIP
)) {
363 if (feature(FEATURE_TELEMETRY
))
369 if (hardwareRevision
== NAZE32_REV5
) {
383 previousTime
= micros();
385 if (masterConfig
.mixerMode
== MIXER_GIMBAL
) {
386 accSetCalibrationCycles(CALIBRATING_ACC_CYCLES
);
388 gyroSetCalibrationCycles(CALIBRATING_GYRO_CYCLES
);
390 baroSetCalibrationCycles(CALIBRATING_BARO_CYCLES
);
394 // TODO - not implemented yet
397 ENABLE_STATE(SMALL_ANGLE
);
398 DISABLE_ARMING_FLAG(PREVENT_ARMING
);
400 #ifdef SOFTSERIAL_LOOPBACK
401 // FIXME this is a hack, perhaps add a FUNCTION_LOOPBACK to support it properly
402 loopbackPort
= (serialPort_t
*)&(softSerialPorts
[0]);
403 if (!loopbackPort
->vTable
) {
404 loopbackPort
= openSoftSerial(0, NULL
, 19200, SERIAL_NOT_INVERTED
);
406 serialPrint(loopbackPort
, "LOOPBACK\r\n");
409 // Now that everything has powered up the voltage and cell count be determined.
411 if (feature(FEATURE_VBAT
| FEATURE_CURRENT_METER
))
412 batteryInit(&masterConfig
.batteryConfig
);
415 if (feature(FEATURE_DISPLAY
)) {
416 #ifdef USE_OLED_GPS_DEBUG_PAGE_ONLY
417 displayShowFixedPage(PAGE_GPS
);
419 displayResetPageCycling();
420 displayEnablePageCycling();
430 #ifdef SOFTSERIAL_LOOPBACK
431 void processLoopback(void) {
433 uint8_t bytesWaiting
;
434 while ((bytesWaiting
= serialTotalBytesWaiting(loopbackPort
))) {
435 uint8_t b
= serialRead(loopbackPort
);
436 serialWrite(loopbackPort
, b
);
441 #define processLoopback()
453 void HardFault_Handler(void)
455 // fall out of the sky
456 writeAllMotors(masterConfig
.escAndServoConfig
.mincommand
);