Add embedded storage drivers and extend firmware metadata
This commit is contained in:
140
c/spi-nor/Inc/spi_nor.h
Normal file
140
c/spi-nor/Inc/spi_nor.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifndef PORTABLE_SPI_NOR_H
|
||||
#define PORTABLE_SPI_NOR_H
|
||||
|
||||
/*
|
||||
* Переносимое ядро SPI NOR.
|
||||
*
|
||||
* Ядро знает только стандартные SPI-команды и callbacks платформы. Оно не
|
||||
* включает HAL, регистры MCU, GPIO проекта, Modbus или код приложения. Каждый
|
||||
* экземпляр хранит собственное состояние и поэтому не использует глобальные
|
||||
* изменяемые переменные.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Поддерживаемые микросхемы ограничены устройствами с 24-битной адресацией. */
|
||||
typedef enum
|
||||
{
|
||||
SPI_NOR_MODEL_NONE = 0,
|
||||
SPI_NOR_MODEL_W25Q64,
|
||||
SPI_NOR_MODEL_W25Q128,
|
||||
SPI_NOR_MODEL_SST25VF016B
|
||||
} spi_nor_model_t;
|
||||
|
||||
/* Ошибки протокола не зависят от кодов конкретного HAL. */
|
||||
typedef enum
|
||||
{
|
||||
SPI_NOR_OK = 0,
|
||||
SPI_NOR_E_ARGUMENT = -1,
|
||||
SPI_NOR_E_IO = -2,
|
||||
SPI_NOR_E_TIMEOUT = -3,
|
||||
SPI_NOR_E_NOT_FOUND = -4,
|
||||
SPI_NOR_E_UNSUPPORTED = -5,
|
||||
SPI_NOR_E_BOUNDS = -6,
|
||||
SPI_NOR_E_ALIGNMENT = -7,
|
||||
SPI_NOR_E_VERIFY = -8,
|
||||
SPI_NOR_E_BUSY = -9
|
||||
} spi_nor_status_t;
|
||||
|
||||
/* Callback SPI возвращает только переносимый результат физического обмена. */
|
||||
typedef enum
|
||||
{
|
||||
SPI_NOR_IO_OK = 0,
|
||||
SPI_NOR_IO_ERROR = -1,
|
||||
SPI_NOR_IO_TIMEOUT = -2
|
||||
} spi_nor_io_status_t;
|
||||
|
||||
/* Геометрия и JEDEC доступны приложению только как копируемая диагностика. */
|
||||
typedef struct
|
||||
{
|
||||
spi_nor_model_t model;
|
||||
uint8_t manufacturer_id;
|
||||
uint8_t memory_type;
|
||||
uint8_t capacity_code;
|
||||
uint32_t capacity_bytes;
|
||||
uint32_t sector_size;
|
||||
uint16_t page_size;
|
||||
} spi_nor_info_t;
|
||||
|
||||
/*
|
||||
* Контракт платформы описывает одну SPI-шину и один сигнал CS.
|
||||
*
|
||||
* transfer выполняется при уже активном CS. NULL в tx означает передачу
|
||||
* dummy-байтов, NULL в rx — игнорирование принятого потока. lock/unlock
|
||||
* необязательны; RTOS-порт может ими сериализовать полную read/program/erase
|
||||
* операцию, а не отдельный SPI пакет.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
void *context;
|
||||
spi_nor_io_status_t (*transfer)(void *context, const uint8_t *tx,
|
||||
uint8_t *rx, size_t size,
|
||||
uint32_t timeout_ms);
|
||||
void (*chip_select)(void *context, uint8_t active);
|
||||
uint32_t (*tick_ms)(void *context);
|
||||
void (*delay_ms)(void *context, uint32_t delay_ms);
|
||||
spi_nor_io_status_t (*lock)(void *context, uint32_t timeout_ms);
|
||||
void (*unlock)(void *context);
|
||||
} spi_nor_io_t;
|
||||
|
||||
/* Тайм-ауты вынесены в конфигурацию для медленных шин и разных RTOS. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t io_timeout_ms;
|
||||
uint32_t lock_timeout_ms;
|
||||
uint32_t program_timeout_ms;
|
||||
uint32_t erase_timeout_ms;
|
||||
uint32_t ready_poll_delay_ms;
|
||||
} spi_nor_config_t;
|
||||
|
||||
/* Контекст полностью принадлежит вызывающему коду и не требует malloc. */
|
||||
typedef struct
|
||||
{
|
||||
spi_nor_io_t io;
|
||||
spi_nor_config_t config;
|
||||
spi_nor_info_t info;
|
||||
uint8_t initialized;
|
||||
uint8_t detected;
|
||||
uint8_t busy;
|
||||
} spi_nor_t;
|
||||
|
||||
/* Возвращает документированные безопасные тайм-ауты библиотеки. */
|
||||
spi_nor_config_t spi_nor_default_config(void);
|
||||
|
||||
/* Инициализация только копирует callbacks и не обращается к физической шине. */
|
||||
spi_nor_status_t spi_nor_init(spi_nor_t *device, const spi_nor_io_t *io,
|
||||
const spi_nor_config_t *config);
|
||||
|
||||
/* Probe будит память, читает JEDEC и разрешает работу известной геометрии. */
|
||||
spi_nor_status_t spi_nor_probe(spi_nor_t *device);
|
||||
|
||||
/* Операции используют физические смещения микросхемы, начиная с нуля. */
|
||||
spi_nor_status_t spi_nor_read(spi_nor_t *device, uint32_t address,
|
||||
void *data, size_t size);
|
||||
spi_nor_status_t spi_nor_program(spi_nor_t *device, uint32_t address,
|
||||
const void *data, size_t size);
|
||||
spi_nor_status_t spi_nor_erase(spi_nor_t *device, uint32_t address,
|
||||
size_t size);
|
||||
|
||||
/* Информация выдаётся только после успешного распознавания поддержанной модели. */
|
||||
spi_nor_status_t spi_nor_get_info(const spi_nor_t *device,
|
||||
spi_nor_info_t *info);
|
||||
|
||||
/* Последний JEDEC доступен и для различения пустой шины и неизвестной модели. */
|
||||
spi_nor_status_t spi_nor_get_last_jedec(const spi_nor_t *device,
|
||||
uint8_t jedec[3]);
|
||||
|
||||
/* Read-only диагностика возвращает status register 1 под общей блокировкой. */
|
||||
spi_nor_status_t spi_nor_read_status_register(spi_nor_t *device,
|
||||
uint8_t *status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTABLE_SPI_NOR_H */
|
||||
Reference in New Issue
Block a user