ADCv4: rev V ADC BOOST thresholds tested in ascending order, BOOST=10/11 unreachable
- Dominant language
- C
- Stars
- 85
- Forks
- 143
- Avg merge
- 4d 21h
- Merged PRs (30d)
- 1
Description
## Summary
In `os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h`, the ADC BOOST selection chains for rev V silicon test their thresholds in ascending order, so the first branch swallows every clock above 6.25 MHz and the `BOOST=10` and `BOOST=11` branches are unreachable dead code. Any ADC kernel clock above 12.5 MHz is therefore programmed with a BOOST level below what ST specifies.
Present at `9aebaf4a40` (current `master` here), and identical in upstream ChibiOS trunk — `ChibiOS/ChibiOS@master:os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h` lines 441-449 — so this presumably wants forwarding to the SourceForge tracker as well.
## The code
`hal_adc_lld.h:447-466`, inside the `#if !defined(STM32_ENFORCE_H7_REV_XY)` branch:
```c
/* ADC boost checks.*/
#if STM32_ADC12_CLOCK > 6250000
#define STM32_ADC12_BOOST (1U << 8U)
#elif STM32_ADC12_CLOCK > 12500000 /* unreachable */
#define STM32_ADC12_BOOST (2U << 8U)
#elif STM32_ADC12_CLOCK > 25000000 /* unreachable */
#define STM32_ADC12_BOOST (3U << 8U)
#else
#define STM32_ADC12_BOOST (0U << 8U)
#endif
```
The `STM32_ADC3_BOOST` chain at `:458-466` has the same defect.
`ADC_CR.BOOST[1:0]` is documented as a floor on the analog clock, not a ceiling:
| BOOST | max f_adc_ker_ck |
|---|---|
| `00` | 6.25 MHz |
| `01` | 12.5 MHz |
| `10` | 25 MHz |
| `11` | 50 MHz |
(See the `ADC_CR` register description in RM0433 for H742/H743/H750/H753 and RM0468 for H72x/H73x.)
So the ordering has to descend. A 32 MHz kernel clock needs `11`; the current chain gives it `01`, two levels low.
The value does reach the hardware — `hal_adc_lld.c:566,568,575` do `adcp->adcm->CR |= STM32_ADC12_BOOST` / `adcp->adcs->CR |= ...` / `adcp->adcm->CR |= STM32_ADC3_BOOST`.
The `STM32_ENFORCE_H7_REV_XY` branch just below (`:470-481`) is a single-bit test against 20 MHz and is correct for rev X/Y, where BOOST is one bit. Only the rev V path is affected.
## Suggested fix
Reverse both chains:
```c
#if STM32_ADC12_CLOCK > 25000000
#define STM32_ADC12_BOOST (3U << 8U)
#elif STM32_ADC12_CLOCK > 12500000
#define STM32_ADC12_BOOST (2U << 8U)
#elif STM32_ADC12_CLOCK > 6250000
#define STM32_ADC12_BOOST (1U << 8U)
#else
#define STM32_ADC12_BOOST (0U << 8U)
#endif
```
## Impact in ArduPilot
Everything that resolves `STM32_ENFORCE_H7_REV_XY` to undefined and clocks the ADC above 12.5 MHz, which is a large set. ArduPilot defines it only for `HAL_CUSTOM_MCU_CLOCKRATE <= 400000000` (`hwdef/common/stm32h7_mcuconf.h:22-24` and `stm32h7_type2_mcuconf.h:22-24`), so:
- the **29 boards** setting `MCU_CLOCKRATE_MHZ 480`. Their crystals are 8, 16 or 24 MHz, all of which reach `PLL3_DIVN 72` / `PLL3_DIVR 9` and a 32 MHz `PLL3_R`, which `STM32_ADCSEL_PLL3_R_CK` feeds straight to the ADC under `ADC_CCR_CKMODE_ADCCK`. Required `BOOST=11`, actual `01`.
- **SPRacingH7RF** (H730, `MCU_CLOCKRATE_MHZ 520`). It was at 48 MHz until the kernel v9 update dropped a `/2` from `STM32_ADC12_CLOCK`, at which point 96 MHz tripped the `STM32_ADCCLK_MAX` assert and the board stopped building — see ArduPilot/ardupilot#34252 and ArduPilot/ardupilot#34349, which brings it to 32 MHz. Either way it sits in the same band.
Boards at 400 MHz or below take the rev X/Y branch and are unaffected.
These boards evidently work well enough for battery voltage and current sensing, so the practical effect is presumably degraded sampling accuracy rather than an outright failure, but it is out of spec and the dead branches are clearly not what was intended.
## Reproducing
The dead branches are visible by inspection. To see the resulting value, build any 480 MHz H743 board and check that `STM32_ADC12_BOOST` expands to `(1U << 8U)` with `STM32_ADC12_CLOCK` at 32000000.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h at the rev V STM32_ADC12_BOOST and STM32_ADC3_BOOST chains, then inspect the uses in hal_adc_lld.c at lines 566, 568, and 575. Build a 480 MHz H743 configuration and verify that a 32 MHz STM32_ADC12_CLOCK selects the documented BOOST value; confirm the rev X/Y branch remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- embedded-iot
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100