Add embedded storage drivers and extend firmware metadata
This commit is contained in:
113
c/spi-nor/README.md
Normal file
113
c/spi-nor/README.md
Normal 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.
|
||||
Reference in New Issue
Block a user