Add embedded storage drivers and extend firmware metadata

This commit is contained in:
2026-09-27 01:44:59 +03:00
parent 795a1279b1
commit 2ad29e7ffd
52 changed files with 5801 additions and 3 deletions

113
c/spi-nor/README.md Normal file
View File

@@ -0,0 +1,113 @@
# Переносимая библиотека SPI NOR
`SpiNor` — самостоятельный синхронный драйвер последовательной NOR Flash. Он
не зависит от STM32, HAL, `main.c`, GPIO проекта, Modbus, GUI и FlashStorage.
Память для контекста предоставляет приложение; `malloc` и глобальное изменяемое
состояние не используются.
## Поддержанные микросхемы
| Модель | JEDEC | Ёмкость | Program | Erase |
|---|---:|---:|---:|---:|
| W25Q64 | `EF 40 17` | 8 МиБ | страницы до 256 байт | 4 КиБ |
| W25Q128 | `EF 40 18` | 16 МиБ | страницы до 256 байт | 4 КиБ |
| SST25VF016B | `BF 25 41` | 2 МиБ | безопасный Byte Program | 4 КиБ |
Ядро использует команды с 24-битным адресом и намеренно не принимает
микросхемы больше 16 МиБ. Неизвестный JEDEC возвращает
`SPI_NOR_E_UNSUPPORTED`; пустая шина `00 00 00` или `FF FF FF` —
`SPI_NOR_E_NOT_FOUND`.
## Структура
- `Inc/spi_nor.h` — публичные типы, callbacks, конфигурация и API;
- `Src/spi_nor.c` — переносимый протокол, JEDEC, bounds, тайм-ауты и verify;
- `Port/STM32F4_HAL` — единственное место с зависимостью от STM32F4 HAL;
- `Examples/portable_init.c` — минимальная интеграция без имён текущей платы;
- `PORTING.md` — пошаговый перенос на другой STM32 или другой MCU;
- `Tests` — mock-шина и сценарии без HAL и реального оборудования.
- `Diagnostics` — два bounded read-only сервиса без HAL/Modbus/GUI;
`spi_nor_read_service` читает физический диапазон через callback, а
`spi_nor_command_service` выполняет одну разрешённую сервисную транзакцию.
Адаптер журнала находится отдельно в
`Libraries/FlashStorage/Adapter/SPI_NOR`: FlashStorage не проникает в ядро
SPI NOR, а SPI NOR не знает формат журнала.
Диагностический сервис принимает только capacity и callback чтения, ограничивает
один пакет 64 байт и не имеет `program`/`erase` API. Приложение может связать
его с Modbus, не добавляя GUI или прикладные зависимости в ядро `SpiNor`.
### Сервис коротких SPI-команд
`spi_nor_command_service` принимает `spi_nor_t`, request с `sequence`, TX до
4 байт и RX до 64 байт, а response возвращает status, echo TX и RX. Владельцем
контекста остаётся приложение; сервис не выделяет память и не хранит историю.
Allowlist одинаков для всех трёх поддержанных моделей:
| Opcode | Строгая форма | Причина допуска |
|---:|---|---|
| `9F` | TX 1, RX 3 | JEDEC ID |
| `05` | TX 1, RX 1 | status register 1 |
| `03` | TX 4 (`03 A2 A1 A0`), RX 1–64 | обычное 24-битное чтение с bounds |
Любой другой opcode возвращает `BLOCKED`. В частности, запрещены WREN/WRDI,
program, все erase, status/protection writes, power-down/release, reset и
неизвестные команды. Это fail-closed read-only API, а не универсальный SPI
terminal. Изменяющий сервисный режим не требуется и в библиотеку не включён.
Одна операция имеет порядок `CS active -> TX -> dummy RX -> CS inactive`.
После ошибки или тайм-аута TX/RX сервис безусловно освобождает CS и очищает
частичный RX. Он использует тот же `busy` и необязательные `lock/unlock`, что
основной экземпляр `spi_nor_t`.
## Публичный API
```c
spi_nor_io_t io;
spi_nor_t flash;
/* Порт приложения заполняет callbacks и собственный io.context. */
FillPlatformCallbacks(&io);
if (spi_nor_init(&flash, &io, NULL) == SPI_NOR_OK &&
spi_nor_probe(&flash) == SPI_NOR_OK) {
uint8_t bytes[16];
(void)spi_nor_read(&flash, 0U, bytes, sizeof(bytes));
}
```
`spi_nor_program()` автоматически делит поток по страницам и проверяет каждый
chunk обратным чтением. `spi_nor_erase()` принимает только полные выровненные
4-КиБ секторы и проверяет каждый стёртый байт на `0xFF`.
## Электрическое подключение
Нужны `SCK`, `MOSI`, `MISO`, отдельный active-low `CS`, питание и земля.
Питание и допустимую частоту следует брать из datasheet конкретной модели.
Для текущей платы используются SPI2: `PB10/SCK`, `PC3/MOSI`, `PC2/MISO` и
`PE3/CS`, но эти имена находятся только в `app_storage.c`.
## Ограничения выполнения
- API синхронный и не предназначен для ISR;
- erase может блокировать вызывающий поток до заданного тайм-аута;
- один `spi_nor_t` не допускает рекурсивных операций;
- при RTOS callbacks `lock/unlock` должны защищать всю составную операцию;
- общий SPI bus требует согласованного mutex и корректного управления CS всех
подключённых устройств;
- DMA callback нельзя считать завершённым до фактического окончания обмена;
- библиотека не меняет SPI mode и clock: это обязанность платформенного порта.
## Гарантии ошибок
При любой ошибке обмена CS возвращается в неактивное состояние. Ошибка program
или erase не маскируется: результат считается успешным только после ожидания
BUSY и полного readback verify. Повторять изменяющую операцию автоматически
библиотека не будет, потому что политика повторов принадлежит приложению.
## Shared source
Canonical source: `templates/c/spi-nor`. Used by `home/climate`; its old paths are compatibility includes. Board-specific ports remain in the application. Change this library, not the forwarding files.