Bug Description
On the KAKUTEH7WING target (and any other H7 target with HSE_MHZ 16), the PLL2 VCO exceeds the STM32H7 PLL specification.
Root Cause
PLL2 dividers are hardcoded in src/main/target/system_stm32h7xx.c (lines 500-512):
RCC_PeriphClkInit.PLL2.PLL2M = 5;
RCC_PeriphClkInit.PLL2.PLL2N = 500;
RCC_PeriphClkInit.PLL2.PLL2R = 4; // 200MHz (for SDMMC)
This assumes HSE = 8 MHz, giving VCO = 8/5 × 500 = 800 MHz within the PLL2 wide VCO range (192-836 MHz per DS12110 Rev 11 §6.3.10 (PLL characteristics). PLL2R = 4 gives 200 MHz SDMMC kernel clock.
On KAKUTEH7WING (HSE = 16 MHz), the math is:
VCO = 16 / 5 × 500 = 1600 MHz
| Output |
Divider |
Frequency |
VCO (836 MHz max) |
Status |
| PLL2P |
2 |
800 MHz |
1600 MHz |
~1.9× over VCO max |
| PLL2Q |
3 |
533 MHz |
1600 MHz |
~1.9× over VCO max |
| PLL2R (SDMMC) |
4 |
400 MHz |
1600 MHz |
~1.9× over VCO max |
PLL VCO Out of Spec
Per DS12110 Rev 11 §6.3.10 (PLL characteristics), the PLL2 wide VCO range is 192-836 MHz (same range as PLL1). At 1600 MHz, the PLL output is unreliable regardless of divider ratio.
SDMMC Kernel Clock Note
The issue previously described 200 MHz as the SDMMC kernel clock "max spec." This was inaccurate. After review:
- 200 MHz is a design convention: the HAL's fixed clock dividers (
SDMMC_NSPEED_CLK_DIV=4, SDMMC_HSPEED_CLK_DIV=2) produce standard SD card frequencies (25/50 MHz SDMMC_CK) from that kernel clock rate
- The HAL reads the actual kernel clock at runtime (
HAL_RCCEx_GetPeriphCLKFreq()) and adapts dynamically — it does not require 200 MHz
- AN5200 states max SDMMC_CK at 208 MHz (SDR104 mode)
- At 400 MHz kernel clock (the buggy value), the fixed dividers intended for 200 MHz would produce double the intended SD card clock (50 MHz in normal speed), potentially exceeding the card's normal-speed limit
The primary fix is making PLL2M dynamic so VCO never exceeds 836 MHz.
Fix (Merged in PR #11596)
Make PLL2M dynamic using the same formula as PLL1M, and reduce PLL2N to keep VCO at 800 MHz:
RCC_PeriphClkInit.PLL2.PLL2M = HSE_VALUE / 1000000 / 2;
RCC_PeriphClkInit.PLL2.PLL2N = 400;
This pins VCO = 800 MHz for any HSE frequency:
- HSE=8: M=4, N=400 → VCO=800 MHz, PLL2R=4 → 200 MHz
- HSE=16: M=8, N=400 → VCO=800 MHz, PLL2R=4 → 200 MHz
Environment
Target: KAKUTEH7WING (HSE_MHZ 16)
MCU: STM32H743
File: src/main/target/system_stm32h7xx.c lines 500-512
PRs
Bug Description
On the KAKUTEH7WING target (and any other H7 target with
HSE_MHZ 16), the PLL2 VCO exceeds the STM32H7 PLL specification.Root Cause
PLL2 dividers are hardcoded in
src/main/target/system_stm32h7xx.c(lines 500-512):This assumes HSE = 8 MHz, giving VCO = 8/5 × 500 = 800 MHz within the PLL2 wide VCO range (192-836 MHz per DS12110 Rev 11 §6.3.10 (PLL characteristics). PLL2R = 4 gives 200 MHz SDMMC kernel clock.
On KAKUTEH7WING (HSE = 16 MHz), the math is:
PLL VCO Out of Spec
Per DS12110 Rev 11 §6.3.10 (PLL characteristics), the PLL2 wide VCO range is 192-836 MHz (same range as PLL1). At 1600 MHz, the PLL output is unreliable regardless of divider ratio.
SDMMC Kernel Clock Note
The issue previously described 200 MHz as the SDMMC kernel clock "max spec." This was inaccurate. After review:
SDMMC_NSPEED_CLK_DIV=4,SDMMC_HSPEED_CLK_DIV=2) produce standard SD card frequencies (25/50 MHz SDMMC_CK) from that kernel clock rateHAL_RCCEx_GetPeriphCLKFreq()) and adapts dynamically — it does not require 200 MHzThe primary fix is making PLL2M dynamic so VCO never exceeds 836 MHz.
Fix (Merged in PR #11596)
Make PLL2M dynamic using the same formula as PLL1M, and reduce PLL2N to keep VCO at 800 MHz:
This pins VCO = 800 MHz for any HSE frequency:
Environment
Target: KAKUTEH7WING (HSE_MHZ 16)
MCU: STM32H743
File:
src/main/target/system_stm32h7xx.clines 500-512PRs
maintenance-9.x): PLL2M dynamic fix only, no DroneCAN changes