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
+11
View File
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.13)
project(flash_storage C)
add_library(flash_storage STATIC Src/flash_storage.c)
target_include_directories(flash_storage PUBLIC Inc)
set_target_properties(flash_storage PROPERTIES C_STANDARD 99 C_STANDARD_REQUIRED YES)
enable_testing()
add_executable(test_flash_storage Tests/test_flash_storage.c ../ds18b20/instance/Src/ds18b20.c)
target_link_libraries(test_flash_storage PRIVATE flash_storage)
target_include_directories(test_flash_storage PRIVATE ../ds18b20/instance/Inc)
add_test(NAME test_flash_storage COMMAND test_flash_storage)
+104
View File
@@ -0,0 +1,104 @@
#ifndef PORTABLE_FLASH_STORAGE_H
#define PORTABLE_FLASH_STORAGE_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FLASH_STORAGE_IMAGE_SIZE 512U
#define FLASH_STORAGE_RECORD_SIZE 544U
#define FLASH_STORAGE_V1_RECORD_SIZE 288U
typedef enum {
FLASH_STORAGE_OK = 0,
FLASH_STORAGE_E_ARGUMENT = -1,
FLASH_STORAGE_E_LAYOUT = -2,
FLASH_STORAGE_E_IO = -3,
FLASH_STORAGE_E_NOT_FOUND = -4,
FLASH_STORAGE_E_CORRUPT = -5,
FLASH_STORAGE_E_BUSY = -6,
FLASH_STORAGE_E_BOUNDS = -7
} flash_storage_status_t;
typedef struct {
flash_storage_status_t (*read)(void *context, uint32_t address,
void *data, size_t size);
flash_storage_status_t (*program)(void *context, uint32_t address,
const void *data, size_t size);
flash_storage_status_t (*erase)(void *context, uint32_t address,
size_t size);
uint32_t (*tick_ms)(void *context);
} flash_storage_ops_t;
typedef struct {
uint32_t bank_address[2];
uint32_t bank_size;
uint32_t program_alignment;
uint32_t erase_alignment;
uint32_t minimum_write_ms;
uint8_t reserve_percent;
} flash_storage_layout_t;
typedef struct {
const flash_storage_ops_t *ops;
void *platform_context;
flash_storage_layout_t layout;
uint32_t latest_address;
uint32_t latest_sequence;
uint32_t next_address;
uint32_t last_write_tick;
uint32_t valid_records;
uint32_t programmed_slots;
uint16_t latest_version;
uint8_t initialized;
uint8_t busy;
uint8_t wrote_this_boot;
/* Рабочая запись принадлежит экземпляру: Flash API не расходует малый
* embedded-стек на 544-байтные автоматические структуры. */
uint32_t workspace[FLASH_STORAGE_RECORD_SIZE / sizeof(uint32_t)];
} flash_storage_t;
typedef struct {
flash_storage_t journal;
uint8_t image[FLASH_STORAGE_IMAGE_SIZE];
uint8_t next_image[FLASH_STORAGE_IMAGE_SIZE];
uint8_t initialized;
} eeprom_store_t;
typedef struct {
uint32_t sequence;
uint32_t valid_records;
uint32_t programmed_slots;
uint32_t allocated_bytes;
uint32_t reserved_bytes;
} flash_storage_info_t;
flash_storage_status_t flash_storage_init(flash_storage_t *instance,
const flash_storage_ops_t *ops, void *platform_context,
const flash_storage_layout_t *layout);
flash_storage_status_t flash_storage_read_latest(flash_storage_t *instance,
void *data, size_t capacity, size_t *length, uint32_t *sequence);
flash_storage_status_t flash_storage_write(flash_storage_t *instance,
const void *data, size_t length);
flash_storage_status_t flash_storage_format(flash_storage_t *instance);
flash_storage_status_t flash_storage_get_info(flash_storage_t *instance,
flash_storage_info_t *info);
flash_storage_status_t eeprom_store_init(eeprom_store_t *instance,
const flash_storage_ops_t *ops, void *platform_context,
const flash_storage_layout_t *layout);
flash_storage_status_t eeprom_store_read(eeprom_store_t *instance,
size_t offset, void *data, size_t size);
flash_storage_status_t eeprom_store_write(eeprom_store_t *instance,
size_t offset, const void *data, size_t size);
flash_storage_status_t eeprom_store_format(eeprom_store_t *instance);
/* API не ISR-safe: erase/program могут надолго блокировать CPU. Один экземпляр
* обслуживается последовательно; разные экземпляры допустимы на независимых
* областях, а общий HAL Flash должен сериализовать платформенный адаптер. */
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,8 @@
#ifndef PORTABLE_FLASH_STORAGE_CONFIG_H
#define PORTABLE_FLASH_STORAGE_CONFIG_H
#define FLASH_STORAGE_MAGIC 0x474E4952UL
#define FLASH_STORAGE_COMMIT 0x54494D43UL
#define FLASH_STORAGE_VERSION 2U
#define FLASH_STORAGE_VERSION_V1 1U
#define FLASH_STORAGE_MIN_RESERVE_PERCENT 10U
#endif
+43
View File
@@ -0,0 +1,43 @@
# FlashStorage
Переносимый журнал двух банков Flash с подтверждёнными записями и восстановлением
после прерванной записи. Предоставляет также EEPROM-подобный образ 512 байт.
Не содержит HAL, файловой системы, адресов конкретной платы или malloc.
Приложение → `flash_storage` / `eeprom_store` → callbacks → Flash-порт платы.
| Файл | Назначение |
|---|---|
| `Inc/flash_storage.h` | Контекст, раскладка банков, read/program/erase/tick callbacks |
| `Inc/flash_storage_config.h` | Версия формата, magic, commit marker |
| `Src/flash_storage.c` | Восстановление, запись, ротация банков; только стандартный C |
| `Tests/test_flash_storage.c` | Прерывание записи, восстановление, несколько экземпляров |
Порт получает контекст, адрес и длину. `read`/`program`/`erase` возвращают
`flash_storage_status_t`; `tick_ms` возвращает uint32_t. Буферы принадлежат
экземпляру. Стирание и программирование могут блокировать процессор: API не
предназначен для ISR. Раскладку и резерв места задаёт `flash_storage_layout_t`.
```c
/* board_ops, board_context и layout определяет порт конкретной платы. */
flash_storage_t journal;
uint8_t payload[512] = {0}, restored[512];
size_t length = 0;
flash_storage_status_t result;
result = flash_storage_init(&journal, &board_ops, board_context, &layout);
if (result == FLASH_STORAGE_OK) {
result = flash_storage_write(&journal, payload, sizeof(payload));
}
if (result == FLASH_STORAGE_OK) {
result = flash_storage_read_latest(&journal, restored,
sizeof(restored), &length, 0);
}
```
Существующий потребитель — climate. Порты STM32F4 и SPI NOR остаются там.
Проверка: `python tools/test_shared_libraries.py` из корня templates.
## Shared source
Canonical source: `templates/c/flash-storage`. Used by `home/climate`; its old paths are compatibility includes. Board-specific ports remain in the application. Change this library, not the forwarding files.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long