Files
templates/c/spi-nor

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