STM32h743-devboard-betaflight
PublicLoading…
STM32H743 Flight Controller (Betaflight Target)
This repository provides an open-source engineering blueprint, custom target files, and a 4-layer hardware carrier board design to run standard Betaflight firmware on a generic DevEBox STM32H743VIT6 development board.
Unlike commercial flight controllers that limit you to pre-configured layouts, utilizing a standard industrial developer board breaks open full control of the silicon. This project serves as a definitive architectural guide to overcoming severe bare-metal implementation bugs, remapping timers for advanced multi-rotor and actuator configurations, and running ultra-low latency PID loops on a highly affordable H7 platform.
Hardware Architecture Manifest
The target configuration files provided here are explicitly tailored and tested against the following component topology and hardware pin allocation mapping:
- Microcontroller Core: STM32H743VIT6 (ARM Cortex-M7 running at a 480MHz bus clock).
- Primary IMU (SPI1): BMI160 Gyro/Accelerometer module routed to native SPI1 pins:
PA4(Chip Select / CS)PA5(SCK),PA6(MISO / SDI),PA7(MOSI / SDO)- Dedicated
PC4EXTI hardware interrupt line synchronization.
- Secondary IMU (SPI2): BMI160 Gyro/Accelerometer module mapped onto isolated native SPI2 pins:
PB12(Chip Select / CS)PB13(SCK),PB14(MISO / SDI),PB15(MOSI / SDO)- Dedicated
PD10EXTI hardware interrupt line synchronization.
- Barometer (I2C1): BMP280 module routed to
PB8(SCL) andPB9(SDA), configured via hardware jumpers on the breakout module to default I2C Address0x76. - Blackbox Telemetry: High-speed onboard SDIO MicroSD card slot combined with an onboard QSPI external flash memory layer (
W25Q64JV):- SDIO (SDMMC1):
PC12(CK),PD2(CMD),PC8(D0),PC9(D1),PC10(D2),PC11(D3). Card detection is handled via software polling (SDCD_PINset toNONE). - QSPI:
PB2(CLK),PB6(CS),PD11(IO0),PD12(IO1),PE2(IO2),PD13(IO3).
- SDIO (SDMMC1):
- Power Supply Module Integration (GM V1.0): Integrated hardware telemetry lines from the buck-regulated external power module routed directly to the microcontroller's high-precision 16-bit ADC peripheral interface:
- Voltage Sensing (V_SENS): Routed to analog input pin
PC1(ADC_VBAT_PIN). - Current Sensing (I_SENS): Routed to analog input pin
PC0(ADC_CURR_PIN).
- Voltage Sensing (V_SENS): Routed to analog input pin
- Actuator Layout & Communications Matrix:
- Motors (1–8):
PA0(Motor 1),PA1(Motor 2),PA2(Motor 3),PA3(Motor 4),PB0(Motor 5, timer remapped),PB1(Motor 6, timer remapped),PD5(Motor 7),PD6(Motor 8). - Servos (1–4):
PE5(Servo 1),PE6(Servo 2),PE1(Servo 3, timer remapped),PA15(Servo 4, timer remapped). - Serial Peripherals:
UART1(PA9TX,PA10RX) dedicated to Serial RX;UART3(PD8TX,PD9RX) assigned to ESC Telemetry;UART6(PC6/PC7) andUART7(PE8/PE7) exposed for general telemetry/VTX expansion. - Peripherals: Beeper output assigned to
PC2(inverted configuration).
- Motors (1–8):
System Layout & Renderings
You can solder through hole Devboard to the SMD pads of this breakout board giving you clear explansion over configured pins, Eight through hole pads have been left on the breakout board that you can align the Devboard on top of breakout board. and similarly solder the BMI160, BMP280 GY board on the breakout board make the work much easy, Though i havent route the circuit for each sensor on the breakout board itself, you can easily do it if you want, or you can just go with GY boards!!!.
Detail guide on how the changes have been made is documented below, you can merge standard betaflight source code files with this. The project layout separates the custom hardware implementation from the localized Betaflight firmware tree structure as follows:
├── Hardware/ # Physical schematic and layout assets
│ ├── KiCad_Source/ # Raw .kicad_sch and .kicad_pcb project files
│ └── Renderings # Board images, schematics, and design references
|
├── STM32h743-devboard-betaflight/ # Target firmware deployment root
│ ├── src/ # Localized Betaflight source tree overlays
│ │ ├── config/
│ │ │ └── configs/
│ │ │ └── DEVBOARD/
│ │ │ └── config.h # Master firmware target pin mapping definitions
│ │ ├── main/
│ │ │ ├── drivers/
│ │ │ │ └── accgyro/
│ │ │ │ └── pios_bmi160.c
│ │ └── platform/
│ │ └── STM32/
│ │ └── startup/
│ │ └── system_stm32h7xx.c
1. Bare-Metal Hardware Troubleshooting
Bringing Betaflight up on standard industrial development boards reveals discrepancies between consumer flight controllers and raw silicon layouts. Below is the technical documentation of the critical bare-metal failures encountered during hardware debugging, along with their permanent firmware solutions.
Bug 1.1: 25MHz HSE Crystal & PLL1 Clock Configuration Failures
The Bug:
Standard Betaflight STM32H7 codebases are optimized for 8MHz or 24MHz external crystals. The DevEBox hardware utilizes a 25MHz HSE. Applying default configuration multipliers caused the internal voltage-controlled oscillator (VCO) to hit 3000MHz, which drastically exceeds the 960MHz hardware limit. This caused the phase-locked loop engine to fail, triggering an infinite safety reset loop inside HandleStuckSysTick().
The Structural Fix:
The internal clock structures (pll1ConfigRevY and pll1ConfigRevV) inside src/platform/STM32/startup/system_stm32h7xx.c must be rewritten to scale the 25MHz crystal safely:
// Adjusted clock parameters for a stable 480MHz SYSCLK
pllConfig_t pll1ConfigRevV = {
.clockMhz = 480,
.m = 5,
.n = 192,
.p = 2,
.q = 8,
.r = 5,
.vos = PWR_REGULATOR_VOLTAGE_SCALE0,
.vciRange = RCC_PLL1VCIRANGE_2,
};
Bug 1.2: Missing HSI48 Internal Oscillator & PLL3 USB Solution
The Bug:
To establish a stable USB Virtual COM Port (VCP), the STM32 USB peripheral requires a 48MHz clock stream. Betaflight natively attempts to activate the internal HSI48 oscillator. However, hardware debugging proved the DevEBox completely ignores RCC_CR_HSI48ON register writes, leaving the USB peripheral without a clock signal and failing to enumerate.
The Structural Fix: Bypass the dead internal HSI48 circuit and synthesize a 48MHz USB clock using the primary 25MHz HSE crystal routed through the PLL3 engine.
Define the macro override in your local config.h:
#define USE_USB_CLOCK_PLL3
Apply these specific division parameters inside the USB initialization block of system_stm32h7xx.c to step the 25MHz HSE down to an exact 48MHz envelope:
PLL3M = 5, // 25MHz HSE / 5 = 5MHz reference
PLL3N = 48, // 5MHz * 48 = 240MHz VCO3
PLL3Q = 5 // 240MHz VCO3 / 5 = 48MHz USB output clock
Bug 1.3: Dual BMI160 Cold-Boot Lockout & DMA Collision
The Bug: When booting two BMI160 gyroscopes simultaneously via SPI1 and SPI2, the secondary gyro regularly fails to lock DMA.
- DMA Hijacking:
DSHOT_BITBANG_1was statically allocated toDMA1 Stream 0, forcing the H7 DMAMUX auto-allocator to starveSPI1_TXof a continuous stream, resulting in CPU-polling mode (missing thedmaflag). - State Variable Collision: The driver code (
pios_bmi160.c) utilized global state variables (BMI160InitDone). When Gyro 1 initialized, it set the variable to true, which caused Gyro 2 to completely bypass its configuration logic on cold boots.
The Structural Fix:
First, bypass the DMAMUX auto-allocator by hardcoding explicit DMA offsets in your local config.h:
// Force dual-gyro initialization on boot
#define DEFAULT_GYRO_TO_USE GYRO_CONFIG_USE_GYRO_BOTH
// Explicit SPI DMA Stream Offsets (Bypasses DMAMUX Auto-Allocation Collisions)
#define SPI1_TX_DMA_OPT 5 // Maps to DMA1 Stream 4
#define SPI1_RX_DMA_OPT 2 // Maps to DMA1 Stream 1
#define SPI2_TX_DMA_OPT 3 // Maps to DMA1 Stream 2
#define SPI2_RX_DMA_OPT 4 // Maps to DMA1 Stream 3
Second, eliminate the shared global states within the driver. Inside src/main/drivers/accgyro/pios_bmi160.c, delete the global boolean variables (BMI160InitDone and BMI160Detected) and replace the initialization functions with this independent configuration logic:
uint8_t bmi160Detect(const extDevice_t *dev)
{
// Toggle CS to activate SPI
spiWrite(dev, 0xFF);
delay(100); // Give SPI some time to start up
// Check the chip ID
if (spiReadRegMsk(dev, BMI160_REG_CHIPID) != 0xd1) {
return MPU_NONE;
}
return BMI_160_SPI;
}
static void BMI160_Init(const extDevice_t *dev)
{
/* Configure the BMI160 Sensor */
if (BMI160_Config(dev) != 0) {
return;
}
bool do_foc = false;
/* Perform fast offset compensation if requested */
if (do_foc) {
BMI160_do_foc(dev);
}
}
2. Firmware Source Tree Modification & Compilation Guide
To replicate this build and compile the custom DevEBox target, follow these exact modifications within the Betaflight source tree.
1. Target Directory Setup
Create a new directory named DEVBOARD inside src/main/config/configs/.
Place your custom config.h files into this new folder.
2. Core Source Modifications
You must manually patch the following core Betaflight files to implement the bare-metal hardware fixes detailed in Section 1:
File: src/platform/STM32/startup/system_stm32h7xx.c
- Locate the
pll1ConfigRevYandpll1ConfigRevVstructures. Update the multipliers for the 25MHz HSE: set.m = 25,.n = 400, and.p = 2. - Locate the USB clock configuration block. Comment out the
HSI48initialization and insert the PLL3 dividers:PLL3M = 5,PLL3N = 48, andPLL3Q = 5. - Locate the
SystemInit()function and comment out thememProtConfigure()call to prevent early boot memory protection faults on this specific developer silicon.
File: src/main/drivers/accgyro/pios_bmi160.c
- Locate the
bmi160Detect()andBMI160_Init()functions. - Delete the
BMI160InitDoneandBMI160Detectedglobal variables and paste the updated initialization block provided in Section 1.3 to ensure both gyros initialize independently and acquire DMA locks.
3. Compilation & Flashing
Step 1: Clone Betaflight with all submodules (prevents empty config/configs directories)
git clone --recurse-submodules [https://github.com/betaflight/betaflight.git](https://github.com/betaflight/betaflight.git)
cd betaflight
(Optional) If you already cloned Betaflight without submodules, run this to fetch them:
git submodule update --init --recursive
Step 2: Copy your custom DEVBOARD target files into the local Betaflight tree
Manually paste your DEVBOARD config.h into src/config/configs/DEVBOARD/ and patch the target core files.
Step 3: Clean and compile the unified DEVBOARD target
make clean
make DEVBOARD -j$(nproc)
Once compilation is complete, flash the resulting .hex file to your STM32H743 via STM32CubeProgrammer or the Betaflight Configurator while the board is in DFU mode. For DFU mode you need to connect BT0 to 3.3V (you can find these pins near the SWT pins).
4. Power Distribution & Critical Sensor Calibration
1. Power Supply Topology
This target configuration assumes the system is powered by an external step-down switching regulator delivering a stable 5V rail to the developer board. The onboard AMS1117-3.3 LDO regulator drops this input to 3.3V for the STM32H7 core and sensor buses, providing robust immunity against heavy Li-ion voltage sag down to a structural threshold of 4.4V.
2. Telemetry & ADC Scaling (User Calibration Required)
To achieve real-time battery status monitoring, the analog Voltage (V_SENS) and Current (I_SENS) lines from your power module must be routed to the microcontroller's ADC pins (PC1 for Voltage, PC0 for Current).
Mandatory Calibration Protocol: Do not rely blindly on stock software scale parameters. Every power module utilizes different internal resistor divider networks, and component manufacturing tolerances fluctuate.
As a structural baseline, this target defaults to our specific hardware mapping (a GM V1.0 power module with a 10.76:1 voltage divider):
set vbat_scale = 108
set current_meter_scale = 85
set current_meter_offset = -3500
save
⚠️ Before your first test flight, you must manually calibrate your hardware:
- Connect your fully assembled battery pack to the drone and measure the raw voltage at the main XT60 bus using a calibrated bench digital multimeter.
- Boot into the Betaflight Configurator GUI and check the reported voltage reading on the main Setup dashboard.
- Micro-adjust the
vbat_scalenumerical values up or down in the CLI tab (or the Power & Battery tab) until the software telemetry read-out matches your multimeter's hardware voltage precisely. - Perform a similar verification for the current sensor by measuring the draw of a known load and adjusting the
current_meter_scaleaccordingly.
No comments yet. Be the first to ask about this board.