Skip to content

Commit 942de4e

Browse files
committed
add flash driver interface
1 parent 8f12e65 commit 942de4e

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed

drivers/base/flash.zig

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
const std = @import("std");
2+
3+
const logger = std.log.scoped(.flash);
4+
5+
const BaseError = error{ Unsupported, InvalidSector };
6+
const WriteError = BaseError || error{ SectorOverrun, WriteDisabled };
7+
const ReadError = BaseError || error{ReadDisabled};
8+
9+
pub const VTable = struct {
10+
init_fn: ?*const fn (*anyopaque) BaseError!void,
11+
deinit_fn: ?*const fn (*anyopaque) BaseError!void,
12+
enable_write_fn: ?*const fn (*anyopaque) BaseError!void,
13+
disable_write_fn: ?*const fn (*anyopaque) BaseError!void,
14+
erase_fn: ?*const fn (*anyopaque, sector: u8) WriteError!void,
15+
write_fn: ?*const fn (*anyopaque, sector: u8, data: []u8) WriteError!void,
16+
read_fn: ?*const fn (*anyopaque, offset: u32, data: []u8) ReadError!usize,
17+
// find_sector_fn: ?*const fn (*anyopaque, offset: u32) BaseError!u32,
18+
sector_size_fn: ?*const fn (*anyopaque, sector: u8) BaseError!u32,
19+
};
20+
21+
const Flash_Device = @This();
22+
ptr: *anyopaque,
23+
vtable: VTable,
24+
pub fn init(flash: Flash_Device) BaseError!void {
25+
if (flash.vtable.init_fn) |initFn| {
26+
return initFn(flash.ptr);
27+
}
28+
}
29+
pub fn deinit(flash: Flash_Device) BaseError!void {
30+
if (flash.vtable.deinit_fn) |deinitFn| {
31+
return deinitFn(flash.ptr);
32+
}
33+
}
34+
pub fn enableWrite(flash: Flash_Device) BaseError!void {
35+
if (flash.vtable.enable_write_fn) |enable_write_fn| {
36+
return try enable_write_fn(flash.ptr);
37+
}
38+
}
39+
pub fn disableWrite(flash: Flash_Device) BaseError!void {
40+
if (flash.vtable.disable_write_fn) |disable_write_fn| {
41+
return try disable_write_fn(flash.ptr);
42+
}
43+
}
44+
pub fn eraseSector(flash: Flash_Device, sector: u8) WriteError!void {
45+
const erase_fn = flash.vtable.erase_fn orelse return error.Unsupported;
46+
return erase_fn(flash.ptr, sector);
47+
}
48+
pub fn write(flash: Flash_Device, sector: u8, data: []u8) WriteError!void {
49+
const sector_size = try flash.sectorSize(sector);
50+
if (data.len > sector_size) return error.SectorOverrun;
51+
try flash.eraseSector(sector);
52+
const write_fn = flash.vtable.write_fn orelse return error.Unsupported;
53+
return write_fn(flash.ptr, sector, data);
54+
}
55+
pub fn read(flash: Flash_Device, offset: u32, data: []u8) ReadError!usize {
56+
const read_fn = flash.vtable.read_fn orelse return error.Unsupported;
57+
return read_fn(flash.ptr, offset, data);
58+
}
59+
// pub fn findSector(flash: Flash_Device, offset: u32) BaseError!u8 {
60+
61+
// }
62+
pub fn sectorSize(flash: Flash_Device, sector: u8) BaseError!u32 {
63+
const sector_size_fn = flash.vtable.sector_size_fn orelse return error.Unsupported;
64+
return sector_size_fn(flash.ptr, sector);
65+
}
66+
67+
pub const TestDevice = struct {
68+
arena: std.heap.ArenaAllocator,
69+
write_enabled: bool = false,
70+
read_enabled: bool = false,
71+
sector_size: u32 = 16384,
72+
num_sectors: u8 = 4,
73+
74+
pub fn flash_device(td: *TestDevice) Flash_Device {
75+
return Flash_Device{ .vtable = vtable, .ptr = td };
76+
}
77+
78+
pub fn init(ctx: *anyopaque) BaseError!void {
79+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
80+
_ = td;
81+
}
82+
pub fn deinit(ctx: *anyopaque) BaseError!void {
83+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
84+
td.arena.deinit();
85+
}
86+
pub fn enableWrite(ctx: *anyopaque) BaseError!void {
87+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
88+
std.debug.print("Enable flash Write\n", .{});
89+
td.read_enabled = true;
90+
td.write_enabled = true;
91+
}
92+
pub fn disableWrite(ctx: *anyopaque) BaseError!void {
93+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
94+
std.debug.print("Disable flash Write\n", .{});
95+
td.read_enabled = false;
96+
td.write_enabled = false;
97+
}
98+
pub fn erase(ctx: *anyopaque, sector: u8) WriteError!void {
99+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
100+
if (td.write_enabled) {
101+
std.debug.print("Erasing sector: {}\n", .{sector});
102+
} else {
103+
return error.WriteDisabled;
104+
}
105+
}
106+
107+
pub fn write(ctx: *anyopaque, sector: u8, data: []u8) WriteError!void {
108+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
109+
if (td.write_enabled) {
110+
std.debug.print("Writing offset: {}, data length: {}\n", .{ sector, data.len });
111+
} else {
112+
return error.WriteDisabled;
113+
}
114+
}
115+
pub fn read(ctx: *anyopaque, offset: u32, data: []u8) ReadError!usize {
116+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
117+
if (td.write_enabled) {
118+
std.debug.print("Reading offset: {}\n", .{offset});
119+
const length = data.len;
120+
for (0..length) |i| {
121+
data[i] = @intCast(i % 256);
122+
}
123+
return length;
124+
} else {
125+
return error.ReadDisabled;
126+
}
127+
}
128+
pub fn sectorSize(ctx: *anyopaque, sector: u8) BaseError!u32 {
129+
const td: *TestDevice = @ptrCast(@alignCast(ctx));
130+
if (sector < td.num_sectors) {
131+
return td.sector_size;
132+
} else {
133+
return error.InvalidSector;
134+
}
135+
}
136+
const vtable = VTable{
137+
.init_fn = TestDevice.init,
138+
.deinit_fn = TestDevice.deinit,
139+
.enable_write_fn = TestDevice.enableWrite,
140+
.disable_write_fn = TestDevice.disableWrite,
141+
.erase_fn = TestDevice.erase,
142+
.write_fn = TestDevice.write,
143+
.read_fn = TestDevice.read,
144+
.sector_size_fn = TestDevice.sectorSize,
145+
};
146+
};
147+
148+
test TestDevice {
149+
var td: TestDevice = .{
150+
.arena = std.heap.ArenaAllocator.init(std.testing.allocator),
151+
};
152+
153+
td.sector_size = 10;
154+
155+
const fd = td.flash_device();
156+
try fd.init();
157+
var buffer: [3]u8 = .{ 42, 43, 44 };
158+
try std.testing.expectError(error.WriteDisabled, fd.write(0, buffer[0..]));
159+
try std.testing.expectError(error.ReadDisabled, fd.read(0, buffer[0..]));
160+
161+
try fd.enableWrite();
162+
163+
try fd.write(0, buffer[0..]);
164+
try std.testing.expectEqual(buffer.len, fd.read(0x123, buffer[0..]));
165+
var big_buf: [11]u8 = undefined;
166+
@memset(big_buf[0..], 123);
167+
try std.testing.expectError(error.SectorOverrun, fd.write(0, big_buf[0..]));
168+
}

0 commit comments

Comments
 (0)