Skip to content

drivers: KV flash storage - #1067

Draft
tact1m4n3 wants to merge 2 commits into
mainfrom
storage-driver
Draft

tact1m4n3 wants to merge 2 commits into
mainfrom
storage-driver

Conversation

@tact1m4n3

Copy link
Copy Markdown
Collaborator

Generic flash storage driver inspired by the rust crate sequential-storage. I needed a persistent storage lib for a project of mine and this is my attempt at writing one. I tried to make it as resilient as possible, like an interrupted store operation shouldn't mess anything up. There are still some TODOs left, but I'd love some feedback on it. I wrote a tiny rp2xxx demo example if anyone wants to try it out.

@tact1m4n3
tact1m4n3 marked this pull request as draft October 3, 2026 18:50
pub const Flash = struct {
// TODO: We must also wait for flash dma transfers to finish in addition to
// critical sections
// TODO: Maybe instead of asserts we should return errors?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, unless we're going down we shouldn't make a hal that makes it hard to make a resilient system


const BASE = hal.flash.XIP_BASE;
// We should get this from the memory map because it might be smaller.
const SIZE = 16 * 1024 * 1024;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

definitely

});
rp2xxx.uart.init_logger(uart);

const flash_storage_start: u32 = 256 * 1024;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we take this from the target? We don't want someone to build an example and accidentally wipe something important.

var current_offset: u32 = flash_storage_start;
while (current_offset < flash_storage_end) : (current_offset += flash.SECTOR_SIZE) {
std.log.info("Erasing sector at offset {x}", .{current_offset});
flash.range_erase(current_offset, flash.SECTOR_SIZE);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this function handle whatever looping it needs to do to wipe everything in the requested range?

Comment thread drivers/src/root.zig
//!
const std = @import("std");

pub const storage = @import("storage.zig");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might want to call this kv storage or persistent kv or something?

Comment thread drivers/src/storage.zig

/// A generic storage implementation that can be used with any flash device.
/// Items are stored sequentially in sectors (inspired by the rust crate
/// sequential storage). It should be resilient to power loss and flash

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you link the crate?

Comment thread drivers/src/storage.zig
src_offset += @truncate(data.len);
dst_offset += @truncate(data.len);
}) {
// if this fails it is something seriosly wrong

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

Comment thread drivers/src/storage.zig
Comment on lines +41 to +42
const WRITE_SIZE = Flash.WRITE_SIZE;
const ERASE_SIZE = Flash.ERASE_SIZE;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it makes sense to comptime enforce that these are powers of two? Or is that a safe assumption?

Comment thread drivers/src/storage.zig
try testing.expectEqual(@as(?u32, null), try s.fetch(3, u32));
}

test "overwrite frees the old item" {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

frees or reuses?

Comment thread drivers/src/storage.zig
if (i > 1000) return error.NeverRanOutOfMemory;
}
}
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine you plan on writing tests which utilize the tripwires?

@mattnite

mattnite commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

In addition to this PR, could you write a couple issues to implement this driver for architectures unlike the rp2xxx? I want to try to catch any leaky abstractions by having you think through some systems like AVR or MSP430, but I don't want to make you implement a patch for hardware you may not have.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants