diff --git a/make/source.mk b/make/source.mk
index c17feaaab..5528bb326 100644
--- a/make/source.mk
+++ b/make/source.mk
@@ -21,6 +21,7 @@ COMMON_SRC = \
drivers/exti.c \
drivers/io.c \
drivers/light_led.c \
+ drivers/mco.c \
drivers/pinio.c \
drivers/resource.c \
drivers/rcc.c \
diff --git a/src/main/drivers/mco.c b/src/main/drivers/mco.c
new file mode 100644
index 000000000..33eb6674f
--- /dev/null
+++ b/src/main/drivers/mco.c
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight are free software. You can redistribute
+ * this software and/or modify this software under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cleanflight and Betaflight are distributed in the hope that they
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+#include
+#include
+#include
+
+#include "platform.h"
+
+#ifdef USE_MCO
+
+#include "drivers/io.h"
+#include "pg/mco.h"
+
+void mcoInit(const mcoConfig_t *mcoConfig)
+{
+ // Only configure MCO2 with PLLI2SCLK as source for now.
+ // Other MCO1 and other sources can easily be added.
+ // For all F4 and F7 varianets, MCO1 is on PA8 and MCO2 is on PC9.
+
+ if (mcoConfig->enabled[1]) {
+ IO_t io = IOGetByTag(DEFIO_TAG_E(PC9));
+ IOInit(io, OWNER_MCO, 2);
+ HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_PLLI2SCLK, RCC_MCODIV_4);
+ IOConfigGPIOAF(io, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL), GPIO_AF0_MCO);
+ }
+}
+#endif
diff --git a/src/main/drivers/mco.h b/src/main/drivers/mco.h
new file mode 100644
index 000000000..a9a5b0692
--- /dev/null
+++ b/src/main/drivers/mco.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight are free software. You can redistribute
+ * this software and/or modify this software under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cleanflight and Betaflight are distributed in the hope that they
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+#pragma once
+
+#include "pg/mco.h"
+
+void mcoInit(const mcoConfig_t *mcoConfig);
diff --git a/src/main/drivers/resource.c b/src/main/drivers/resource.c
index c1bab637d..620e347de 100644
--- a/src/main/drivers/resource.c
+++ b/src/main/drivers/resource.c
@@ -76,4 +76,5 @@ const char * const ownerNames[OWNER_TOTAL_COUNT] = {
"USB_MSC_PIN",
"SPI_PREINIT_IPU",
"SPI_PREINIT_OPU",
+ "MCO",
};
diff --git a/src/main/drivers/resource.h b/src/main/drivers/resource.h
index 54c66da9d..9d23789d6 100644
--- a/src/main/drivers/resource.h
+++ b/src/main/drivers/resource.h
@@ -76,6 +76,7 @@ typedef enum {
OWNER_USB_MSC_PIN,
OWNER_SPI_PREINIT_IPU,
OWNER_SPI_PREINIT_OPU,
+ OWNER_MCO,
OWNER_TOTAL_COUNT
} resourceOwner_e;
diff --git a/src/main/fc/init.c b/src/main/fc/init.c
index 7bc5ab5f5..d49d2723c 100644
--- a/src/main/fc/init.c
+++ b/src/main/fc/init.c
@@ -56,6 +56,7 @@
#include "drivers/inverter.h"
#include "drivers/io.h"
#include "drivers/light_led.h"
+#include "drivers/mco.h"
#include "drivers/nvic.h"
#include "drivers/pwm_esc_detect.h"
#include "drivers/pwm_output.h"
@@ -96,6 +97,7 @@
#include "pg/bus_i2c.h"
#include "pg/bus_spi.h"
#include "pg/flash.h"
+#include "pg/mco.h"
#include "pg/pinio.h"
#include "pg/piniobox.h"
#include "pg/pg.h"
@@ -295,6 +297,12 @@ void init(void)
}
#endif
+ // Configure MCO output after config is stable
+
+#ifdef USE_MCO
+ mcoInit(mcoConfig());
+#endif
+
#if defined(USE_SPEKTRUM_BIND)
if (featureIsEnabled(FEATURE_RX_SERIAL)) {
switch (rxConfig()->serialrx_provider) {
diff --git a/src/main/interface/cli.c b/src/main/interface/cli.c
index 5cf455ca5..cf08ea1b4 100644
--- a/src/main/interface/cli.c
+++ b/src/main/interface/cli.c
@@ -128,6 +128,7 @@ extern uint8_t __config_end;
#include "pg/bus_spi.h"
#include "pg/gyrodev.h"
#include "pg/max7456.h"
+#include "pg/mco.h"
#include "pg/pinio.h"
#include "pg/pg.h"
#include "pg/pg_ids.h"
diff --git a/src/main/interface/settings.c b/src/main/interface/settings.c
index 4d5d41d68..f26f0ad27 100644
--- a/src/main/interface/settings.c
+++ b/src/main/interface/settings.c
@@ -72,6 +72,7 @@
#include "pg/flash.h"
#include "pg/gyrodev.h"
#include "pg/max7456.h"
+#include "pg/mco.h"
#include "pg/pg.h"
#include "pg/pg_ids.h"
#include "pg/pinio.h"
@@ -1190,6 +1191,9 @@ const clivalue_t valueTable[] = {
{ "gyro_2_i2c_address", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, I2C_ADDR7_MAX }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, i2cAddress) },
{ "gyro_2_sensor_align", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_ALIGNMENT }, PG_GYRO_DEVICE_CONFIG, PG_ARRAY_ELEMENT_OFFSET(gyroDeviceConfig_t, 1, align) },
#endif
+#ifdef USE_MCO
+ { "mco2_on_pc9", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MCO_CONFIG, offsetof(mcoConfig_t, enabled[1]) },
+#endif
};
const uint16_t valueTableEntryCount = ARRAYLEN(valueTable);
diff --git a/src/main/pg/mco.c b/src/main/pg/mco.c
new file mode 100644
index 000000000..e95f3e9b7
--- /dev/null
+++ b/src/main/pg/mco.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight are free software. You can redistribute
+ * this software and/or modify this software under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cleanflight and Betaflight are distributed in the hope that they
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+#include
+#include
+
+#include "platform.h"
+
+#ifdef USE_MCO
+
+#include "drivers/io.h"
+#include "pg/pg.h"
+#include "pg/pg_ids.h"
+#include "pg/mco.h"
+
+PG_REGISTER_WITH_RESET_TEMPLATE(mcoConfig_t, mcoConfig, PG_MCO_CONFIG, 0);
+
+PG_RESET_TEMPLATE(mcoConfig_t, mcoConfig,
+ .enabled[0] = 0,
+ .enabled[1] = 0,
+);
+#endif // USE_MCO
diff --git a/src/main/pg/mco.h b/src/main/pg/mco.h
new file mode 100644
index 000000000..d4fa86e3e
--- /dev/null
+++ b/src/main/pg/mco.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight are free software. You can redistribute
+ * this software and/or modify this software under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cleanflight and Betaflight are distributed in the hope that they
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "pg/pg.h"
+#include "drivers/io_types.h"
+
+typedef struct mcoConfig_s {
+ uint8_t enabled[2];
+} mcoConfig_t;
+
+PG_DECLARE(mcoConfig_t, mcoConfig);
diff --git a/src/main/pg/pg_ids.h b/src/main/pg/pg_ids.h
index d17448229..7794f7464 100644
--- a/src/main/pg/pg_ids.h
+++ b/src/main/pg/pg_ids.h
@@ -135,7 +135,8 @@
#define PG_BOARD_CONFIG 538
#define PG_RCDEVICE_CONFIG 539
#define PG_GYRO_DEVICE_CONFIG 540
-#define PG_BETAFLIGHT_END 540
+#define PG_MCO_CONFIG 541
+#define PG_BETAFLIGHT_END 541
// OSD configuration (subject to change)
diff --git a/src/main/target/common_pre.h b/src/main/target/common_pre.h
index 49dd02938..7614f9c08 100644
--- a/src/main/target/common_pre.h
+++ b/src/main/target/common_pre.h
@@ -78,6 +78,7 @@
#define USE_ADC_INTERNAL
#define USE_USB_CDC_HID
#define USE_USB_MSC
+#define USE_MCO
#endif
#if defined(STM32F4) || defined(STM32F7)
diff --git a/src/main/target/system_stm32f7xx.c b/src/main/target/system_stm32f7xx.c
index ef683a855..8c8d8900d 100644
--- a/src/main/target/system_stm32f7xx.c
+++ b/src/main/target/system_stm32f7xx.c
@@ -229,6 +229,19 @@
while (1);
}
+ // Configure PLLI2S for 27MHz operation
+ // Actual output will be done by mcoInit in drivers/mco.c
+
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_PLLI2S;
+ PeriphClkInitStruct.PLLI2S.PLLI2SN = 216;
+ PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
+ PeriphClkInitStruct.PLLI2S.PLLI2SQ = 2;
+ PeriphClkInitStruct.PLLI2SDivQ = 1;
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
+ {
+ while (1);
+ }
+
// Activating the timerprescalers while the APBx prescalers are 1/2/4 will connect the TIMxCLK to HCLK which has been configured to 216MHz
__HAL_RCC_TIMCLKPRESCALER(RCC_TIMPRES_ACTIVATED);