ArduPilot / ArduPilot/ChibiOS

ADCv4: rev V ADC BOOST thresholds tested in ascending order, BOOST=10/11 unreachable

Open Beginner friendly
#111 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.