Переносимая библиотека 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
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.