/* 掉电不丢区的 ESP 实现:分区表里那块名叫 `evlog` 的 data 分区(见 partitions.csv)。 ⚠️ **不用 NVS,也不用 SPIFFS。** §10.7 要的是一条环形的、按序号增量拉取的 记录流,而 NVS 是键值表(4096 条记录 = 4096 个键,它的页式 GC 会把 「写一条事件」变成一次不可预测的搬移),SPIFFS 是文件系统(掉电一致性 自己就是一整章)。evlog 自己已经是环形缓冲,它要的只是「擦一扇区 / 写一段字节」。 分区找不到时返回 HAL_ERR_STATE 而不是 abort:这一条**不该**把板子挡在启动之外。 §10.7 的日志是排查手段,不是安全链的一环;丢了日志要告警,但五路照供电。 (对比 `rail_selftest()`:那张表错了会把命令发到另一路上去,所以那里是 abort。) */ #include #include "esp_partition.h" #include "hal_store.h" static const esp_partition_t *s_part; hal_err_t hal_store_init(void) { if (s_part != NULL) { return HAL_OK; } s_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "evlog"); return (s_part != NULL) ? HAL_OK : HAL_ERR_STATE; } void hal_store_geometry(hal_store_geom_t *g) { if (g == NULL) { return; } if (s_part == NULL) { g->sector_bytes = 0; g->sectors = 0; return; } /* ⚠️ 用分区自己报的 `erase_size`,不要写死 4096:esp_partition_erase_range() 的对齐要求就是拿这个字段说的,两处不一致时报的是 ESP_ERR_INVALID_ARG。 */ g->sector_bytes = s_part->erase_size; g->sectors = s_part->size / s_part->erase_size; } static bool range_ok(uint32_t off, uint32_t len) { return s_part != NULL && len <= s_part->size && off <= s_part->size - len; } hal_err_t hal_store_read(uint32_t off, void *buf, uint32_t len) { if (s_part == NULL) { return HAL_ERR_STATE; } if (buf == NULL || !range_ok(off, len)) { return HAL_ERR_ARG; } return (esp_partition_read(s_part, off, buf, len) == ESP_OK) ? HAL_OK : HAL_ERR_BUS; } hal_err_t hal_store_write(uint32_t off, const void *buf, uint32_t len) { if (s_part == NULL) { return HAL_ERR_STATE; } if (buf == NULL || !range_ok(off, len) || (off % 4u) != 0u || (len % 4u) != 0u) { return HAL_ERR_ARG; } return (esp_partition_write(s_part, off, buf, len) == ESP_OK) ? HAL_OK : HAL_ERR_BUS; } hal_err_t hal_store_erase(uint32_t sector) { if (s_part == NULL) { return HAL_ERR_STATE; } const uint32_t off = sector * s_part->erase_size; if (off >= s_part->size) { return HAL_ERR_ARG; } return (esp_partition_erase_range(s_part, off, s_part->erase_size) == ESP_OK) ? HAL_OK : HAL_ERR_BUS; }