Исследование / 13.09.2026

Реверс прошивки FM33LG025: результаты и требования к будущему прибору

Дата: 13 сентября 2026. Исследование сохранённого C:\dump\fw_128k.bin, не новое чтение подключённого аппарата. Исходные дампы не изменялись; к USB/J-Link и реальной памяти прибора в этой работе не обращались. Исходники будущего ядра также не менялись.

Короткий вывод

Из бинарника восстановлены рабочие алгоритмы измерений, несколько моделей калибровки, температурные поправки, пороговые тревоги, запись журнала, основные экраны и последовательность запуска. Выводы проверялись по машинным инструкциям; существенные участки дополнительно исполнялись в изолированном ARM-эмуляторе с искусственными входами.

Для будущей прошивки наиболее важны четыре результата:

Навигация

Надёжность исходного материала

ПроверкаРезультат
Основной BIN131072 байта, адрес загрузки 0, ARM Thumb little-endian
SHA-256fa0ff6bb9fdd148ac1449d6a12b491c04434ec47ca6283439f0b6e6875a62560
fw_128k_check.binПобайтно совпадает с основным
BIN внутри fw_128k.zipПобайтно совпадает с основным
test4k.binФрагмент основного по адресу 0xDC20, не начало прошивки
fm33_dataflash_00010000.binТочная верхняя половина основного BIN, не доказательство отдельного Data Flash
Старый листинг Untitled-1.txtПроверено 130329 представленных байтов, расхождений нет; это не доказательство правильной разметки кода/данных
Нулевые BINПустые результаты прежних попыток, данных для реверса не содержат; сохранены

Начальный указатель стека 0x200028B8, вход после сброса 0xDC с Thumb-битом в векторе. Найденная таблица startup по 0x16878 распаковывает 3856 байт из 0x1689C в 0x20000000, затем обнуляет 6568 байт начиная с 0x20000F10. Трансляция распаковщика и независимое исполнение его исходных инструкций дали одинаковый результат; см. проверку startup (локальный материал).

Это восстановило указатели на тексты меню и встроенную конфигурацию. Совпадение двух файлов не доказывает, что в них присутствуют все области памяти микросхемы или что именно эта версия работает сейчас на подключённом аппарате. Эталонной контрольной суммы производителя нет: непротиворечивость копий не исключает повреждения, уже присутствовавшего при их получении.

Карта основных функций

ОбластьАдреса FlashЧто восстановлено
ADC/DMA0x11C0, 0xC6F8, 0xF5CШесть каналов, аппаратное усреднение, обработка десяти сканов, порядок результатов
Цепочка измерений0xAEC4, вызов из 0x1056CПоочерёдная обработка четырёх газовых слотов до значения для тревог
Фильтры0xFE48, 0x1044CСкользящее среднее 8 и округлённое 0.8*новое + 0.2*предыдущее
Калибровка0x9A7C, 0xA9A4, 0xA490Возрастающая/убывающая кусочно-линейная и нелинейная ветви
Температура0x11478, 0xA6AC, 0xE758Отдельный аналоговый вход, температура калибровки, полиномиальные поправки
Тревоги0xC1F6–0xC6D0, 0x1534Две ступени/допустимый интервал, переходы событий, приоритеты оповещения
NVM0xECF0, 0xEF74Чтение/запись внешней памяти, страницы 64 байта
Калибровочные копии0x11150, 0x112E8Восстановление/сохранение заводских полей
Журнал0x1360, 0x2188Запись при смене ступени, просмотр 14-байтных записей
Интерфейс0x1056C, 0x4684, 0x4330Основной автомат, меню, сервисный ввод
Подписи газов0x77E8, 0x3B74Тип из настроек выбирает строку в восстановленной RAM

Измерения: что нельзя упустить

Последовательность старого тракта: аппаратное усреднение 8× → десять отсчётов с удалением одного минимума и максимума → масштабирование → скользящее среднее 8 → рекурсивное сглаживание → пересчёт по калибровке и температуре → смещение нуля/специальные преобразования → ограничение диапазона → тревоги. Конкретные ветви зависят от типа и режима канала: для H₂S/CO температурная ветвь является альтернативным двухточечным пересчётом с особым span, а не универсальной поправкой поверх четырёхузловой таблицы.

Четыре слоя фильтрации нельзя переносить без оценки задержки. При обычном начальном RCHF 8 МГц код настраивает CPU 24 МГц, SysTick 1 мс и шаг планировщика 10 мс. Основная задача готова каждые 100 мс; при четырёх включённых каналах номинально получается 400 мс на обновление одного канала. Это расчёт программной конфигурации, а не измерение платы. Уже скользящему среднему из восьми значений для полной замены старого окна нужно восемь обновлений. Для будущего прибора важен проверяемый срок обнаружения изменения, а не сходство количества фильтров.

Слот по умолчаниюПодпись из кодаADCH / L во внутренней шкале
0EXCH650 / 20
1O₂CH13235 / 195, один десятичный знак
2H₂SCH1520 / 10
3COCH14200 / 50

Температура — CH5, батарея — CH27 (VBAT/3). Это встроенные исходные настройки, которые загрузка внешней памяти может заменить; не измеренные текущие настройки аппарата и не рекомендуемые нормативные пороги нового изделия.

Калибровочная запись занимает 57 байт на слот, содержит опорные точки, смещение, температуру и дополнительные параметры. Восстановлен путь до четырёх узлов; пустая таблица местами заменяется встроенным поведением, а не явным отказом. Для нового ядра отсутствие/невалидность калибровки нужно представлять отдельным состоянием.

Особенно важно: старый код фиксирует кислородное показание 203 < x <= 216 в 209 при соответствующих настройках; есть зоны фиксации нуля и дополнительные условные поправки. Итог после этих преобразований используется и тревогами. Нельзя считать такие изменения только оформлением экрана.

Тревоги, память и журнал

Обычная схема: x < L — норма, L <= x < H — первая ступень, x >= H — высокая. В кислородной ветви x < L — низкая тревога, L <= x < H — норма, x >= H — высокая. Однако при нулевом первом u16-поле калибровочной записи эта специальная ветка пропускается, причём прошлое состояние не обязательно очищается. В проверенном фрагменте самостоятельного гистерезиса нет. Переход в другую тревожную ступень пишет событие, повтор той же ступени и возврат в норму — нет.

Внешняя память имеет 7-битный адрес 0x50, используются 32 КиБ и страницы по 64 байта. Это совместимо с организацией 24C256, но маркировку микросхемы ещё нужно подтвердить. Калибровки находятся с 0x0000, настройки каналов с 0x0201, журнал с 0x1203, его счётчик с 0x1201.

Проверено исполнением: после записи №2000 счётчик становится нулём; ошибка записи не предотвращает обновление счётчика; один байт записи не инициализируется. Для нашей реализации нужны иной формат, контроль целостности, обработка ошибок и тесты прерывания питания. «Журнал на 2000 записей» сам по себе не означает устойчивый кольцевой журнал.

Запуск и обслуживание

Есть многошаговый запуск, ожидание Starting/Please Wait, последовательное включение световых/вибрационных/звуковых выходов, основное меню, калибровочные и заводские операции. Наличие управляющего импульса не доказывает самодиагностику исправности исполнительного узла: в исследованном обработчике обратная связь не обнаружена.

Сервисные действия нужно разделить по последствиям: изменение порогов, новая калибровка, восстановление заводских данных, перезапись заводской копии. Старые постоянные пароли и скрытые режимы не являются моделью защиты для нового изделия.

Питание: важная зависимость от экрана

Найдены разные состояния предупреждения и критического питания. Для фильтрованной оценки батареи проверено: ниже 3555 при исходном состоянии возникает экран предупреждения 7; ниже 3455 после завершённого предупреждения выполняются команды завершения работы; выше 3650 состояние предупреждения сбрасывается. Равенство порогу не равно его пересечению. Масштаб согласуется с милливольтами, но физическое напряжение и отключение питания эмуляция не проверяет.

В режиме 7 главный обработчик пропускает вызов обработки газа 0xAEC4 до завершения предупреждения батареи. Это не означает остановку самого ADC, но показывает нежелательную зависимость критического расчётного пути от интерфейса. В новой архитектуре обработку газа следует отделить от отображения предупреждений.

Что уже проверено, а что остаётся неизвестным

Исполнялись отдельные исходные функции, а не весь прибор. Память, кнопки и входные значения задавались моделью; физические драйверы на границах подменялись. 235 сценариев прошли: 102 измерительных, 108 тревог/журнала, 20 интерфейса и 5 питания; отдельно проверены копии дампа и распаковка startup. Состав и результаты хранятся в evidence/test-summary.json. Из этого не следует, что дефектов нет: часть сценариев как раз подтверждает нежелательное поведение старого кода.

Открытые вопросы, которые нельзя подменять догадкой:

Рабочий следующий шаг в рамках реверса: все ветви калибровки и отказов, фактические задержки; затем read-only исследование внешней памяти после подтверждения её типа и подключения. Следующий шаг в разработке: отдельное решение о реализации требований из future-firmware-requirements.md, начиная с контракта измерения и настоящей калибровки.