Stream Flash 流式写入

本页依据 文档基线与后续更新 中记录的 Zephyr main 快照更新。

Stream Flash 把连续到达的数据片段汇聚到应用缓冲区,再按底层 Flash 写块要求写入。 它适合固件传输等场景,公共接口位于 <zephyr/storage/stream_flash.h>。 组件不负责网络协议、镜像认证或应用级传输重试。

初始化与最后一次 flush

启用 CONFIG_STREAM_FLASH=y、底层 Flash 驱动,以及示例需要的 CONFIG_FLASH_MAP=y。 stream_flash_init() 接收设备、缓冲区、缓冲区大小、设备内偏移、可用范围和可选回调。 缓冲区长度应是设备写块大小的整数倍,且不能超过适用擦除页大小。

下面的函数向应用专用、已按要求准备好的 storage_partition 写入一段数据:

#include <zephyr/device.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/storage/stream_flash.h>
#include <errno.h>

static struct stream_flash_ctx stream;
static uint8_t write_buffer[256];

int store_stream(const uint8_t *data, size_t length)
{
    const struct flash_area *area;
    int rc = flash_area_open(PARTITION_ID(storage_partition), &area);

    if (rc != 0) {
        return rc;
    }
    if (!device_is_ready(area->fa_dev)) {
        flash_area_close(area);
        return -ENODEV;
    }
    rc = stream_flash_init(&stream, area->fa_dev, write_buffer,
                           sizeof(write_buffer), area->fa_off,
                           area->fa_size, NULL);
    if (rc == 0) {
        rc = stream_flash_buffered_write(&stream, data, length, true);
    }
    flash_area_close(area);
    return rc;
}

这是单次会话示例,不可由多个调用者并发复用同一个上下文。 实际分片传输先多次以 flush=false 写入,结束时调用一次 flush=true, 可用 NULL, 0, true 刷出最后剩余数据。flush 结束该会话,再次写入前必须重新初始化。

stream_flash_buffered_write() 返回状态码,不是本次写入字节数。 用 stream_flash_bytes_written() 查询已写载荷字节数, stream_flash_bytes_buffered() 查询仍在 RAM 中的字节数。 底层对齐填充可能占用额外存储空间,应在传输前确认分区容量。

擦除与回读

是否由组件处理擦除取决于 CONFIG_STREAM_FLASH_ERASE 等配置;未启用自动擦除时, 调用者按介质要求准备目标区域。旧 stream_flash_erase_page() 已弃用, 需要主动擦除时使用 Flash Map 或 Flash 驱动接口,并明确擦除范围。

开启 CONFIG_STREAM_FLASH_POST_WRITE_CALLBACK 后,可传入回读校验回调。 回调得到写后读回的内容,能够更新摘要等;写缓冲区也用于回读,不能在回调中假设 原始发送缓冲区或网络片段仍在其中。

持久化进度

CONFIG_STREAM_FLASH_PROGRESS 提供基于 Settings 的进度保存、加载和清除接口。 需要配置可用的 Settings 后端,并在相应存储初始化完成后使用。

进度表示已经提交的写入位置,不会自动保存尚在 RAM 的片段,也不能自动证明前缀内容 与新下载镜像一致。恢复时应核对镜像身份、分区、已写数据和协议偏移, 从确认的提交位置继续,完成后清除对应进度。

上游依据