Skip to content

targets: add BLADE_F4 (STM32F405) and BLADE_PRO_H7 (STM32H743)#48

Open
sensei-hacker wants to merge 6 commits intomaintenance-9.xfrom
hackrc1
Open

targets: add BLADE_F4 (STM32F405) and BLADE_PRO_H7 (STM32H743)#48
sensei-hacker wants to merge 6 commits intomaintenance-9.xfrom
hackrc1

Conversation

@sensei-hacker
Copy link
Owner

Summary

Adds two new flight controller targets from PR iNavFlight#9904 (hakrc1), with corrections applied before integration.

Changes

New targets:

  • BLADE_F4 — STM32F405 flight controller
  • BLADE_PRO_H7 — STM32H743 flight controller with dual IMU support

Corrections from code review:

  • Fix IMU2 SPI bus: MPU6000/ICM42605/BMI270 _BUS_2 macros changed from BUS_SPI1BUS_SPI4 (IMU2 is wired to SPI4 on PE11–PE14)
  • Assign unique TARGET_BOARD_IDENTIFIER: "BLF4" and "BLPH" (both were "RUSH")
  • Fix MAX_PWM_OUTPUT_PORTS to match actual timerHardware[] entries
  • Fix timerHardware[] comments to match actual pin order; remove dead commented-out duplicate block
  • Remove FEATURE_SOFTSERIAL from BLADE_F4 DEFAULT_FEATURES (no softserial port defined)
  • Remove unused USE_SPI_DEVICE_3 and pin definitions from BLADE_F4

Testing

Both targets build successfully against maintenance-9.x.

@qodo-code-review
Copy link

Review Summary by Qodo

Grey Divider

Walkthroughs

Grey Divider

File Changes

Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Mar 6, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. IMU2 busdev tag broken 🐞 Bug ✓ Correctness
Description
BLADE_PRO_H7 registers IMU bus devices with BUSDEV_REGISTER_SPI_TAG using (DEVFLAGS_NONE, <index>)
where the macro expects (<tag>, <flags>), causing both IMUs to have tag=0 and setting flags=1 for
the *_2 devices. This can prevent IMU2 from being discovered and may enable
DEVFLAGS_USE_RAW_REGISTERS on the second IMU, breaking SPI register access.
Code

src/main/target/BLADE_PRO_H7/target.c[R29-36]

+BUSDEV_REGISTER_SPI_TAG(busdev_mpu6000_1,  DEVHW_MPU6000,   MPU6000_SPI_BUS_1, MPU6000_CS_PIN_1,  MPU6000_EXTI_PIN_1,   DEVFLAGS_NONE, 0,  IMU_MPU6000_ALIGN_1);
+BUSDEV_REGISTER_SPI_TAG(busdev_mpu6000_2,  DEVHW_MPU6000,   MPU6000_SPI_BUS_2, MPU6000_CS_PIN_2,  MPU6000_EXTI_PIN_2,   DEVFLAGS_NONE, 1,  IMU_MPU6000_ALIGN_2);
+
+BUSDEV_REGISTER_SPI_TAG(busdev_icm42688_1, DEVHW_ICM42605, ICM42605_SPI_BUS_1, ICM42605_CS_PIN_1, ICM42605_EXTI_PIN_1,  DEVFLAGS_NONE, 0,  IMU_ICM42605_ALIGN_1);
+BUSDEV_REGISTER_SPI_TAG(busdev_icm42688_2, DEVHW_ICM42605, ICM42605_SPI_BUS_2, ICM42605_CS_PIN_2, ICM42605_EXTI_PIN_2,  DEVFLAGS_NONE, 1,  IMU_ICM42605_ALIGN_2);
+
+BUSDEV_REGISTER_SPI_TAG(busdev_bmi270_1,   DEVHW_BMI270,   BMI270_SPI_BUS_1,   BMI270_CS_PIN_1,   BMI270_EXTI_PIN_1,    DEVFLAGS_NONE, 0, IMU_BMI270_ALIGN_1);
+BUSDEV_REGISTER_SPI_TAG(busdev_bmi270_2,   DEVHW_BMI270,   BMI270_SPI_BUS_2,   BMI270_CS_PIN_2,   BMI270_EXTI_PIN_2,    DEVFLAGS_NONE, 1, IMU_BMI270_ALIGN_2);
Evidence
The macro signature is BUSDEV_REGISTER_SPI_TAG(..., _tag, _flags, _param); in BLADE_PRO_H7 it is
called with DEVFLAGS_NONE in the _tag position and 0/1 in the _flags position. busDeviceInit later
selects descriptors strictly by matching the requested tag to descriptor->tag; IMU drivers pass
gyro->imuSensorToUse (0/1) as the tag, so the IMU2 (tag=1) lookup will fail. Additionally, flags=1
corresponds to DEVFLAGS_USE_RAW_REGISTERS, which alters SPI register addressing semantics.

src/main/target/BLADE_PRO_H7/target.c[29-36]
src/main/drivers/bus.h[219-243]
src/main/drivers/bus.h[151-158]
src/main/drivers/bus.c[115-135]
src/main/drivers/accgyro/accgyro_mpu6000.c[190-200]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`BUSDEV_REGISTER_SPI_TAG` is called with `DEVFLAGS_NONE` in the `_tag` position and `0/1` in the `_flags` position. This breaks tag-based device selection (`tag==descriptor-&gt;tag`) and unintentionally enables `DEVFLAGS_USE_RAW_REGISTERS` for the second IMU descriptors.

### Issue Context
- `BUSDEV_REGISTER_SPI_TAG(..., _tag, _flags, _param)` stores `_tag` into `descriptor.tag` and `_flags` into `descriptor.flags`.
- IMU drivers call `busDeviceInit(..., gyro-&gt;imuSensorToUse, ...)` where `imuSensorToUse` is the IMU index (0 or 1).

### Fix Focus Areas
- src/main/target/BLADE_PRO_H7/target.c[29-36]

### Proposed change
For each of the six registrations, change:
- `..., DEVFLAGS_NONE, 0, ...` -&gt; `..., 0, DEVFLAGS_NONE, ...`
- `..., DEVFLAGS_NONE, 1, ...` -&gt; `..., 1, DEVFLAGS_NONE, ...`

(Repeat for MPU6000, ICM42605, BMI270 descriptors.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. H7 DMA stream reuse 🐞 Bug ⛯ Reliability
Description
Several BLADE_PRO_H7 OUTPUT_AUTO timer entries use the same DMA mapping variant (0), which maps to
the same DMA stream on STM32H7. When multiple such channels are configured for DMA-based output
(e.g., DSHOT), later channels can fail DMA init and silently produce no output.
Code

src/main/target/BLADE_PRO_H7/target.c[R38-53]

+timerHardware_t timerHardware[] = {
+    DEF_TIM(TIM3, CH4, PB1, TIM_USE_OUTPUT_AUTO, 0, 0),   // S2
+    DEF_TIM(TIM3, CH3, PB0, TIM_USE_OUTPUT_AUTO, 0, 1),   // S1
+    DEF_TIM(TIM5, CH2, PA1, TIM_USE_OUTPUT_AUTO, 0, 2),   // S4  
+    DEF_TIM(TIM5, CH1, PA0, TIM_USE_OUTPUT_AUTO, 0, 3),   // S3  
+ 
+    DEF_TIM(TIM5, CH3, PA2, TIM_USE_OUTPUT_AUTO, 0, 4),   // S5
+    DEF_TIM(TIM5, CH4, PA3, TIM_USE_OUTPUT_AUTO, 0, 5),   // S6
+    DEF_TIM(TIM4, CH1, PD12, TIM_USE_OUTPUT_AUTO, 0, 6),   // S7
+    DEF_TIM(TIM4, CH2, PD13, TIM_USE_OUTPUT_AUTO, 0, 7),   // S8
+
+    DEF_TIM(TIM15, CH1, PE5, TIM_USE_OUTPUT_AUTO, 0, 0),   // S11
+    DEF_TIM(TIM15, CH2, PE6, TIM_USE_OUTPUT_AUTO, 0, 0),   // S12 DMA_NONE
+    DEF_TIM(TIM4, CH4, PD15, TIM_USE_OUTPUT_AUTO, 0, 0),   // S10 DMA_NONE
+	DEF_TIM(TIM4, CH3, PD14, TIM_USE_OUTPUT_AUTO, 0, 0),   // S9
+
Evidence
On STM32H7, the 6th argument of DEF_TIM selects a DMA mapping variant; variant 0 resolves to DMA1
stream 0. BLADE_PRO_H7 uses variant 0 on multiple OUTPUT_AUTO channels beyond the first 8. DMA
lookup intentionally ignores the request/channel and matches only DMA+stream; DMA setup aborts if
that stream is already owned, and DSHOT will skip unconfigured ports, resulting in missing motor
output without a hard failure.

src/main/target/BLADE_PRO_H7/target.c[38-53]
src/main/drivers/timer_def_stm32h7xx.h[25-34]
src/main/drivers/timer_def_stm32h7xx.h[43-48]
src/main/drivers/dma_stm32h7xx.c[75-83]
src/main/drivers/timer_impl_hal.c[334-345]
src/main/drivers/pwm_output.c[282-314]
src/main/drivers/pwm_output.c[499-513]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
On STM32H7, the `DEF_TIM(..., dmavar)` argument selects a specific DMA stream mapping. In `BLADE_PRO_H7/target.c`, several OUTPUT_AUTO channels (e.g., S9 and S11) reuse `dmavar = 0`, which maps to the same DMA stream. Since DMA streams are single-owner (`impl_timerPWMConfigChannelDMA` aborts when already owned), DMA-based protocols like DSHOT can fail to configure on later channels, resulting in missing output.

### Issue Context
- `DEF_TIM(..., dmavar)` -&gt; `DEF_TIM_DMAMAP(dmavar, tim_ch)` selects a specific DMA stream.
- On H7, DMA tag resolution matches only `(DMA, stream)`, so reusing a stream across different peripherals collides.

### Fix Focus Areas
- src/main/target/BLADE_PRO_H7/target.c[38-56]

### Suggested fix
- Keep unique `dmavar` assignments across all OUTPUT_AUTO entries that may be used for DSHOT.
 - Example approach: keep existing 0..7 for S1..S8, then change S9/S11 (and any other DMA-capable extra outputs) to use unused variants 8..15.
- For channels that are known to have `DMA_NONE` in the H7 timer map (e.g., TIM15 CH2, TIM4 CH4), consider changing their `usageFlags` from `TIM_USE_OUTPUT_AUTO` to `TIM_USE_SERVO` if they are not intended to ever be used as DSHOT motor outputs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +29 to +36
BUSDEV_REGISTER_SPI_TAG(busdev_mpu6000_1, DEVHW_MPU6000, MPU6000_SPI_BUS_1, MPU6000_CS_PIN_1, MPU6000_EXTI_PIN_1, DEVFLAGS_NONE, 0, IMU_MPU6000_ALIGN_1);
BUSDEV_REGISTER_SPI_TAG(busdev_mpu6000_2, DEVHW_MPU6000, MPU6000_SPI_BUS_2, MPU6000_CS_PIN_2, MPU6000_EXTI_PIN_2, DEVFLAGS_NONE, 1, IMU_MPU6000_ALIGN_2);

BUSDEV_REGISTER_SPI_TAG(busdev_icm42688_1, DEVHW_ICM42605, ICM42605_SPI_BUS_1, ICM42605_CS_PIN_1, ICM42605_EXTI_PIN_1, DEVFLAGS_NONE, 0, IMU_ICM42605_ALIGN_1);
BUSDEV_REGISTER_SPI_TAG(busdev_icm42688_2, DEVHW_ICM42605, ICM42605_SPI_BUS_2, ICM42605_CS_PIN_2, ICM42605_EXTI_PIN_2, DEVFLAGS_NONE, 1, IMU_ICM42605_ALIGN_2);

BUSDEV_REGISTER_SPI_TAG(busdev_bmi270_1, DEVHW_BMI270, BMI270_SPI_BUS_1, BMI270_CS_PIN_1, BMI270_EXTI_PIN_1, DEVFLAGS_NONE, 0, IMU_BMI270_ALIGN_1);
BUSDEV_REGISTER_SPI_TAG(busdev_bmi270_2, DEVHW_BMI270, BMI270_SPI_BUS_2, BMI270_CS_PIN_2, BMI270_EXTI_PIN_2, DEVFLAGS_NONE, 1, IMU_BMI270_ALIGN_2);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Imu2 busdev tag broken 🐞 Bug ✓ Correctness

BLADE_PRO_H7 registers IMU bus devices with BUSDEV_REGISTER_SPI_TAG using (DEVFLAGS_NONE, <index>)
where the macro expects (<tag>, <flags>), causing both IMUs to have tag=0 and setting flags=1 for
the *_2 devices. This can prevent IMU2 from being discovered and may enable
DEVFLAGS_USE_RAW_REGISTERS on the second IMU, breaking SPI register access.
Agent Prompt
### Issue description
`BUSDEV_REGISTER_SPI_TAG` is called with `DEVFLAGS_NONE` in the `_tag` position and `0/1` in the `_flags` position. This breaks tag-based device selection (`tag==descriptor->tag`) and unintentionally enables `DEVFLAGS_USE_RAW_REGISTERS` for the second IMU descriptors.

### Issue Context
- `BUSDEV_REGISTER_SPI_TAG(..., _tag, _flags, _param)` stores `_tag` into `descriptor.tag` and `_flags` into `descriptor.flags`.
- IMU drivers call `busDeviceInit(..., gyro->imuSensorToUse, ...)` where `imuSensorToUse` is the IMU index (0 or 1).

### Fix Focus Areas
- src/main/target/BLADE_PRO_H7/target.c[29-36]

### Proposed change
For each of the six registrations, change:
- `..., DEVFLAGS_NONE, 0, ...` -> `..., 0, DEVFLAGS_NONE, ...`
- `..., DEVFLAGS_NONE, 1, ...` -> `..., 1, DEVFLAGS_NONE, ...`

(Repeat for MPU6000, ICM42605, BMI270 descriptors.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants