Состояние переносимого ядра — 2026-09-13
Это реализация программных этапов из reverse-engineering/future-firmware-requirements.md,
а не утверждение готовности законченного измерительного прибора. Исходный аналоговый
проект O2/CO/H2S/CO2 сохранён; альтернативный цифровой вход — дополнительный контракт,
не выбор другого CO2-сенсора. Дамп чужого прибора и физическое устройство не менялись.
Реализовано и проверено
| Область | Реализация | Основная проверка |
| Измерения M01–M04 | ADC24 и отдельный ввод концентрации; время, качество, единицы, независимые окна; сброс после ошибки | Отсутствие/старение/обрыв, смена источника, выход за диапазон |
| Калибровка C01–C04 | 2–5 точек, оба направления, прямой/обратный расчёт; zero/span-сеанс; профиль/версия/температура/дата | Узлы, интервалы, нестабильность, отмена, сбой записи без изменения RAM |
| Температура T01 | Проверяемая табличная модель Ccal × R(Tcal) / R(T); контроль возраста | Диапазон, NaN/Inf, нулевой отклик, переполнение, восстановление |
| Межгазовая коррекция T02 | Неизменяемый снимок входов, суммирование поправок; верхние оценки пропускаются | Перестановка правил/каналов, невозможный результат, повторный tick |
| Тревоги A01–A04 | HIGH_ONLY / INTERVAL / TWO_HIGH, включительные пороги, гистерезис, задержки, фиксация, ack | Точные границы, задержка, дребезг, новый HIGH после mute, отказ |
| Время M05–M06 | AnalyzerCore: submit/tick без участия экрана; цифровые входы не имитируют ADC | Ступенька с окном 4 и задержкой 100 мс; старение всех каналов |
| Хранение S01–S02 | Указатели/size_t не сериализуются; формат LE/IEEE754, версии, CRC32, два слота, барьеры sync | Каждый байт обрыва обновления; каждый байт повреждения новой копии |
| Журнал L01–L02 | 16 записей по кольцу; sequence/head/count; raw24, качество, наличие значения | 100 событий, кольцо, переполнение sequence, сохранение/загрузка |
| Состояния U01–U03 | Отдельный supervisor; запрос самотеста не равен обратной связи; подтверждение restore | Калибровка/низкая батарея одновременно с тревогой; неподтверждённый выход |
14 групп CTest включают сценарии консоли и перезапуск с файлом настроек.
Проверки C принудительно включены также в Release. Дополнительно выполнены
AddressSanitizer/UndefinedBehaviorSanitizer и анализ GCC -fanalyzer.
Windows x64 собран MinGW; все 13 C-тестов и сценарии консоли/файлового хранения
также выполнены нативно в Windows. Готовая сборка размещена в build/gas_analyzer_core.exe.
Это набор инженерных проверок, не метрологические или сертификационные испытания.
Что именно хранится
Настройки: для каждого канала профиль ID, модель версии 1, календарная дата калибровки
в Unix seconds (0 = не задана), температура, точки и политика тревог. Байтовый формат
SET1 — 400 байт. Таблицы температурных профилей остаются в реестре приложения;
их указатели/строки не записываются. Смена профиля требует нового ID/версии.
Эмулятор использует один файл 4096 байт:
| Смещение | Область | Два слота |
| 0 | Рабочие настройки | 2 × 512 байт |
| 1024 | Защищённая опорная копия | 2 × 512 байт |
| 2048 | Журнал | 2 × 1024 байт |
Заголовок каждого слота: magic GAS1, версия 1, sequence, длина, CRC32; затем payload
и нулевое заполнение. Последние 4 байта CMIT пишутся после тела и sync. CRC покрывает
всё тело с обнулённым полем CRC, но не CMIT. Следующая запись идёт в неактивный слот.
При повреждении обеих копий нет молчаливой подстановки заводских значений.
Настройки и журнал не являются общей транзакцией. Ошибка sync или контрольного чтения
после commit может означать, что новая запись уже сохранена: после такого ответа
нужно перечитать хранилище. При первой оборванной записи, если ещё нет ни одной
валидной копии, автоматического восстановления нет. Файловый адаптер использует
flush + fsync/_commit; это не доказательство поведения конкретной EEPROM при пропадании питания.
Файл рассчитан на одного писателя. Журнал сохраняется снимком, а не оптимизирован
по ресурсу перезаписи EEPROM. У core нет автоматической фоновой записи: её планирует адаптер.
Контракт интеграции
- Приложение задаёт каналы, подтверждённые профили и политики тревог, затем вызывает
analyzer_core_init. - Температурный адаптер обновляет температуру, признак валидности и монотонное время в DeviceState.
- Драйвер передаёт
AdcMeasurementлибоConcentrationMeasurement. Цифровое значение —
уже калиброванная концентрация, перед необязательными дальнейшими коррекциями.
- Планировщик вызывает
analyzer_core_tick/device_supervisor_tickрегулярно независимо от UI,
включая отсутствие новых данных. Часы uint32; шаги меньше 2^31 мс, допускается переполнение.
- UI читает качество, final_value и тревоги. Не округлять/не «приклеивать» final_value ради экрана.
- Сервисные операции и блокирующее файловое хранение не вызываются внутри измерительного tick.
Для реальной платы нужны ограниченные по времени/асинхронные драйверы и измерение загрузки/стека.
Межгазовые правила в AnalyzerCore выключены по умолчанию. Приложение может явно
подключить проверенные правила; тогда неполный набор входов делает коррекцию невалидной,
а не выдаёт «норму без поправки». Эмулятор сохраняет отдельный демонстрационный режим:
при неполном наборе он сообщает о пропуске поправки. Это не политика готового прибора.
Ограничения и следующий аппаратный этап
- Коэффициенты имеющихся температурных таблиц демонстрационные. Модель корректирует
чувствительность, но не температурное смещение нуля. Для другого физического эффекта
нужен подтверждённый профиль/алгоритм, а не произвольно подобранный полином.
- Настройки гистерезиса, задержек, фиксации и допустимой нестабильности калибровки должны
быть утверждены для прибора. В эмуляторе задержки и гистерезис нулевые, фиксация выключена.
- Zero/span API протестирован на синтетических отсчётах.
cal— ручной редактор таблицы,
не автоматическая подача эталонного газа и не физическая процедура поверки.
- Эмулятор интерактивный и с виртуальным временем. Это не фоновый опрос USB-устройства.
- Самотест без обратной связи остаётся UNVERIFIED. Решение о допустимом ручном подтверждении
и обязательных выходах требует схемы и продуктовых требований.
- STM32/HAL/AD7124, реальная температура, GPIO, заряд/питание, часы, EEPROM/Flash,
аппаратный дисплей и кнопки не реализованы: в переданном описании точный MCU и плата ещё не выбраны.
- Для следующего этапа нужны точный MCU, схема аналоговых каналов и ADC (режим, масштаб,
опорное напряжение), точная модель CO2, температурный датчик, память и схема оповещения.
- Затем: ресурс стека/RAM/Flash и износ памяти на целевой платформе, HIL/обрыв питания,
реальные газовые смеси, температурная камера и фактическое время реакции.
Подключённый китайский аппарат не является целевой платой новой прошивки. Без этих
данных переносить в него получившееся ядро или выдавать модель за готовый газоанализатор нельзя.