Linux удалил 3.3 В из STM32: VREFINT калибровали при 1.8 В
Калибровочная ячейка хранит не обещание «внутри всегда ровно столько-то вольт». Она хранит результат конкретного измерения: ADC1 оцифровал внутренний источник при 30 °C и известном напряжении питания аналоговой части. Чтобы по этому числу восстановить сегодняшнее VREF+, драйвер обязан помнить условия того заводского измерения.
Заводской отсчёт привязан к питанию
В серии из восьми патчей для Linux IIO-разработчики ST добавили ADC для STM32MP23 и STM32MP25 и одновременно убрали глобальную константу `STM32_ADC_VREFINT_VOLTAGE 3300`. Вместо неё конфигурация каждого семейства получает своё `vref_charac`. Для MP23 и MP25 код задаёт 1800 мВ. Datasheet подтверждает это условие: `VREFINT_CAL` получен при `VDDA18ADC = VREF+ = 1.8 V`.
ADC оказался описанием физической топологии
Внутренний VREFINT близок к постоянному напряжению, однако ADC измеряет отношение этого напряжения к своей опоре. Если питание VREF+ просело, один и тот же bandgap займёт больше кодов шкалы; при росте VREF+ его raw-код уменьшится. Поэтому обработанное драйвером значение получается по формуле `VREF+ = vref_charac × VREFINT_CAL / raw_code`.
Подстановка 3.3 В вместо правильных 1.8 В раздула бы именно вычисленное VREF+ в 1.833 раза. Это не шум последнего младшего разряда и не тонкость округления: неверный коэффициент попадает во всю цепочку, которая использует оценку аналоговой опоры для перевода внешних ADC-отсчётов в вольты. Масштаб ошибки конкретного канала зависит от дальнейшей обработки, однако сама оценка VREF+ была бы заведомо ложной.
Код драйвера хранит условия измерения
Патчи заодно раскрывают устройство аналоговой части MP23 и MP25. ADC1 и ADC2 живут в общем блоке ADC12, ADC3 обслуживается отдельно; для каждого предусмотрены собственные таблицы триггеров, предделители тактирования, времена выборки и детали калибровки. Доступны до 20 мультиплексируемых каналов, дифференциальный и однополярный режимы, разрядность от 6 до 12 бит. В MP25 драйвер знает и внутренние точки контроля VDDCPU с VDDGPU.
Канал 19 физически подключён к VREF+. Драйвер намеренно скрывает его среди обычных IIO-входов: считывание собственного опорного питания как внешнего датчика не даёт калиброванного результата. Для этой задачи предусмотрена связка заводского `VREFINT_CAL` и текущего измерения VREFINT. В документации MP25 сам внутренний источник указан около 0.800 В, с диапазоном 0.792–0.808 В, поэтому индивидуальный заводской код здесь действительно несёт полезную информацию о конкретном кристалле.
История важна далеко за пределами Linux. Многие прошивки берут готовую формулу для VREFINT из соседнего семейства STM32, переносят её вместе с константой питания и получают правдоподобные, но масштабно неверные вольты. Калибровочное слово, напряжение VREF+ при его записи, температура, доступ к OTP, settling внутреннего канала и sampling time составляют одну измерительную систему.
Серия пока находится в обсуждении upstream, поэтому имена полей и детали интерфейса ещё могут поменяться. Физический факт уже подтверждён datasheet: у MP23 и MP25 заводская точка VREFINT — 1.8 В. Одно удалённое из драйвера число показало границу между чтением регистра ADC и настоящим измерением напряжения.