From f074658ee285a613d1af9da2eba8fdb4b876a891 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 23 May 2026 10:32:42 -0700 Subject: [PATCH 01/61] Migrate uf2 to 0.16.0 --- tools/uf2/src/elf2uf2.zig | 26 ++++++++++++-------------- tools/uf2/src/example.zig | 33 +++++++++++++++------------------ tools/uf2/src/uf2.zig | 2 +- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/tools/uf2/src/elf2uf2.zig b/tools/uf2/src/elf2uf2.zig index c4fb66e38..4aa559432 100644 --- a/tools/uf2/src/elf2uf2.zig +++ b/tools/uf2/src/elf2uf2.zig @@ -37,15 +37,13 @@ fn find_arg(args: []const []const u8, key: []const u8) !?[]const u8 { var elf_reader_buf: [1024]u8 = undefined; var output_writer_buf: [1024]u8 = undefined; -pub fn main() !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - - const args = try std.process.argsAlloc(gpa.allocator()); - defer std.process.argsFree(gpa.allocator(), args); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); for (args) |arg| if (std.mem.eql(u8, "--help", arg)) { - var writer = std.fs.File.stdout().writer(&.{}); + var writer = std.Io.File.stdout().writer(io, &.{}); try writer.interface.writeAll(usage); return; }; @@ -74,21 +72,21 @@ pub fn main() !void { else null; - var archive = uf2.Archive.init(gpa.allocator()); + var archive = uf2.Archive.init(gpa); defer archive.deinit(); - const elf_file = try std.fs.cwd().openFile(elf_path, .{}); - defer elf_file.close(); - var elf_reader = elf_file.reader(&elf_reader_buf); + const elf_file = try std.Io.Dir.cwd().openFile(io, elf_path, .{}); + defer elf_file.close(io); + var elf_reader = elf_file.reader(io, &elf_reader_buf); try archive.add_elf(&elf_reader, .{ .family_id = family_id, }); - const dest_file = try std.fs.cwd().createFile(output_path, .{}); - defer dest_file.close(); + const dest_file = try std.Io.Dir.cwd().createFile(io, output_path, .{}); + defer dest_file.close(io); - var writer = dest_file.writer(&output_writer_buf); + var writer = dest_file.writer(io, &output_writer_buf); try archive.write_to(&writer.interface); try writer.interface.flush(); } diff --git a/tools/uf2/src/example.zig b/tools/uf2/src/example.zig index 87534803d..fe8319a8a 100644 --- a/tools/uf2/src/example.zig +++ b/tools/uf2/src/example.zig @@ -1,42 +1,39 @@ const std = @import("std"); const uf2 = @import("uf2"); -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - const allocator = debug_allocator.allocator(); - - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len == 3) { - var archive = uf2.Archive.init(allocator); + var archive = uf2.Archive.init(gpa); defer archive.deinit(); - const file = try std.fs.cwd().openFile(args[1], .{}); - defer file.close(); + const file = try std.Io.Dir.cwd().openFile(io, args[1], .{}); + defer file.close(io); var buf: [4096]u8 = undefined; - var reader = file.reader(&buf); + var reader = file.reader(io, &buf); try archive.add_elf(&reader, .{ .family_id = .RP2040, }); - const out_file = try std.fs.cwd().createFile(args[2], .{}); - defer out_file.close(); + const out_file = try std.Io.Dir.cwd().createFile(io, args[2], .{}); + defer out_file.close(io); var write_buf: [4096]u8 = undefined; - var writer = out_file.writer(&write_buf); + var writer = out_file.writer(io, &write_buf); try archive.write_to(&writer.interface); } else if (args.len == 2) { - const file = try std.fs.cwd().openFile(args[1], .{}); - defer file.close(); + const file = try std.Io.Dir.cwd().openFile(io, args[1], .{}); + defer file.close(io); // Buffer must be at least 512 bytes (the size of `uf2.Block`) var buf: [4096]u8 = undefined; - var reader = file.reader(&buf); + var reader = file.reader(io, &buf); - var archive: uf2.Archive = .init(allocator); + var archive: uf2.Archive = .init(gpa); defer archive.deinit(); try archive.read_from(&reader.interface, .{}); diff --git a/tools/uf2/src/uf2.zig b/tools/uf2/src/uf2.zig index a7f069636..214403139 100644 --- a/tools/uf2/src/uf2.zig +++ b/tools/uf2/src/uf2.zig @@ -77,7 +77,7 @@ pub const Archive = struct { /// Adds an elf to the archive. Returns error if the family id (if /// specified) is already present in the archive. - pub fn add_elf(self: *Archive, reader: *std.fs.File.Reader, opts: ELF_Options) !void { + pub fn add_elf(self: *Archive, reader: *std.Io.File.Reader, opts: ELF_Options) !void { if (opts.family_id) |family_id| if (try self.families.fetchPut(self.allocator, family_id, {}) != null) return error.FamilyIdCollision; From b395dbba1baa352a6c3a9541a5be44181138b068 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 24 May 2026 13:10:45 -0700 Subject: [PATCH 02/61] regz updated for 0.16.0 --- tools/regz/build.zig | 49 +- tools/regz/build.zig.zon | 8 +- tools/regz/src/Database.zig | 49 +- tools/regz/src/FS_Directory.zig | 35 - tools/regz/src/VirtualFilesystem.zig | 246 ++++-- tools/regz/src/atdf.zig | 4 +- tools/regz/src/embassy.zig | 112 +-- tools/regz/src/gen.zig | 1067 ++++++++++++++++++++++---- tools/regz/src/main.zig | 65 +- tools/regz/src/module.zig | 10 +- tools/regz/src/output_tests.zig | 960 ----------------------- tools/regz/src/svd.zig | 4 +- tools/regz/src/targetdb.zig | 47 +- 13 files changed, 1329 insertions(+), 1327 deletions(-) delete mode 100644 tools/regz/src/FS_Directory.zig delete mode 100644 tools/regz/src/output_tests.zig diff --git a/tools/regz/build.zig b/tools/regz/build.zig index 1570f018b..ce6146130 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -30,25 +30,50 @@ pub fn build(b: *Build) !void { const zqlite = zqlite_dep.module("zqlite"); zqlite.linkLibrary(sqlite3_lib); + const xml_module = b.createModule(.{ + .root_source_file = b.path("src/xml.zig"), + .target = target, + .optimize = optimize, + }); + + const regz_module = b.addModule("regz", .{ + .root_source_file = b.path("src/module.zig"), + .target = target, + .optimize = optimize, + .imports = &.{ + .{ + .name = "zqlite", + .module = zqlite, + }, + .{ + .name = "xml", + .module = xml_module, + }, + }, + }); + regz_module.linkLibrary(libxml2_dep.artifact("xml")); + const regz = b.addExecutable(.{ .name = "regz", .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, + .imports = &.{ + .{ + .name = "regz", + .module = regz_module, + }, + .{ + .name = "xml", + .module = xml_module, + }, + }, }), .use_llvm = true, }); - regz.linkLibrary(libxml2_dep.artifact("xml2")); - regz.root_module.addImport("zqlite", zqlite); b.installArtifact(regz); - const exported_module = b.addModule("regz", .{ - .root_source_file = b.path("src/module.zig"), - }); - exported_module.linkLibrary(libxml2_dep.artifact("xml2")); - exported_module.addImport("zqlite", zqlite); - const run_cmd = b.addRunArtifact(regz); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| { @@ -59,15 +84,9 @@ pub fn build(b: *Build) !void { run_step.dependOn(&run_cmd.step); const tests = b.addTest(.{ - .root_module = b.createModule(.{ - .root_source_file = b.path("src/Database.zig"), - .target = target, - .optimize = optimize, - }), + .root_module = regz_module, .use_llvm = true, }); - tests.linkLibrary(libxml2_dep.artifact("xml2")); - tests.root_module.addImport("zqlite", zqlite); tests.step.dependOn(®z.step); const run_tests = b.addRunArtifact(tests); diff --git a/tools/regz/build.zig.zon b/tools/regz/build.zig.zon index 154dc6eaa..b4ba99920 100644 --- a/tools/regz/build.zig.zon +++ b/tools/regz/build.zig.zon @@ -10,12 +10,12 @@ }, .dependencies = .{ .libxml2 = .{ - .url = "git+https://github.com/mattnite/zig-build-libxml2.git#5474281ad4d173ed298ee789c7dce4f5edb78e10", - .hash = "libxml2-0.0.0-Kr0Y1Ac4ngAiRuFTS2qMO9j-KZsD0PKFKKXoZjynTHLq", + .url = "git+https://github.com/allyourcodebase/libxml2.git?ref=2.15.1-2#2528fad1bf17a0a70999930cfd9280554f547787", + .hash = "libxml2-2.15.1-2-qHdjhmNMAAAiZOWqVridicq2oMf5NHv0n9W41bz9FtMM", }, .sqlite3 = .{ - .url = "git+https://github.com/allyourcodebase/sqlite3#8f840560eae88ab66668c6827c64ffbd0d74ef37", - .hash = "sqlite3-3.51.0-DMxLWssOAABZ8cAvU_LfBIbp0kZjm824PU8sSLXpEDdr", + .url = "git+https://github.com/allyourcodebase/sqlite3#b7514a2b76003bee57db1fc78e84a2abc7499efa", + .hash = "sqlite3-3.51.0-DMxLWuAOAABO27GnPH0iTeI57EkQPpGwqI7LTfiE4Pda", }, .zqlite = .{ .url = "git+https://github.com/karlseguin/zqlite.zig#b44ed5cdc64859b08446c246f307e65ebe2b2d9c", diff --git a/tools/regz/src/Database.zig b/tools/regz/src/Database.zig index 00f606371..19f637fa8 100644 --- a/tools/regz/src/Database.zig +++ b/tools/regz/src/Database.zig @@ -9,7 +9,7 @@ const assert = std.debug.assert; const zqlite = @import("zqlite"); const c = zqlite.c; -const xml = @import("xml.zig"); +const xml = @import("xml"); const svd = @import("svd.zig"); const atdf = @import("atdf.zig"); const embassy = @import("embassy.zig"); @@ -19,7 +19,6 @@ const analysis = @import("analysis.zig"); const Patch = @import("patch.zig").Patch; const SQL_Options = @import("SQL_Options.zig"); const Arch = @import("arch.zig").Arch; -pub const Directory = @import("Directory.zig"); const log = std.log.scoped(.db); const file_size_max = 100 * 1024 * 1024; @@ -615,43 +614,43 @@ pub fn create_from_doc(allocator: Allocator, format: Format, doc: xml.Doc) !*Dat return db; } -pub fn create_from_path(allocator: Allocator, format: Format, path: []const u8, device: ?[]const u8) !*Database { +pub fn create_from_path(gpa: Allocator, io: std.Io, format: Format, path: []const u8, device: ?[]const u8) !*Database { return switch (format) { .embassy => blk: { - var db = try Database.create(allocator); + var db = try Database.create(gpa); errdefer { std.log.err("sqlite: {s}", .{db.conn.lastError()}); db.destroy(); } - try embassy.load_into_db(db, path, device); + try embassy.load_into_db(db, io, path, device); break :blk db; }, .targetdb => blk: { - var db = try Database.create(allocator); + var db = try Database.create(gpa); errdefer { std.log.err("sqlite: {s}", .{db.conn.lastError()}); db.destroy(); } - try targetdb.load_into_db(db, path, device); + try targetdb.load_into_db(db, io, path, device); break :blk db; }, .svd, .atdf => blk: { - const text = try std.fs.cwd().readFileAlloc(allocator, path, file_size_max); - defer allocator.free(text); + const text = try std.Io.Dir.cwd().readFileAlloc(io, path, gpa, @enumFromInt(file_size_max)); + defer gpa.free(text); - break :blk create_from_xml(allocator, format, text); + break :blk create_from_xml(gpa, format, text); }, }; } -pub fn create_from_xml(allocator: Allocator, format: Format, xml_text: []const u8) !*Database { +pub fn create_from_xml(gpa: Allocator, format: Format, xml_text: []const u8) !*Database { assert(format.is_XML()); var doc = try xml.Doc.from_memory(xml_text); defer doc.deinit(); - return create_from_doc(allocator, format, doc); + return create_from_doc(gpa, format, doc); } pub const CreateDeviceOptions = struct { @@ -811,7 +810,7 @@ fn all(db: *Database, comptime T: type, comptime query: []const u8, allocator: A var rows = try db.conn.rows(query, args); defer rows.deinit(); - var list: std.ArrayList(T) = .{}; + var list: std.ArrayList(T) = .empty; while (rows.next()) |row| { try list.append(allocator, try scan_row(T, allocator, row)); } @@ -919,18 +918,18 @@ fn get_nested_struct_fields( fn recursively_calculate_struct_size( db: *Database, depth: *u8, - cache: *std.AutoArrayHashMap(StructID, u64), - allocator: Allocator, + cache: *std.AutoArrayHashMapUnmanaged(StructID, u64), + gpa: Allocator, struct_id: StructID, ) !u64 { if (depth.* >= max_recursion_depth) return error.MaxRecursionDepth; - const registers = try db.get_struct_registers(allocator, struct_id); - defer allocator.free(registers); + const registers = try db.get_struct_registers(gpa, struct_id); + defer gpa.free(registers); - const nested_struct_fields = try db.get_nested_struct_fields(allocator, struct_id); - defer allocator.free(nested_struct_fields); + const nested_struct_fields = try db.get_nested_struct_fields(gpa, struct_id); + defer gpa.free(nested_struct_fields); var max_end: ?u32 = null; for (registers) |register| { @@ -946,7 +945,7 @@ fn recursively_calculate_struct_size( for (nested_struct_fields) |nsf| { const nested_struct_field_end = nsf.offset_bytes + ((nsf.size_bytes orelse cache.get(nsf.struct_id) orelse - try db.recursively_calculate_struct_size(depth, cache, allocator, nsf.struct_id)) * (nsf.count orelse 1)); + try db.recursively_calculate_struct_size(depth, cache, gpa, nsf.struct_id)) * (nsf.count orelse 1)); if (max_end) |end| { if (nested_struct_field_end > end) max_end = @intCast(nested_struct_field_end); @@ -974,8 +973,8 @@ pub fn get_nested_struct_fields_with_calculated_size( log.debug("nested_struct_fields.len={} struct_id={f}", .{ nested_struct_fields.len, struct_id }); - var size_cache: std.AutoArrayHashMap(StructID, u64) = .init(gpa); - defer size_cache.deinit(); + var size_cache: std.AutoArrayHashMapUnmanaged(StructID, u64) = .empty; + defer size_cache.deinit(gpa); for (nested_struct_fields) |*nsf| { if (nsf.size_bytes != null) { @@ -2060,7 +2059,7 @@ fn cleanup_unused_enums(db: *Database) !void { } pub fn apply_patch(db: *Database, zon_text: [:0]const u8, diags: *std.zon.parse.Diagnostics) !void { - const patches = try std.zon.parse.fromSlice([]const Patch, db.gpa, zon_text, diags, .{}); + const patches = try std.zon.parse.fromSliceAlloc([]const Patch, db.gpa, zon_text, diags, .{}); defer std.zon.parse.free(db.gpa, patches); for (patches) |patch| { @@ -2166,8 +2165,8 @@ pub fn apply_patch(db: *Database, zon_text: [:0]const u8, diags: *std.zon.parse. pub const ToZigOptions = gen.ToZigOptions; -pub fn to_zig(db: *Database, output_dir: Directory, opts: ToZigOptions) !void { - try gen.to_zig(db, output_dir, opts); +pub fn to_zig(db: *Database, io: std.Io, output_dir: std.Io.Dir, opts: ToZigOptions) !void { + try gen.to_zig(db, io, output_dir, opts); } test "all" { diff --git a/tools/regz/src/FS_Directory.zig b/tools/regz/src/FS_Directory.zig deleted file mode 100644 index 69e0bd8e5..000000000 --- a/tools/regz/src/FS_Directory.zig +++ /dev/null @@ -1,35 +0,0 @@ -dir: std.fs.Dir, - -const vtable = Directory.VTable{ - .create_file = create_file, -}; - -pub fn create_file(ctx: *anyopaque, filename: []const u8, contents: []const u8) Directory.CreateFileError!void { - const fs: *FS_Directory = @ptrCast(@alignCast(ctx)); - const file: std.fs.File = if (std.fs.path.dirname(filename)) |dirname| blk: { - var dir = fs.dir.makeOpenPath(dirname, .{}) catch return error.System; - defer dir.close(); - - break :blk dir.createFile(std.fs.path.basename(filename), .{}) catch return error.System; - } else fs.dir.createFile(filename, .{}) catch return error.System; - defer file.close(); - - file.writeAll(contents) catch return error.System; -} - -pub fn init(dir: std.fs.Dir) FS_Directory { - return FS_Directory{ - .dir = dir, - }; -} - -pub fn directory(fs: *FS_Directory) Directory { - return Directory{ - .ptr = fs, - .vtable = &vtable, - }; -} - -const FS_Directory = @This(); -const std = @import("std"); -const Directory = @import("Directory.zig"); diff --git a/tools/regz/src/VirtualFilesystem.zig b/tools/regz/src/VirtualFilesystem.zig index 4481f0251..040f35940 100644 --- a/tools/regz/src/VirtualFilesystem.zig +++ b/tools/regz/src/VirtualFilesystem.zig @@ -1,9 +1,9 @@ //! Filesystem to store generated files gpa: Allocator, -directories: Map(ID, Dir) = .{}, -files: Map(ID, File) = .{}, +directories: Map(ID, Dir) = .empty, +files: Map(ID, File) = .empty, // child -> parent -hierarchy: Map(ID, ID) = .{}, +hierarchy: Map(ID, ID) = .empty, next_id: u16 = 1, const VirtualFilesystem = @This(); @@ -13,7 +13,7 @@ const Allocator = std.mem.Allocator; const Map = std.AutoArrayHashMapUnmanaged; const assert = std.debug.assert; -const Directory = @import("Database.zig").Directory; +const log = std.log.scoped(.vfs); pub const Kind = enum { file, @@ -26,18 +26,76 @@ pub const Dir = struct { pub fn deinit(d: *Dir, gpa: Allocator) void { gpa.free(d.name); } + + fn create_file(userdata: ?*anyopaque, dir: std.Io.Dir, sub_path: []const u8, _: std.Io.Dir.CreateFileOptions) std.Io.File.OpenError!std.Io.File { + const vfs: *VirtualFilesystem = @ptrCast(@alignCast(userdata.?)); + const dir_id: ID = @enumFromInt(dir.handle); + + if (std.mem.findScalar(u8, sub_path, '/') != null) { + log.err("path includes '/': '{s}'", .{sub_path}); + return error.BadPathName; + } + + const id = vfs.create_file(dir_id, sub_path) catch |err| switch (err) { + error.OutOfMemory => return error.NoSpaceLeft, + }; + return .{ + .handle = @intFromEnum(id), + .flags = .{ + .nonblocking = false, + }, + }; + } + + fn create_dir_path_open( + userdata: ?*anyopaque, + parent_dir: std.Io.Dir, + sub_path: []const u8, + _: std.Io.Dir.Permissions, + _: std.Io.Dir.OpenOptions, + ) std.Io.Dir.CreateDirPathOpenError!std.Io.Dir { + const vfs: *VirtualFilesystem = @ptrCast(@alignCast(userdata.?)); + const parent: ID = @enumFromInt(parent_dir.handle); + const id = vfs.create_dir(parent, sub_path) catch return error.NoSpaceLeft; + + return .{ + .handle = @intFromEnum(id), + }; + } + + fn close(_: ?*anyopaque, _: []const std.Io.Dir) void {} }; pub const File = struct { name: []const u8, - content: []const u8, + content: std.Io.Writer.Allocating, pub fn deinit(f: *File, gpa: Allocator) void { gpa.free(f.name); - gpa.free(f.content); + f.content.deinit(); } + + pub fn close(_: ?*anyopaque, _: []const std.Io.File) void {} }; +fn operate(userdata: ?*anyopaque, op: std.Io.Operation) std.Io.Cancelable!std.Io.Operation.Result { + const vfs: *VirtualFilesystem = @ptrCast(@alignCast(userdata.?)); + return switch (op) { + .file_write_streaming => |write_op| blk: { + const file = vfs.files.getPtr(@enumFromInt(write_op.file.handle)).?; + const header = write_op.header; + const data = write_op.data; + const splat = write_op.splat; + break :blk .{ + .file_write_streaming = file.content.writer.writeSplatHeader(header, data, splat) catch error.NoSpaceLeft, + }; + }, + .file_read_streaming => unreachable, + .device_io_control => unreachable, + .net_receive => unreachable, + }; +} + pub const ID = enum(u16) { root = 0, _, @@ -58,27 +116,23 @@ pub fn deinit(fs: *VirtualFilesystem) void { fs.hierarchy.deinit(fs.gpa); } -pub fn dir(fs: *VirtualFilesystem) Directory { - return Directory{ - .ptr = @ptrCast(fs), - .vtable = &.{ - .create_file = create_file_fn, - }, - }; +pub fn root_dir(fs: *VirtualFilesystem) std.Io.Dir { + _ = fs; + return .{ .handle = @intFromEnum(ID.root) }; } pub fn get_file(fs: *VirtualFilesystem, path: []const u8) !?ID { - var components: std.ArrayList([]const u8) = .{}; + var components: std.ArrayList([]const u8) = .empty; defer components.deinit(fs.gpa); var it = std.mem.tokenizeScalar(u8, path, '/'); while (it.next()) |component| try components.append(fs.gpa, component); - return fs.recursive_get_file(.root, components.items); + return fs.recursive_get_file(0, .root, components.items); } -fn recursive_get_file(fs: *VirtualFilesystem, dir_id: ID, components: []const []const u8) !?ID { +fn recursive_get_file(fs: *VirtualFilesystem, depth: usize, dir_id: ID, components: []const []const u8) !?ID { return switch (components.len) { 0 => null, 1 => blk: { @@ -102,7 +156,7 @@ fn recursive_get_file(fs: *VirtualFilesystem, dir_id: ID, components: []const [] if (child.kind != .directory) continue; - break try fs.recursive_get_file(child.id, components[1..]) orelse continue; + break try fs.recursive_get_file(depth + 1, child.id, components[1..]) orelse continue; } else null; }, }; @@ -114,7 +168,7 @@ pub const Entry = struct { }; pub fn get_children(fs: *VirtualFilesystem, allocator: Allocator, id: ID) ![]const Entry { - var ret: std.ArrayList(Entry) = .{}; + var ret: std.ArrayList(Entry) = .empty; for (fs.hierarchy.keys(), fs.hierarchy.values()) |child_id, parent_id| { if (parent_id == id) try ret.append(allocator, .{ @@ -143,14 +197,13 @@ fn create_dir(fs: *VirtualFilesystem, parent: ID, name: []const u8) !ID { return id; } -fn create_file(fs: *VirtualFilesystem, parent: ID, name: []const u8, content: []const u8) !ID { +fn create_file(fs: *VirtualFilesystem, parent: ID, name: []const u8) !ID { const id = fs.new_id(); const name_copy = try fs.gpa.dupe(u8, name); - const content_copy = try fs.gpa.dupe(u8, content); try fs.files.put(fs.gpa, id, .{ .name = name_copy, - .content = content_copy, + .content = .init(fs.gpa), }); try fs.hierarchy.put(fs.gpa, id, parent); @@ -178,7 +231,7 @@ pub fn get_name(fs: *VirtualFilesystem, id: ID) []const u8 { pub fn get_content(fs: *VirtualFilesystem, id: ID) []const u8 { assert(fs.get_kind(id) == .file); - return fs.files.get(id).?.content; + return fs.files.get(id).?.content.writer.buffered(); } fn get_child(fs: *VirtualFilesystem, parent: ID, component: []const u8) ?ID { @@ -188,26 +241,133 @@ fn get_child(fs: *VirtualFilesystem, parent: ID, component: []const u8) ?ID { } else null; } -fn create_file_fn(ctx: *anyopaque, path: []const u8, content: []const u8) Directory.CreateFileError!void { - const fs: *VirtualFilesystem = @ptrCast(@alignCast(ctx)); - - var components: std.ArrayList([]const u8) = .{}; - defer components.deinit(fs.gpa); - - var it = std.mem.tokenizeScalar(u8, path, '/'); - while (it.next()) |component| - try components.append(fs.gpa, component); - - var parent: ID = .root; - if (components.items.len > 1) for (components.items[0 .. components.items.len - 2]) |component| { - const dir_id: ID = fs.get_child(parent, component) orelse blk: { - const id = try fs.create_dir(parent, component); - break :blk id; - }; - - parent = dir_id; +pub fn io(vfs: *VirtualFilesystem) std.Io { + return .{ + .userdata = vfs, + .vtable = &.{ + .dirCreateFile = Dir.create_file, + .operate = operate, + + // Default/failing/unimplemented handlers + .crashHandler = std.Io.noCrashHandler, + .async = std.Io.noAsync, + .concurrent = std.Io.failingConcurrent, + .await = std.Io.unreachableAwait, + .cancel = std.Io.unreachableCancel, + .groupAsync = std.Io.noGroupAsync, + .groupConcurrent = std.Io.failingGroupConcurrent, + .groupAwait = std.Io.unreachableGroupAwait, + .groupCancel = std.Io.unreachableGroupCancel, + + .recancel = std.Io.unreachableRecancel, + .swapCancelProtection = std.Io.unreachableSwapCancelProtection, + .checkCancel = std.Io.unreachableCheckCancel, + + .futexWait = std.Io.noFutexWait, + .futexWaitUncancelable = std.Io.noFutexWaitUncancelable, + .futexWake = std.Io.noFutexWake, + + .batchAwaitAsync = std.Io.unreachableBatchAwaitAsync, + .batchAwaitConcurrent = std.Io.unreachableBatchAwaitConcurrent, + .batchCancel = std.Io.unreachableBatchCancel, + + .dirCreateDir = std.Io.failingDirCreateDir, + .dirCreateDirPath = std.Io.failingDirCreateDirPath, + .dirCreateDirPathOpen = Dir.create_dir_path_open, + .dirOpenDir = std.Io.failingDirOpenDir, + .dirStat = std.Io.failingDirStat, + .dirStatFile = std.Io.failingDirStatFile, + .dirAccess = std.Io.failingDirAccess, + .dirCreateFileAtomic = std.Io.failingDirCreateFileAtomic, + .dirOpenFile = std.Io.failingDirOpenFile, + .dirClose = Dir.close, + .dirRead = std.Io.noDirRead, + .dirRealPath = std.Io.failingDirRealPath, + .dirRealPathFile = std.Io.failingDirRealPathFile, + .dirDeleteFile = std.Io.failingDirDeleteFile, + .dirDeleteDir = std.Io.failingDirDeleteDir, + .dirRename = std.Io.failingDirRename, + .dirRenamePreserve = std.Io.failingDirRenamePreserve, + .dirSymLink = std.Io.failingDirSymLink, + .dirReadLink = std.Io.failingDirReadLink, + .dirSetOwner = std.Io.failingDirSetOwner, + .dirSetFileOwner = std.Io.failingDirSetFileOwner, + .dirSetPermissions = std.Io.failingDirSetPermissions, + .dirSetFilePermissions = std.Io.failingDirSetFilePermissions, + .dirSetTimestamps = std.Io.noDirSetTimestamps, + .dirHardLink = std.Io.failingDirHardLink, + + .fileStat = std.Io.failingFileStat, + .fileLength = std.Io.failingFileLength, + .fileClose = File.close, + .fileWritePositional = std.Io.failingFileWritePositional, + .fileWriteFileStreaming = std.Io.noFileWriteFileStreaming, + .fileWriteFilePositional = std.Io.noFileWriteFilePositional, + .fileReadPositional = std.Io.failingFileReadPositional, + .fileSeekBy = std.Io.failingFileSeekBy, + .fileSeekTo = std.Io.failingFileSeekTo, + .fileSync = std.Io.failingFileSync, + .fileIsTty = std.Io.unreachableFileIsTty, + .fileEnableAnsiEscapeCodes = std.Io.unreachableFileEnableAnsiEscapeCodes, + .fileSupportsAnsiEscapeCodes = std.Io.unreachableFileSupportsAnsiEscapeCodes, + .fileSetLength = std.Io.failingFileSetLength, + .fileSetOwner = std.Io.failingFileSetOwner, + .fileSetPermissions = std.Io.failingFileSetPermissions, + .fileSetTimestamps = std.Io.noFileSetTimestamps, + .fileLock = std.Io.failingFileLock, + .fileTryLock = std.Io.failingFileTryLock, + .fileUnlock = std.Io.unreachableFileUnlock, + .fileDowngradeLock = std.Io.failingFileDowngradeLock, + .fileRealPath = std.Io.failingFileRealPath, + .fileHardLink = std.Io.failingFileHardLink, + + .fileMemoryMapCreate = std.Io.failingFileMemoryMapCreate, + .fileMemoryMapDestroy = std.Io.unreachableFileMemoryMapDestroy, + .fileMemoryMapSetLength = std.Io.unreachableFileMemoryMapSetLength, + .fileMemoryMapRead = std.Io.unreachableFileMemoryMapRead, + .fileMemoryMapWrite = std.Io.unreachableFileMemoryMapWrite, + + .processExecutableOpen = std.Io.failingProcessExecutableOpen, + .processExecutablePath = std.Io.failingProcessExecutablePath, + .lockStderr = std.Io.unreachableLockStderr, + .tryLockStderr = std.Io.noTryLockStderr, + .unlockStderr = std.Io.unreachableUnlockStderr, + .processCurrentPath = std.Io.failingProcessCurrentPath, + .processSetCurrentDir = std.Io.failingProcessSetCurrentDir, + .processSetCurrentPath = std.Io.failingProcessSetCurrentPath, + .processReplace = std.Io.failingProcessReplace, + .processReplacePath = std.Io.failingProcessReplacePath, + .processSpawn = std.Io.failingProcessSpawn, + .processSpawnPath = std.Io.failingProcessSpawnPath, + .childWait = std.Io.unreachableChildWait, + .childKill = std.Io.unreachableChildKill, + + .progressParentFile = std.Io.failingProgressParentFile, + + .now = std.Io.noNow, + .clockResolution = std.Io.failingClockResolution, + .sleep = std.Io.noSleep, + + .random = std.Io.noRandom, + .randomSecure = std.Io.failingRandomSecure, + + .netListenIp = std.Io.failingNetListenIp, + .netAccept = std.Io.failingNetAccept, + .netBindIp = std.Io.failingNetBindIp, + .netConnectIp = std.Io.failingNetConnectIp, + .netListenUnix = std.Io.failingNetListenUnix, + .netConnectUnix = std.Io.failingNetConnectUnix, + .netSocketCreatePair = std.Io.failingNetSocketCreatePair, + .netSend = std.Io.failingNetSend, + + .netRead = std.Io.failingNetRead, + .netWrite = std.Io.failingNetWrite, + .netWriteFile = std.Io.failingNetWriteFile, + .netClose = std.Io.unreachableNetClose, + .netShutdown = std.Io.failingNetShutdown, + .netInterfaceNameResolve = std.Io.failingNetInterfaceNameResolve, + .netInterfaceName = std.Io.unreachableNetInterfaceName, + .netLookup = std.Io.failingNetLookup, + }, }; - - const file_name = components.items[components.items.len - 1]; - _ = try fs.create_file(parent, file_name, content); } diff --git a/tools/regz/src/atdf.zig b/tools/regz/src/atdf.zig index 70c140570..70f8497db 100644 --- a/tools/regz/src/atdf.zig +++ b/tools/regz/src/atdf.zig @@ -11,7 +11,7 @@ const DeviceID = Database.DeviceID; const StructID = Database.StructID; const RegisterID = Database.RegisterID; -const xml = @import("xml.zig"); +const xml = @import("xml"); const Arch = @import("arch.zig").Arch; const log = std.log.scoped(.atdf); @@ -368,7 +368,7 @@ fn load_module_type(ctx: *Context, node: xml.Node) !void { fn load_module_interrupt_group(ctx: *Context, node: xml.Node) !void { const name = node.get_attribute("name") orelse return error.MissingInterruptGroupName; - try ctx.interrupt_groups.put(ctx.db.gpa, name, .{}); + try ctx.interrupt_groups.put(ctx.db.gpa, name, .empty); var interrupt_it = node.iterate(&.{}, &.{"interrupt"}); while (interrupt_it.next()) |interrupt_node| diff --git a/tools/regz/src/embassy.zig b/tools/regz/src/embassy.zig index b716fecc0..d52e792b7 100644 --- a/tools/regz/src/embassy.zig +++ b/tools/regz/src/embassy.zig @@ -144,12 +144,12 @@ pub const ChipFile = struct { } }; -pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void { - var package_dir = try std.fs.cwd().openDir(path, .{}); - defer package_dir.close(); +pub fn load_into_db(db: *Database, io: std.Io, path: []const u8, device: ?[]const u8) !void { + var package_dir = try std.Io.Dir.cwd().openDir(io, path, .{}); + defer package_dir.close(io); - var data_dir = try package_dir.openDir("data", .{}); - defer data_dir.close(); + var data_dir = try package_dir.openDir(io, "data", .{}); + defer data_dir.close(io); var arena = std.heap.ArenaAllocator.init(db.gpa); defer arena.deinit(); @@ -163,19 +163,19 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void chip_files.deinit(allocator); } - var register_files = std.StringArrayHashMap(std.json.Parsed(std.json.Value)).init(allocator); + var register_files: std.StringArrayHashMapUnmanaged(std.json.Parsed(std.json.Value)) = .empty; defer { for (register_files.values()) |*value| value.deinit(); - register_files.deinit(); + register_files.deinit(allocator); } - var chips_dir = try data_dir.openDir("chips", .{ .iterate = true }); - defer chips_dir.close(); + var chips_dir = try data_dir.openDir(io, "chips", .{ .iterate = true }); + defer chips_dir.close(io); var it = chips_dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) continue; @@ -189,7 +189,7 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void std.log.info("file: {s}", .{entry.name}); - const chip_file_text = try chips_dir.readFileAlloc(allocator, entry.name, std.math.maxInt(usize)); + const chip_file_text = try chips_dir.readFileAlloc(io, entry.name, allocator, .unlimited); defer allocator.free(chip_file_text); var scanner = std.json.Scanner.initCompleteInput(allocator, chip_file_text); @@ -214,8 +214,8 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void return error.DeviceMissing; } - var registers_dir = try data_dir.openDir("registers", .{ .iterate = true }); - defer registers_dir.close(); + var registers_dir = try data_dir.openDir(io, "registers", .{ .iterate = true }); + defer registers_dir.close(io); //This holds extra data for extended registers var extends_list_arena = std.heap.ArenaAllocator.init(allocator); @@ -223,13 +223,13 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void const extends_list_allocator = extends_list_arena.allocator(); it = registers_dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) continue; std.log.info("file: {s}", .{entry.name}); - const register_file_text = try registers_dir.readFileAlloc(allocator, entry.name, std.math.maxInt(usize)); + const register_file_text = try registers_dir.readFileAlloc(io, entry.name, allocator, .unlimited); defer allocator.free(register_file_text); var scanner = std.json.Scanner.initCompleteInput(allocator, register_file_text); @@ -249,7 +249,7 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void try handle_extends(allocator, extends_list_allocator, ®ister_file.value); const register_name = try allocator.dupe(u8, entry.name[0 .. entry.name.len - std.fs.path.extension(entry.name).len]); - try register_files.put(register_name, register_file); + try register_files.put(allocator, register_name, register_file); } // sort to try to keep things somewhat in order @@ -260,8 +260,8 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void .name = name, }); - var enums = std.StringArrayHashMap(Database.EnumID).init(allocator); - defer enums.deinit(); + var enums: std.StringArrayHashMapUnmanaged(Database.EnumID) = .empty; + defer enums.deinit(allocator); for (register_file.value.object.keys(), register_file.value.object.values()) |key, obj| { if (!std.mem.startsWith(u8, key, "enum/")) @@ -277,7 +277,7 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void .size_bits = @intCast(size), }); - try enums.put(key["enum/".len..], enum_id); + try enums.put(allocator, key["enum/".len..], enum_id); for (obj.object.get("variants").?.array.items) |item| { const enum_field_name = item.object.get("name").?.string; @@ -592,41 +592,45 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void /// Reads throught the json data handles the "extends" inheritance. fn handle_extends(allocator: std.mem.Allocator, extends_allocator: std.mem.Allocator, root_json: *std.json.Value) !void { - var root_json_clone = std.json.Value{ .object = try root_json.object.clone() }; - var itr = root_json.object.iterator(); - while (itr.next()) |entry| { - const item_name = entry.key_ptr.*; - const item_value = entry.value_ptr; - - if (item_value.*.object.contains("extends")) { - - // This Collects unique items from the ancestors. - var arr: std.json.ObjectMap = std.json.ObjectMap.init(allocator); - defer arr.deinit(); - - // Get child value and kind holder of inherting items - var child = root_json.object.get(item_name).?; - const list_name = get_section(item_name); - - // Add child items to dictionary so they are not overwritten. - for (child.object.get(list_name).?.array.items) |child_item| { - const child_item_name = child_item.object.get("name").?.string; - try arr.put(child_item_name, child_item); - } - - // Handle all parents and grandparents of the current child. - try resolve_inheritance_recursively(allocator, &root_json_clone, item_name, &arr); - - // Replacement items will go here and should be released via the arena extends allocator - var new_list = std.json.Array.init(extends_allocator); - for (arr.values()) |value| { - try new_list.append(value); - } - try child.object.put(list_name, std.json.Value{ .array = new_list }); - try root_json_clone.object.put(item_name, child); - } - } - root_json.* = root_json_clone; + // TODO: fix later + _ = allocator; + _ = extends_allocator; + _ = root_json; + //var root_json_clone = std.json.Value{ .object = try root_json.object.clone(extends_allocator) }; + //var itr = root_json.object.iterator(); + //while (itr.next()) |entry| { + // const item_name = entry.key_ptr.*; + // const item_value = entry.value_ptr; + + // if (item_value.*.object.contains("extends")) { + + // // This Collects unique items from the ancestors. + // var arr: std.json.ObjectMap = std.json.ObjectMap.init(allocator); + // defer arr.deinit(); + + // // Get child value and kind holder of inherting items + // var child = root_json.object.get(item_name).?; + // const list_name = get_section(item_name); + + // // Add child items to dictionary so they are not overwritten. + // for (child.object.get(list_name).?.array.items) |child_item| { + // const child_item_name = child_item.object.get("name").?.string; + // try arr.put(child_item_name, child_item); + // } + + // // Handle all parents and grandparents of the current child. + // try resolve_inheritance_recursively(allocator, &root_json_clone, item_name, &arr); + + // // Replacement items will go here and should be released via the arena extends allocator + // var new_list = std.json.Array.init(extends_allocator); + // for (arr.values()) |value| { + // try new_list.append(value); + // } + // try child.object.put(list_name, std.json.Value{ .array = new_list }); + // try root_json_clone.object.put(item_name, child); + // } + //} + //root_json.* = root_json_clone; } // General function to handle inheritance diff --git a/tools/regz/src/gen.zig b/tools/regz/src/gen.zig index b0173c971..e37b9f402 100644 --- a/tools/regz/src/gen.zig +++ b/tools/regz/src/gen.zig @@ -13,10 +13,9 @@ const DevicePeripheral = Database.DevicePeripheral; const EnumID = Database.EnumID; const StructID = Database.StructID; const NestedStructField = Database.NestedStructField; +const VirtualFilesystem = @import("VirtualFilesystem.zig"); const Properties = @import("properties.zig").Properties; -const Directory = @import("Directory.zig"); -const VirtualFilesystem = @import("VirtualFilesystem.zig"); const arm = @import("arch/arm.zig"); const avr = @import("arch/avr.zig"); const riscv = @import("arch/riscv.zig"); @@ -25,23 +24,24 @@ const log = std.log.scoped(.gen); pub const ToZigOptions = struct {}; -pub fn to_zig(db: *Database, dir: Directory, opts: ToZigOptions) !void { +pub fn to_zig(db: *Database, io: std.Io, dir: std.Io.Dir, opts: ToZigOptions) !void { var arena = std.heap.ArenaAllocator.init(db.gpa); defer arena.deinit(); - try write_device_files(db, arena.allocator(), dir, opts); - try write_types_files(db, arena.allocator(), dir, opts); + try write_device_files(io, db, arena.allocator(), dir, opts); + try write_types_files(io, db, arena.allocator(), dir, opts); } fn write_device_files( + io: std.Io, db: *Database, arena: Allocator, - dir: Directory, + dir: std.Io.Dir, opts: ToZigOptions, ) !void { const devices = try db.get_devices(arena); for (devices) |device| { - write_device_file(db, arena, &device, dir, opts) catch |err| { + write_device_file(db, io, arena, &device, dir, opts) catch |err| { log.warn("failed to write device: {}", .{err}); }; } @@ -62,9 +62,10 @@ fn write_imports(opts: ToZigOptions, types_public: bool, types_path: []const u8, fn write_device_file( db: *Database, + io: std.Io, arena: Allocator, device: *const Database.Device, - dir: Directory, + dir: std.Io.Dir, opts: ToZigOptions, ) !void { var buf: std.Io.Writer.Allocating = .init(arena); @@ -149,22 +150,34 @@ fn write_device_file( try ast.render(arena, &rendered_buffer.writer, fixups); const filename = try std.fmt.allocPrint(arena, "{s}.zig", .{device.name}); - try dir.create_file(filename, rendered_buffer.written()); + try dir.writeFile(io, .{ + .sub_path = filename, + .data = rendered_buffer.written(), + }); } -fn write_types_files(db: *Database, arena: Allocator, dir: Directory, opts: ToZigOptions) !void { - try dir.create_file("types.zig", +fn write_types_files(io: std.Io, db: *Database, arena: Allocator, dir: std.Io.Dir, opts: ToZigOptions) !void { + try dir.writeFile(io, .{ + .sub_path = "types.zig", + .data = \\pub const peripherals = @import("types/peripherals.zig"); \\ - ); + , + }); - try write_peripherals_files(db, arena, dir, opts); + try write_peripherals_files(io, db, arena, dir, opts); } -fn write_peripherals_files(db: *Database, arena: Allocator, dir: Directory, opts: ToZigOptions) !void { +fn write_peripherals_files(io: std.Io, db: *Database, arena: Allocator, dir: std.Io.Dir, opts: ToZigOptions) !void { var index_content: std.Io.Writer.Allocating = .init(arena); const index_writer = &index_content.writer; + const types_dir = try dir.createDirPathOpen(io, "types", .{}); + defer types_dir.close(io); + + const peripherals_dir = try types_dir.createDirPathOpen(io, "peripherals", .{}); + defer peripherals_dir.close(io); + const peripherals = try db.get_peripherals(arena); for (peripherals) |peripheral| { var periph_content: std.Io.Writer.Allocating = .init(arena); @@ -180,7 +193,7 @@ fn write_peripherals_files(db: *Database, arena: Allocator, dir: Directory, opts continue; }; - const path = try std.fmt.allocPrint(arena, "types/peripherals/{s}.zig", .{ + const path = try std.fmt.allocPrint(arena, "{s}.zig", .{ peripheral.name, }); @@ -205,7 +218,10 @@ fn write_peripherals_files(db: *Database, arena: Allocator, dir: Directory, opts const fixups: std.zig.Ast.Render.Fixups = .{}; try ast.render(arena, &rendered_buffer.writer, fixups); - try dir.create_file(path, rendered_buffer.written()); + try peripherals_dir.writeFile(io, .{ + .sub_path = path, + .data = rendered_buffer.written(), + }); if (try db.struct_is_zero_sized(arena, peripheral.struct_id)) { try index_writer.print( @@ -227,7 +243,10 @@ fn write_peripherals_files(db: *Database, arena: Allocator, dir: Directory, opts } } - try dir.create_file("types/peripherals.zig", index_content.written()); + try types_dir.writeFile(io, .{ + .sub_path = "peripherals.zig", + .data = index_content.written(), + }); } pub fn write_file_comment(allocator: Allocator, comment: []const u8, writer: *std.Io.Writer) !void { @@ -1442,8 +1461,6 @@ fn raw_property_value_to_bool(value: []const u8) !bool { return error.BadValue; } -const tests = @import("output_tests.zig"); - fn expect_register(expected: *const Register, actual: *const Register) !void { try std.testing.expectEqual(expected.id, actual.id); try std.testing.expectEqual(expected.struct_id, actual.struct_id); @@ -1727,16 +1744,46 @@ fn expect_output(expected_outputs: []const ExpectedOutput, vfs: *VirtualFilesyst } test "gen.peripheral instantiation" { - var db = try tests.peripheral_instantiation(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + const struct_id = try db.get_peripheral_struct(peripheral_id); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 32, + .offset_bytes = 0, + .reset_mask = 0x1, + .reset_value = 0x1, + }); + + _ = try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 1, + .offset_bits = 0, + }); + + const device_id = try db.create_device(.{ + .name = "TEST_DEVICE", + .arch = .cortex_m0, + }); + + _ = try db.create_device_peripheral(device_id, .{ + .name = "TEST0", + .offset_bytes = 0x1000, + .struct_id = struct_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "TEST_DEVICE.zig", @@ -1782,14 +1829,14 @@ test "gen.peripheral instantiation" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -1810,16 +1857,56 @@ test "gen.peripheral instantiation" { } test "gen.peripherals with a shared type" { - var db = try tests.peripherals_with_shared_type(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 32, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 1, + .offset_bits = 0, + }); + + const device_id = try db.create_device(.{ + .name = "TEST_DEVICE", + .arch = .cortex_m0, + }); + + _ = try db.create_device_peripheral( + device_id, + .{ + .name = "TEST0", + .offset_bytes = 0x1000, + .struct_id = struct_id, + }, + ); + _ = try db.create_device_peripheral( + device_id, + .{ + .name = "TEST1", + .offset_bytes = 0x2000, + .struct_id = struct_id, + }, + ); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "TEST_DEVICE.zig", @@ -1866,14 +1953,14 @@ test "gen.peripherals with a shared type" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -1894,16 +1981,51 @@ test "gen.peripherals with a shared type" { } test "gen.peripheral with modes" { - var db = try tests.peripheral_with_modes(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ .name = "TEST_PERIPHERAL" }); + const struct_id = try db.get_peripheral_struct(peripheral_id); + const register1_id = try db.create_register( + struct_id, + .{ .name = "TEST_REGISTER1", .size_bits = 32, .offset_bytes = 0 }, + ); + const register2_id = try db.create_register( + struct_id, + .{ .name = "TEST_REGISTER2", .size_bits = 32, .offset_bytes = 0 }, + ); + const common_reg_id = try db.create_register( + struct_id, + .{ .name = "COMMON_REGISTER", .size_bits = 32, .offset_bytes = 4 }, + ); + + try db.add_register_field(common_reg_id, .{ + .name = "TEST_FIELD", + .size_bits = 1, + .offset_bits = 0, + }); + + const mode1_id = try db.create_mode(struct_id, .{ + .name = "TEST_MODE1", + .value = "0x00", + .qualifier = "TEST_PERIPHERAL.TEST_MODE1.COMMON_REGISTER.TEST_FIELD", + }); + const mode2_id = try db.create_mode(struct_id, .{ + .name = "TEST_MODE2", + .value = "0x01", + .qualifier = "TEST_PERIPHERAL.TEST_MODE2.COMMON_REGISTER.TEST_FIELD", + }); + + try db.add_register_mode(register1_id, mode1_id); + try db.add_register_mode(register2_id, mode2_id); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -1913,14 +2035,14 @@ test "gen.peripheral with modes" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -1980,16 +2102,36 @@ test "gen.peripheral with modes" { } test "gen.peripheral with enum" { - var db = try tests.peripheral_with_enum(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + + const enum_id = try db.create_enum(struct_id, .{ + .name = "TEST_ENUM", + .size_bits = 4, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + _ = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -1999,14 +2141,14 @@ test "gen.peripheral with enum" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2030,16 +2172,35 @@ test "gen.peripheral with enum" { } test "gen.peripheral with enum, enum is exhausted of values" { - var db = try tests.peripheral_with_enum_and_its_exhausted_of_values(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const enum_id = try db.create_enum(struct_id, .{ + .name = "TEST_ENUM", + .size_bits = 1, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + _ = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2049,14 +2210,14 @@ test "gen.peripheral with enum, enum is exhausted of values" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2079,16 +2240,42 @@ test "gen.peripheral with enum, enum is exhausted of values" { } test "gen.field with named enum" { - var db = try tests.field_with_named_enum(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const enum_id = try db.create_enum(struct_id, .{ + .name = "TEST_ENUM", + .size_bits = 4, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 4, + .offset_bits = 0, + .enum_id = enum_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2098,14 +2285,14 @@ test "gen.field with named enum" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2132,16 +2319,44 @@ test "gen.field with named enum" { } test "gen.field with named enum and named default" { - var db = try tests.field_with_named_enum_and_named_default(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const enum_id = try db.create_enum(struct_id, .{ + .name = "TEST_ENUM", + .size_bits = 4, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + .reset_mask = 0xF, + .reset_value = 0x1, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 4, + .offset_bits = 0, + .enum_id = enum_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2151,14 +2366,14 @@ test "gen.field with named enum and named default" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2185,16 +2400,44 @@ test "gen.field with named enum and named default" { } test "gen.field with named enum and unnamed default" { - var db = try tests.field_with_named_enum_and_unnamed_default(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const enum_id = try db.create_enum(struct_id, .{ + .name = "TEST_ENUM", + .size_bits = 4, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + .reset_mask = 0xF, + .reset_value = 0xA, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 4, + .offset_bits = 0, + .enum_id = enum_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2204,14 +2447,14 @@ test "gen.field with named enum and unnamed default" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2238,16 +2481,41 @@ test "gen.field with named enum and unnamed default" { } test "gen.field with anonymous enum" { - var db = try tests.field_with_anonymous_enum(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const enum_id = try db.create_enum(null, .{ + .size_bits = 4, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 4, + .offset_bits = 0, + .enum_id = enum_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2257,14 +2525,14 @@ test "gen.field with anonymous enum" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2289,16 +2557,43 @@ test "gen.field with anonymous enum" { } test "gen.field with anonymous enum and default" { - var db = try tests.field_with_anonymous_enum_and_default(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const enum_id = try db.create_enum(null, .{ + .size_bits = 4, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + .reset_mask = 0xF, + .reset_value = 0x1, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 4, + .offset_bits = 0, + .enum_id = enum_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2308,14 +2603,14 @@ test "gen.field with anonymous enum and default" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2340,16 +2635,50 @@ test "gen.field with anonymous enum and default" { } test "gen.namespaced register groups" { - var db = try tests.namespaced_register_groups(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + // peripheral + const peripheral_id = try db.create_peripheral(.{ + .name = "PORT", + }); + const struct_id = try db.get_peripheral_struct(peripheral_id); + + // register_groups + const portb_group_id = try db.create_nested_struct(struct_id, .{ .name = "PORTB" }); + const portc_group_id = try db.create_nested_struct(struct_id, .{ .name = "PORTC" }); + + // registers + _ = try db.create_register(portb_group_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0 }); + _ = try db.create_register(portb_group_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 1 }); + _ = try db.create_register(portb_group_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 2 }); + _ = try db.create_register(portc_group_id, .{ .name = "PORTC", .size_bits = 8, .offset_bytes = 0 }); + _ = try db.create_register(portc_group_id, .{ .name = "DDRC", .size_bits = 8, .offset_bytes = 1 }); + _ = try db.create_register(portc_group_id, .{ .name = "PINC", .size_bits = 8, .offset_bytes = 2 }); + + // device + const device_id = try db.create_device(.{ .name = "ATmega328P", .arch = .avr8 }); + + // instances + _ = try db.create_device_peripheral(device_id, .{ + .name = "PORTB", + .offset_bytes = 0x23, + .struct_id = portb_group_id, + }); + + _ = try db.create_device_peripheral(device_id, .{ + .name = "PORTC", + .offset_bytes = 0x26, + .struct_id = portc_group_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "ATmega328P.zig", @@ -2396,14 +2725,14 @@ test "gen.namespaced register groups" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORT = @import("peripherals/PORT.zig"); \\ , }, .{ - .path = "peripherals/PORT.zig", + .path = "types/peripherals/PORT.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2434,16 +2763,35 @@ test "gen.namespaced register groups" { } test "gen.peripheral with reserved register" { - var db = try tests.peripheral_with_reserved_register(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "PORTB", + }); + const struct_id = try db.get_peripheral_struct(peripheral_id); + + _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 32, .offset_bytes = 0 }); + _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 32, .offset_bytes = 8 }); + + const device_id = try db.create_device(.{ + .name = "ATmega328P", + .arch = .avr8, + }); + + _ = try db.create_device_peripheral(device_id, .{ + .name = "PORTB", + .offset_bytes = 0x23, + .struct_id = struct_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "ATmega328P.zig", @@ -2489,14 +2837,14 @@ test "gen.peripheral with reserved register" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORTB = @import("peripherals/PORTB.zig").PORTB; \\ , }, .{ - .path = "peripherals/PORTB.zig", + .path = "types/peripherals/PORTB.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2518,16 +2866,35 @@ test "gen.peripheral with reserved register" { } test "gen.peripheral with count" { - var db = try tests.peripheral_with_count(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const device_id = try db.create_device(.{ .name = "ATmega328P", .arch = .avr8 }); + + const peripheral_id = try db.create_peripheral(.{ + .name = "PORTB", + .size_bytes = 3, + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + _ = try db.create_device_peripheral(device_id, .{ + .name = "PORTB", + .offset_bytes = 0x23, + .count = 4, + .struct_id = struct_id, + }); + + _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0 }); + _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 1 }); + _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 2 }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "ATmega328P.zig", @@ -2573,14 +2940,14 @@ test "gen.peripheral with count" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORTB = @import("peripherals/PORTB.zig").PORTB; \\ , }, .{ - .path = "peripherals/PORTB.zig", + .path = "types/peripherals/PORTB.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2602,16 +2969,36 @@ test "gen.peripheral with count" { } test "gen.peripheral with count, padding required" { - var db = try tests.peripheral_with_count_padding_required(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const device_id = try db.create_device(.{ .name = "ATmega328P", .arch = .avr8 }); + + const peripheral_id = try db.create_peripheral(.{ + .name = "PORTB", + .size_bytes = 4, + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + + _ = try db.create_device_peripheral(device_id, .{ + .name = "PORTB", + .offset_bytes = 0x23, + .count = 4, + .struct_id = struct_id, + }); + + _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0 }); + _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 1 }); + _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 2 }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "ATmega328P.zig", @@ -2657,14 +3044,14 @@ test "gen.peripheral with count, padding required" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORTB = @import("peripherals/PORTB.zig").PORTB; \\ , }, .{ - .path = "peripherals/PORTB.zig", + .path = "types/peripherals/PORTB.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2687,16 +3074,36 @@ test "gen.peripheral with count, padding required" { } test "gen.register with count" { - var db = try tests.register_with_count(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const device_id = try db.create_device(.{ + .name = "ATmega328P", + .arch = .avr8, + }); + + const peripheral_id = try db.create_peripheral(.{ + .name = "PORTB", + }); + const struct_id = try db.get_peripheral_struct(peripheral_id); + + _ = try db.create_device_peripheral(device_id, .{ + .name = "PORTB", + .offset_bytes = 0x23, + .struct_id = struct_id, + }); + + _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0, .count = 4 }); + _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 4 }); + _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 5 }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "ATmega328P.zig", @@ -2742,14 +3149,14 @@ test "gen.register with count" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORTB = @import("peripherals/PORTB.zig").PORTB; \\ , }, .{ - .path = "peripherals/PORTB.zig", + .path = "types/peripherals/PORTB.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2771,16 +3178,49 @@ test "gen.register with count" { } test "gen.register with count and fields" { - var db = try tests.register_with_count_and_fields(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const device_id = try db.create_device(.{ + .name = "ATmega328P", + .arch = .avr8, + }); + + const peripheral_id = try db.create_peripheral(.{ + .name = "PORTB", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + + _ = try db.create_device_peripheral(device_id, .{ + .name = "PORTB", + .offset_bytes = 0x23, + .struct_id = struct_id, + }); + + const portb_id = try db.create_register(struct_id, .{ + .name = "PORTB", + .size_bits = 8, + .offset_bytes = 0, + .count = 4, + }); + + _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 4 }); + _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 5 }); + + try db.add_register_field(portb_id, .{ + .name = "TEST_FIELD", + .size_bits = 4, + .offset_bits = 0, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "ATmega328P.zig", @@ -2826,14 +3266,14 @@ test "gen.register with count and fields" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORTB = @import("peripherals/PORTB.zig").PORTB; \\ , }, .{ - .path = "peripherals/PORTB.zig", + .path = "types/peripherals/PORTB.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2858,16 +3298,37 @@ test "gen.register with count and fields" { } test "gen.field with count, width of one, offset, and padding" { - var db = try tests.field_with_count_width_of_one_offset_and_padding(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "PORTB", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + + const portb_id = try db.create_register(struct_id, .{ + .name = "PORTB", + .size_bits = 8, + .offset_bytes = 0, + }); + + inline for (0..5) |i| { + const suffix = std.fmt.comptimePrint("{d}", .{i}); + try db.add_register_field(portb_id, .{ + .name = "TEST_FIELD" ++ suffix, + .size_bits = 1, + .offset_bits = 2 + i, + }); + } + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2877,14 +3338,14 @@ test "gen.field with count, width of one, offset, and padding" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORTB = @import("peripherals/PORTB.zig").PORTB; \\ , }, .{ - .path = "peripherals/PORTB.zig", + .path = "types/peripherals/PORTB.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2910,16 +3371,37 @@ test "gen.field with count, width of one, offset, and padding" { } test "gen.field with count, multi-bit width, offset, and padding" { - var db = try tests.field_with_count_multi_bit_width_offset_and_padding(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "PORTB", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + + const portb_id = try db.create_register(struct_id, .{ + .name = "PORTB", + .size_bits = 8, + .offset_bytes = 0, + }); + + inline for (0..2) |i| { + const suffix = std.fmt.comptimePrint("{d}", .{i}); + try db.add_register_field(portb_id, .{ + .name = "TEST_FIELD" ++ suffix, + .size_bits = 2, + .offset_bits = 2 + (i * 2), + }); + } + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -2929,14 +3411,14 @@ test "gen.field with count, multi-bit width, offset, and padding" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const PORTB = @import("peripherals/PORTB.zig").PORTB; \\ , }, .{ - .path = "peripherals/PORTB.zig", + .path = "types/peripherals/PORTB.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -2959,16 +3441,31 @@ test "gen.field with count, multi-bit width, offset, and padding" { } test "gen.interrupts.avr" { - var db = try tests.interrupts_avr(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const device_id = try db.create_device(.{ + .name = "ATmega328P", + .arch = .avr8, + }); + + _ = try db.create_interrupt(device_id, .{ + .name = "TEST_VECTOR1", + .idx = 1, + }); + + _ = try db.create_interrupt(device_id, .{ + .name = "TEST_VECTOR2", + .idx = 3, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "ATmega328P.zig", @@ -3025,7 +3522,7 @@ test "gen.interrupts.avr" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\ , @@ -3034,16 +3531,37 @@ test "gen.interrupts.avr" { } test "gen.peripheral type with register and field" { - var db = try tests.peripheral_type_with_register_and_field(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + .description = "test peripheral", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .description = "test register", + .size_bits = 32, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .description = "test field", + .size_bits = 1, + .offset_bits = 0, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3053,14 +3571,14 @@ test "gen.peripheral type with register and field" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -3084,16 +3602,56 @@ test "gen.peripheral type with register and field" { } test "gen.name collisions in enum name cause them to be anonymous" { - var db = try tests.enums_with_name_collision(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const enum1_id = try db.create_enum(struct_id, .{ + .name = "ENUM", + .size_bits = 4, + }); + + try db.add_enum_field(enum1_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum1_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + const enum2_id = try db.create_enum(struct_id, .{ + .name = "ENUM", + .size_bits = 4, + }); + + try db.add_enum_field(enum2_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum2_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD1", + .size_bits = 4, + .offset_bits = 0, + .enum_id = enum1_id, + }); + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD2", + .size_bits = 4, + .offset_bits = 4, + .enum_id = enum2_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3103,14 +3661,14 @@ test "gen.name collisions in enum name cause them to be anonymous" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -3139,16 +3697,42 @@ test "gen.name collisions in enum name cause them to be anonymous" { } test "gen.pick one enum field in value collisions" { - var db = try tests.enum_with_value_collision(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const enum_id = try db.create_enum(null, .{ + .name = "ENUM", + .size_bits = 4, + }); + + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); + try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 0 }); + + const register_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .size_bits = 8, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .size_bits = 4, + .offset_bits = 0, + .enum_id = enum_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3158,14 +3742,14 @@ test "gen.pick one enum field in value collisions" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -3189,16 +3773,42 @@ test "gen.pick one enum field in value collisions" { } //test "gen.pick one enum field in name collisions" { -// var db = try tests.enum_fields_with_name_collision(std.testing.allocator); +// var db = try Database.create(std.testing.allocator); // defer db.destroy(); // +// const peripheral_id = try db.create_peripheral(.{ +// .name = "TEST_PERIPHERAL", +// }); +// +// const struct_id = try db.get_peripheral_struct(peripheral_id); +// const enum_id = try db.create_enum(null, .{ +// .name = "ENUM", +// .size_bits = 4, +// }); +// +// try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); +// try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 1 }); +// +// const register_id = try db.create_register(struct_id, .{ +// .name = "TEST_REGISTER", +// .size_bits = 8, +// .offset_bytes = 0, +// }); +// +// try db.add_register_field(register_id, .{ +// .name = "TEST_FIELD", +// .size_bits = 4, +// .offset_bits = 0, +// .enum_id = enum_id, +// }); +// // var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); // defer buffer.deinit(); // // var vfs: VirtualFilesystem = .init(std.testing.allocator); // defer vfs.deinit(); // -// try db.to_zig(vfs.dir(), .{}); +// try db.to_zig(vfs.io(), vfs.root_dir(), .{}); // try expect_output(&.{ // .{ // .path = "types.zig", @@ -3239,16 +3849,43 @@ test "gen.pick one enum field in value collisions" { //} //test "gen.register fields with name collision" { -// var db = try tests.register_fields_with_name_collision(std.testing.allocator); +// var db = try Database.create(std.testing.allocator); // defer db.destroy(); // +// const peripheral_id = try db.create_peripheral(.{ +// .name = "TEST_PERIPHERAL", +// .description = "test peripheral", +// }); +// +// const struct_id = try db.get_peripheral_struct(peripheral_id); +// +// const register_id = try db.create_register(struct_id, .{ +// .name = "TEST_REGISTER", +// .description = "test register", +// .size_bits = 32, +// .offset_bytes = 0, +// }); +// +// try db.add_register_field(register_id, .{ +// .name = "TEST_FIELD", +// .description = "test field 1", +// .size_bits = 1, +// .offset_bits = 0, +// }); +// try db.add_register_field(register_id, .{ +// .name = "TEST_FIELD", +// .description = "test field 2", +// .size_bits = 1, +// .offset_bits = 1, +// }); +// // var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); // defer buffer.deinit(); // // var vfs: VirtualFilesystem = .init(std.testing.allocator); // defer vfs.deinit(); // -// try db.to_zig(vfs.dir(), .{}); +// try db.to_zig(vfs.io(), vfs.root_dir(), .{}); // try expect_output(&.{ // .{ // .path = "types.zig", @@ -3288,16 +3925,45 @@ test "gen.pick one enum field in value collisions" { //} test "gen.nested struct field in a peripheral" { - var db = try tests.nested_struct_field_in_a_peripheral(std.testing.allocator, 0); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + .description = "test peripheral", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const nested_struct_id = try db.create_struct(.{}); + + const register_id = try db.create_register(nested_struct_id, .{ + .name = "TEST_REGISTER", + .description = "test register", + .size_bits = 32, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .description = "test field 1", + .size_bits = 1, + .offset_bits = 0, + }); + + try db.add_nested_struct_field(struct_id, .{ + .name = "TEST_NESTED", + .description = "test nested struct", + .offset_bytes = 0, + .struct_id = nested_struct_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3307,14 +3973,14 @@ test "gen.nested struct field in a peripheral" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -3342,16 +4008,47 @@ test "gen.nested struct field in a peripheral" { } test "gen.nested struct field in a peripheral that has a named type" { - var db = try tests.nested_struct_field_in_a_peripheral_that_has_a_named_type(std.testing.allocator, 0); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + .description = "test peripheral", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const nested_struct_id = try db.create_nested_struct(struct_id, .{ + .name = "TEST_NESTED_TYPE", + }); + + const register_id = try db.create_register(nested_struct_id, .{ + .name = "TEST_REGISTER", + .description = "test register", + .size_bits = 32, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .description = "test field 1", + .size_bits = 1, + .offset_bits = 0, + }); + + try db.add_nested_struct_field(struct_id, .{ + .name = "TEST_NESTED", + .description = "test nested struct", + .offset_bytes = 0, + .struct_id = nested_struct_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3361,14 +4058,14 @@ test "gen.nested struct field in a peripheral that has a named type" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -3398,16 +4095,45 @@ test "gen.nested struct field in a peripheral that has a named type" { } test "gen.nested struct field in a peripheral with offset" { - var db = try tests.nested_struct_field_in_a_peripheral(std.testing.allocator, 4); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + .description = "test peripheral", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const nested_struct_id = try db.create_struct(.{}); + + const register_id = try db.create_register(nested_struct_id, .{ + .name = "TEST_REGISTER", + .description = "test register", + .size_bits = 32, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .description = "test field 1", + .size_bits = 1, + .offset_bits = 0, + }); + + try db.add_nested_struct_field(struct_id, .{ + .name = "TEST_NESTED", + .description = "test nested struct", + .offset_bytes = 4, + .struct_id = nested_struct_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3417,14 +4143,14 @@ test "gen.nested struct field in a peripheral with offset" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -3454,16 +4180,52 @@ test "gen.nested struct field in a peripheral with offset" { } test "gen.nested struct field in nested struct field" { - var db = try tests.nested_struct_field_in_a_nested_struct_field(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + .description = "test peripheral", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const nested_struct_id = try db.create_struct(.{}); + const nested_nested_struct_id = try db.create_struct(.{}); + + const register_id = try db.create_register(nested_nested_struct_id, .{ + .name = "TEST_REGISTER", + .description = "test register", + .size_bits = 32, + .offset_bytes = 0, + }); + + try db.add_register_field(register_id, .{ + .name = "TEST_FIELD", + .description = "test field 1", + .size_bits = 1, + .offset_bits = 0, + }); + + try db.add_nested_struct_field(struct_id, .{ + .name = "TEST_NESTED", + .description = "test nested struct", + .offset_bytes = 0, + .struct_id = nested_struct_id, + }); + + try db.add_nested_struct_field(nested_struct_id, .{ + .name = "TEST_NESTED_NESTED", + .offset_bytes = 0, + .struct_id = nested_nested_struct_id, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3473,14 +4235,14 @@ test "gen.nested struct field in nested struct field" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; @@ -3511,16 +4273,61 @@ test "gen.nested struct field in nested struct field" { } test "gen.nested struct field next to register" { - var db = try tests.nested_struct_field_next_to_register(std.testing.allocator); + var db = try Database.create(std.testing.allocator); defer db.destroy(); + const peripheral_id = try db.create_peripheral(.{ + .name = "TEST_PERIPHERAL", + .description = "test peripheral", + }); + + const struct_id = try db.get_peripheral_struct(peripheral_id); + const nested_struct_id = try db.create_nested_struct(struct_id, .{ + .name = "TEST_NESTED_TYPE", + }); + + const register1_id = try db.create_register(nested_struct_id, .{ + .name = "TEST_REGISTER", + .description = "test register", + .size_bits = 32, + .offset_bytes = 0, + }); + + try db.add_register_field(register1_id, .{ + .name = "TEST_FIELD", + .description = "test field 1", + .size_bits = 1, + .offset_bits = 0, + }); + + try db.add_nested_struct_field(struct_id, .{ + .name = "TEST_NESTED", + .description = "test nested struct", + .offset_bytes = 0, + .struct_id = nested_struct_id, + }); + + const register2_id = try db.create_register(struct_id, .{ + .name = "TEST_REGISTER", + .description = "test register", + .size_bits = 32, + .offset_bytes = 4, + }); + + try db.add_register_field(register2_id, .{ + .name = "TEST_FIELD", + .description = "test field 1", + .size_bits = 1, + .offset_bits = 0, + }); + var buffer: std.Io.Writer.Allocating = .init(std.testing.allocator); defer buffer.deinit(); var vfs: VirtualFilesystem = .init(std.testing.allocator); defer vfs.deinit(); - try db.to_zig(vfs.dir(), .{}); + try db.to_zig(vfs.io(), vfs.root_dir(), .{}); try expect_output(&.{ .{ .path = "types.zig", @@ -3530,14 +4337,14 @@ test "gen.nested struct field next to register" { , }, .{ - .path = "peripherals.zig", + .path = "types/peripherals.zig", .content = \\pub const TEST_PERIPHERAL = @import("peripherals/TEST_PERIPHERAL.zig").TEST_PERIPHERAL; \\ , }, .{ - .path = "peripherals/TEST_PERIPHERAL.zig", + .path = "types/peripherals/TEST_PERIPHERAL.zig", .content = \\const microzig = @import("microzig"); \\const mmio = microzig.mmio; diff --git a/tools/regz/src/main.zig b/tools/regz/src/main.zig index 4a1cd79ad..53e945631 100644 --- a/tools/regz/src/main.zig +++ b/tools/regz/src/main.zig @@ -1,8 +1,9 @@ const std = @import("std"); -const clap = @import("clap"); -const xml = @import("xml.zig"); -const Database = @import("Database.zig"); -const FS_Directory = @import("FS_Directory.zig"); + +const regz = @import("regz"); +const Database = regz.Database; + +const xml = @import("xml"); const ArenaAllocator = std.heap.ArenaAllocator; const Allocator = std.mem.Allocator; @@ -12,8 +13,8 @@ pub const std_options = std.Options{ .log_level = .warn, }; -pub fn main() !void { - main_impl() catch |err| switch (err) { +pub fn main(init: std.process.Init) !void { + main_impl(init) catch |err| switch (err) { error.Explained => std.process.exit(1), else => return err, }; @@ -25,7 +26,7 @@ const Arguments = struct { input_path: ?[]const u8 = null, output_path: ?[:0]const u8 = null, device: ?[]const u8 = null, - patch_paths: std.ArrayList([]const u8) = .{}, + patch_paths: std.ArrayList([]const u8) = .empty, dump_path: ?[:0]const u8 = null, help: bool = false, @@ -62,12 +63,9 @@ fn print_usage(writer: *std.Io.Writer) !void { try writer.flush(); } -fn parse_args(allocator: Allocator) !Arguments { - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); - +fn parse_args(gpa: Allocator, io: std.Io, args: []const []const u8) !Arguments { var ret = Arguments{ - .allocator = allocator, + .allocator = gpa, }; errdefer ret.deinit(); @@ -77,7 +75,7 @@ fn parse_args(allocator: Allocator) !Arguments { ret.help = true; } else if (std.mem.eql(u8, args[i], "--db_dump_path")) { i += 1; - ret.dump_path = try allocator.dupeZ(u8, args[i]); + ret.dump_path = try gpa.dupeZ(u8, args[i]); } else if (std.mem.eql(u8, args[i], "--format")) { i += 1; if (i >= args.len) @@ -93,10 +91,10 @@ fn parse_args(allocator: Allocator) !Arguments { }; } else if (std.mem.eql(u8, args[i], "--output_path")) { i += 1; - ret.output_path = try allocator.dupeZ(u8, args[i]); + ret.output_path = try gpa.dupeZ(u8, args[i]); } else if (std.mem.eql(u8, args[i], "--device")) { i += 1; - ret.device = try allocator.dupe(u8, args[i]); + ret.device = try gpa.dupe(u8, args[i]); } else if (std.mem.eql(u8, args[i], "--patch_path")) { i += 1; try ret.append_patch_path(args[i]); @@ -104,7 +102,7 @@ fn parse_args(allocator: Allocator) !Arguments { std.log.err("Unknown argument '{s}'", .{args[i]}); var buf: [80]u8 = undefined; - var writer = std.fs.File.stderr().writer(&buf); + var writer = std.Io.File.stderr().writer(io, &buf); try print_usage(&writer.interface); return error.Explained; } else if (ret.input_path != null) { @@ -114,26 +112,25 @@ fn parse_args(allocator: Allocator) !Arguments { }); return error.Explained; } else { - ret.input_path = try allocator.dupe(u8, args[i]); + ret.input_path = try gpa.dupe(u8, args[i]); }; return ret; } -fn main_impl() anyerror!void { +fn main_impl(init: std.process.Init) anyerror!void { defer xml.cleanupParser(); - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); + const gpa = init.gpa; + const io = init.io; + const args_raw = try init.minimal.args.toSlice(init.arena.allocator()); - const allocator = gpa.allocator(); - - var args = try parse_args(allocator); + var args = try parse_args(gpa, io, args_raw); defer args.deinit(); if (args.help) { var buf: [80]u8 = undefined; - var writer = std.fs.File.stdout().writer(&buf); + var writer = std.Io.File.stdout().writer(io, &buf); try print_usage(&writer.interface); return; } @@ -146,12 +143,12 @@ fn main_impl() anyerror!void { return error.Explained; }; - var db = try Database.create_from_path(allocator, format, input_path, args.device); + var db = try Database.create_from_path(gpa, io, format, input_path, args.device); defer db.destroy(); for (args.patch_paths.items) |patch_path| { - const patch = try std.fs.cwd().readFileAllocOptions(allocator, patch_path, std.math.maxInt(u64), null, .@"1", 0); - defer allocator.free(patch); + const patch = try std.Io.Dir.cwd().readFileAllocOptions(io, patch_path, gpa, .unlimited, .@"1", 0); + defer gpa.free(patch); var diags: std.zon.parse.Diagnostics = .{}; defer diags.deinit(db.gpa); @@ -167,12 +164,9 @@ fn main_impl() anyerror!void { // arch dependent stuff { - var arena = ArenaAllocator.init(allocator); - defer arena.deinit(); - - for (try db.get_devices(arena.allocator())) |device| { + for (try db.get_devices(init.arena.allocator())) |device| { if (device.arch.is_arm()) { - const arm = @import("arch/arm.zig"); + const arm = regz.arm; try arm.load_system_interrupts(db, device.id, device.arch); } } @@ -182,9 +176,8 @@ fn main_impl() anyerror!void { try db.backup(dump_path); } // output_path is the directory to write files - var output_dir = try std.fs.cwd().makeOpenPath(output_path, .{}); - defer output_dir.close(); + var output_dir = try std.Io.Dir.cwd().createDirPathOpen(io, output_path, .{}); + defer output_dir.close(io); - var fs = FS_Directory.init(output_dir); - try db.to_zig(fs.directory(), .{}); + try db.to_zig(io, output_dir, .{}); } diff --git a/tools/regz/src/module.zig b/tools/regz/src/module.zig index afb4bbc8a..21c70d4f3 100644 --- a/tools/regz/src/module.zig +++ b/tools/regz/src/module.zig @@ -4,4 +4,12 @@ pub const arm = @import("arch/arm.zig"); pub const Patch = @import("patch.zig").Patch; pub const Arch = @import("arch.zig").Arch; pub const embassy = @import("embassy.zig"); -pub const VirtualFilesystem = @import("VirtualFilesystem.zig"); + +test { + _ = Database; + _ = Analysis; + _ = arm; + _ = Patch; + _ = Arch; + _ = embassy; +} diff --git a/tools/regz/src/output_tests.zig b/tools/regz/src/output_tests.zig deleted file mode 100644 index 2de4e25a5..000000000 --- a/tools/regz/src/output_tests.zig +++ /dev/null @@ -1,960 +0,0 @@ -//! Common test conditions for code generation and regzon -const std = @import("std"); -const Allocator = std.mem.Allocator; - -const Database = @import("Database.zig"); - -pub fn peripheral_type_with_register_and_field(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - .description = "test peripheral", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .description = "test register", - .size_bits = 32, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .description = "test field", - .size_bits = 1, - .offset_bits = 0, - }); - - return db; -} - -pub fn peripheral_instantiation(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - const struct_id = try db.get_peripheral_struct(peripheral_id); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 32, - .offset_bytes = 0, - .reset_mask = 0x1, - .reset_value = 0x1, - }); - - _ = try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 1, - .offset_bits = 0, - }); - - const device_id = try db.create_device(.{ - .name = "TEST_DEVICE", - .arch = .cortex_m0, - }); - - _ = try db.create_device_peripheral(device_id, .{ - .name = "TEST0", - .offset_bytes = 0x1000, - .struct_id = struct_id, - }); - - return db; -} - -pub fn peripherals_with_shared_type(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 32, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 1, - .offset_bits = 0, - }); - - const device_id = try db.create_device(.{ - .name = "TEST_DEVICE", - .arch = .cortex_m0, - }); - - _ = try db.create_device_peripheral( - device_id, - .{ - .name = "TEST0", - .offset_bytes = 0x1000, - .struct_id = struct_id, - }, - ); - _ = try db.create_device_peripheral( - device_id, - .{ - .name = "TEST1", - .offset_bytes = 0x2000, - .struct_id = struct_id, - }, - ); - - return db; -} - -pub fn peripheral_with_modes(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ .name = "TEST_PERIPHERAL" }); - const struct_id = try db.get_peripheral_struct(peripheral_id); - const register1_id = try db.create_register( - struct_id, - .{ .name = "TEST_REGISTER1", .size_bits = 32, .offset_bytes = 0 }, - ); - const register2_id = try db.create_register( - struct_id, - .{ .name = "TEST_REGISTER2", .size_bits = 32, .offset_bytes = 0 }, - ); - const common_reg_id = try db.create_register( - struct_id, - .{ .name = "COMMON_REGISTER", .size_bits = 32, .offset_bytes = 4 }, - ); - - try db.add_register_field(common_reg_id, .{ - .name = "TEST_FIELD", - .size_bits = 1, - .offset_bits = 0, - }); - - const mode1_id = try db.create_mode(struct_id, .{ - .name = "TEST_MODE1", - .value = "0x00", - .qualifier = "TEST_PERIPHERAL.TEST_MODE1.COMMON_REGISTER.TEST_FIELD", - }); - const mode2_id = try db.create_mode(struct_id, .{ - .name = "TEST_MODE2", - .value = "0x01", - .qualifier = "TEST_PERIPHERAL.TEST_MODE2.COMMON_REGISTER.TEST_FIELD", - }); - - try db.add_register_mode(register1_id, mode1_id); - try db.add_register_mode(register2_id, mode2_id); - - return db; -} - -pub fn peripheral_with_enum(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - const enum_id = try db.create_enum(struct_id, .{ - .name = "TEST_ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - _ = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - }); - - return db; -} - -pub fn peripheral_with_enum_and_its_exhausted_of_values(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const enum_id = try db.create_enum(struct_id, .{ - .name = "TEST_ENUM", - .size_bits = 1, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - _ = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - }); - - return db; -} - -pub fn field_with_named_enum(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const enum_id = try db.create_enum(struct_id, .{ - .name = "TEST_ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum_id, - }); - - return db; -} - -pub fn field_with_named_enum_and_named_default(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const enum_id = try db.create_enum(struct_id, .{ - .name = "TEST_ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - .reset_mask = 0xF, - .reset_value = 0x1, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum_id, - }); - - return db; -} - -pub fn field_with_anonymous_enum(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const enum_id = try db.create_enum(null, .{ - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum_id, - }); - - return db; -} - -pub fn field_with_anonymous_enum_and_default(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const enum_id = try db.create_enum(null, .{ - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - .reset_mask = 0xF, - .reset_value = 0x1, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum_id, - }); - - return db; -} - -pub fn namespaced_register_groups(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - // peripheral - const peripheral_id = try db.create_peripheral(.{ - .name = "PORT", - }); - const struct_id = try db.get_peripheral_struct(peripheral_id); - - // register_groups - const portb_group_id = try db.create_nested_struct(struct_id, .{ .name = "PORTB" }); - const portc_group_id = try db.create_nested_struct(struct_id, .{ .name = "PORTC" }); - - // registers - _ = try db.create_register(portb_group_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0 }); - _ = try db.create_register(portb_group_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 1 }); - _ = try db.create_register(portb_group_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 2 }); - _ = try db.create_register(portc_group_id, .{ .name = "PORTC", .size_bits = 8, .offset_bytes = 0 }); - _ = try db.create_register(portc_group_id, .{ .name = "DDRC", .size_bits = 8, .offset_bytes = 1 }); - _ = try db.create_register(portc_group_id, .{ .name = "PINC", .size_bits = 8, .offset_bytes = 2 }); - - // device - const device_id = try db.create_device(.{ .name = "ATmega328P", .arch = .avr8 }); - - // instances - _ = try db.create_device_peripheral(device_id, .{ - .name = "PORTB", - .offset_bytes = 0x23, - .struct_id = portb_group_id, - }); - - _ = try db.create_device_peripheral(device_id, .{ - .name = "PORTC", - .offset_bytes = 0x26, - .struct_id = portc_group_id, - }); - - return db; -} - -pub fn peripheral_with_reserved_register(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "PORTB", - }); - const struct_id = try db.get_peripheral_struct(peripheral_id); - - _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 32, .offset_bytes = 0 }); - _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 32, .offset_bytes = 8 }); - - const device_id = try db.create_device(.{ - .name = "ATmega328P", - .arch = .avr8, - }); - - _ = try db.create_device_peripheral(device_id, .{ - .name = "PORTB", - .offset_bytes = 0x23, - .struct_id = struct_id, - }); - - return db; -} - -pub fn peripheral_with_count(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const device_id = try db.create_device(.{ .name = "ATmega328P", .arch = .avr8 }); - - const peripheral_id = try db.create_peripheral(.{ - .name = "PORTB", - .size_bytes = 3, - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - _ = try db.create_device_peripheral(device_id, .{ - .name = "PORTB", - .offset_bytes = 0x23, - .count = 4, - .struct_id = struct_id, - }); - - _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0 }); - _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 1 }); - _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 2 }); - - return db; -} - -pub fn peripheral_with_count_padding_required(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const device_id = try db.create_device(.{ .name = "ATmega328P", .arch = .avr8 }); - - const peripheral_id = try db.create_peripheral(.{ - .name = "PORTB", - .size_bytes = 4, - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - _ = try db.create_device_peripheral(device_id, .{ - .name = "PORTB", - .offset_bytes = 0x23, - .count = 4, - .struct_id = struct_id, - }); - - _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0 }); - _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 1 }); - _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 2 }); - - return db; -} - -pub fn register_with_count(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const device_id = try db.create_device(.{ - .name = "ATmega328P", - .arch = .avr8, - }); - - const peripheral_id = try db.create_peripheral(.{ - .name = "PORTB", - }); - const struct_id = try db.get_peripheral_struct(peripheral_id); - - _ = try db.create_device_peripheral(device_id, .{ - .name = "PORTB", - .offset_bytes = 0x23, - .struct_id = struct_id, - }); - - _ = try db.create_register(struct_id, .{ .name = "PORTB", .size_bits = 8, .offset_bytes = 0, .count = 4 }); - _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 4 }); - _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 5 }); - - return db; -} - -pub fn register_with_count_and_fields(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const device_id = try db.create_device(.{ - .name = "ATmega328P", - .arch = .avr8, - }); - - const peripheral_id = try db.create_peripheral(.{ - .name = "PORTB", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - _ = try db.create_device_peripheral(device_id, .{ - .name = "PORTB", - .offset_bytes = 0x23, - .struct_id = struct_id, - }); - - const portb_id = try db.create_register(struct_id, .{ - .name = "PORTB", - .size_bits = 8, - .offset_bytes = 0, - .count = 4, - }); - - _ = try db.create_register(struct_id, .{ .name = "DDRB", .size_bits = 8, .offset_bytes = 4 }); - _ = try db.create_register(struct_id, .{ .name = "PINB", .size_bits = 8, .offset_bytes = 5 }); - - try db.add_register_field(portb_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - }); - - return db; -} - -pub fn field_with_count_width_of_one_offset_and_padding(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "PORTB", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - const portb_id = try db.create_register(struct_id, .{ - .name = "PORTB", - .size_bits = 8, - .offset_bytes = 0, - }); - - inline for (0..5) |i| { - const suffix = std.fmt.comptimePrint("{d}", .{i}); - try db.add_register_field(portb_id, .{ - .name = "TEST_FIELD" ++ suffix, - .size_bits = 1, - .offset_bits = 2 + i, - }); - } - - return db; -} - -pub fn field_with_count_multi_bit_width_offset_and_padding(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "PORTB", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - const portb_id = try db.create_register(struct_id, .{ - .name = "PORTB", - .size_bits = 8, - .offset_bytes = 0, - }); - - inline for (0..2) |i| { - const suffix = std.fmt.comptimePrint("{d}", .{i}); - try db.add_register_field(portb_id, .{ - .name = "TEST_FIELD" ++ suffix, - .size_bits = 2, - .offset_bits = 2 + (i * 2), - }); - } - - return db; -} - -pub fn interrupts_avr(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const device_id = try db.create_device(.{ - .name = "ATmega328P", - .arch = .avr8, - }); - - _ = try db.create_interrupt(device_id, .{ - .name = "TEST_VECTOR1", - .idx = 1, - }); - - _ = try db.create_interrupt(device_id, .{ - .name = "TEST_VECTOR2", - .idx = 3, - }); - - return db; -} - -pub fn enums_with_name_collision(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const enum1_id = try db.create_enum(struct_id, .{ - .name = "ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum1_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum1_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - const enum2_id = try db.create_enum(struct_id, .{ - .name = "ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum2_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum2_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD1", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum1_id, - }); - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD2", - .size_bits = 4, - .offset_bits = 4, - .enum_id = enum2_id, - }); - - return db; -} - -pub fn field_with_named_enum_and_unnamed_default(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const enum_id = try db.create_enum(struct_id, .{ - .name = "TEST_ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 1 }); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - .reset_mask = 0xF, - .reset_value = 0xA, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum_id, - }); - - return db; -} - -pub fn enum_with_value_collision(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const enum_id = try db.create_enum(null, .{ - .name = "ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD2", .value = 0 }); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum_id, - }); - return db; -} - -pub fn enum_fields_with_name_collision(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const enum_id = try db.create_enum(null, .{ - .name = "ENUM", - .size_bits = 4, - }); - - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 0 }); - try db.add_enum_field(enum_id, .{ .name = "TEST_ENUM_FIELD1", .value = 1 }); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .size_bits = 8, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .size_bits = 4, - .offset_bits = 0, - .enum_id = enum_id, - }); - return db; -} - -pub fn register_fields_with_name_collision(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - .description = "test peripheral", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - - const register_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .description = "test register", - .size_bits = 32, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .description = "test field 1", - .size_bits = 1, - .offset_bits = 0, - }); - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .description = "test field 2", - .size_bits = 1, - .offset_bits = 1, - }); - - return db; -} - -pub fn nested_struct_field_in_a_peripheral(allocator: Allocator, offset_bytes: u64) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - .description = "test peripheral", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const nested_struct_id = try db.create_struct(.{}); - - const register_id = try db.create_register(nested_struct_id, .{ - .name = "TEST_REGISTER", - .description = "test register", - .size_bits = 32, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .description = "test field 1", - .size_bits = 1, - .offset_bits = 0, - }); - - try db.add_nested_struct_field(struct_id, .{ - .name = "TEST_NESTED", - .description = "test nested struct", - .offset_bytes = offset_bytes, - .struct_id = nested_struct_id, - }); - - return db; -} - -pub fn nested_struct_field_in_a_peripheral_that_has_a_named_type(allocator: Allocator, offset_bytes: u64) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - .description = "test peripheral", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const nested_struct_id = try db.create_nested_struct(struct_id, .{ - .name = "TEST_NESTED_TYPE", - }); - - const register_id = try db.create_register(nested_struct_id, .{ - .name = "TEST_REGISTER", - .description = "test register", - .size_bits = 32, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .description = "test field 1", - .size_bits = 1, - .offset_bits = 0, - }); - - try db.add_nested_struct_field(struct_id, .{ - .name = "TEST_NESTED", - .description = "test nested struct", - .offset_bytes = offset_bytes, - .struct_id = nested_struct_id, - }); - - return db; -} - -pub fn nested_struct_field_in_a_nested_struct_field(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - .description = "test peripheral", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const nested_struct_id = try db.create_struct(.{}); - const nested_nested_struct_id = try db.create_struct(.{}); - - const register_id = try db.create_register(nested_nested_struct_id, .{ - .name = "TEST_REGISTER", - .description = "test register", - .size_bits = 32, - .offset_bytes = 0, - }); - - try db.add_register_field(register_id, .{ - .name = "TEST_FIELD", - .description = "test field 1", - .size_bits = 1, - .offset_bits = 0, - }); - - try db.add_nested_struct_field(struct_id, .{ - .name = "TEST_NESTED", - .description = "test nested struct", - .offset_bytes = 0, - .struct_id = nested_struct_id, - }); - - try db.add_nested_struct_field(nested_struct_id, .{ - .name = "TEST_NESTED_NESTED", - .offset_bytes = 0, - .struct_id = nested_nested_struct_id, - }); - - return db; -} - -pub fn nested_struct_field_next_to_register(allocator: Allocator) !*Database { - var db = try Database.create(allocator); - errdefer db.destroy(); - - const peripheral_id = try db.create_peripheral(.{ - .name = "TEST_PERIPHERAL", - .description = "test peripheral", - }); - - const struct_id = try db.get_peripheral_struct(peripheral_id); - const nested_struct_id = try db.create_nested_struct(struct_id, .{ - .name = "TEST_NESTED_TYPE", - }); - - const register1_id = try db.create_register(nested_struct_id, .{ - .name = "TEST_REGISTER", - .description = "test register", - .size_bits = 32, - .offset_bytes = 0, - }); - - try db.add_register_field(register1_id, .{ - .name = "TEST_FIELD", - .description = "test field 1", - .size_bits = 1, - .offset_bits = 0, - }); - - try db.add_nested_struct_field(struct_id, .{ - .name = "TEST_NESTED", - .description = "test nested struct", - .offset_bytes = 0, - .struct_id = nested_struct_id, - }); - - const register2_id = try db.create_register(struct_id, .{ - .name = "TEST_REGISTER", - .description = "test register", - .size_bits = 32, - .offset_bytes = 4, - }); - - try db.add_register_field(register2_id, .{ - .name = "TEST_FIELD", - .description = "test field 1", - .size_bits = 1, - .offset_bits = 0, - }); - - return db; -} diff --git a/tools/regz/src/svd.zig b/tools/regz/src/svd.zig index 050b691f0..983325164 100644 --- a/tools/regz/src/svd.zig +++ b/tools/regz/src/svd.zig @@ -3,7 +3,7 @@ const ArenaAllocator = std.heap.ArenaAllocator; const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const xml = @import("xml.zig"); +const xml = @import("xml"); const Arch = @import("arch.zig").Arch; const Database = @import("Database.zig"); @@ -746,7 +746,7 @@ const DimElements = struct { pattern: []const u8, fn expand(list: *const List, gpa: Allocator) ![]const []const u8 { - var ret: std.ArrayList([]const u8) = .{}; + var ret: std.ArrayList([]const u8) = .empty; defer ret.deinit(gpa); if (std.mem.indexOf(u8, list.pattern, "-")) |dash_idx| { diff --git a/tools/regz/src/targetdb.zig b/tools/regz/src/targetdb.zig index ade6d1796..ff2bbd804 100644 --- a/tools/regz/src/targetdb.zig +++ b/tools/regz/src/targetdb.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const xml = @import("xml.zig"); +const xml = @import("xml"); const Database = @import("Database.zig"); const DeviceID = Database.DeviceID; @@ -34,12 +34,12 @@ fn parse_isa_to_arch(isa: []const u8) Arch { return .unknown; } -pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void { - var targetdb_dir = try std.fs.cwd().openDir(path, .{}); - defer targetdb_dir.close(); +pub fn load_into_db(db: *Database, io: std.Io, path: []const u8, device: ?[]const u8) !void { + var targetdb_dir = try std.Io.Dir.cwd().openDir(io, path, .{}); + defer targetdb_dir.close(io); - var devices_dir = try targetdb_dir.openDir("devices", .{ .iterate = true }); - defer devices_dir.close(); + var devices_dir = try targetdb_dir.openDir(io, "devices", .{ .iterate = true }); + defer devices_dir.close(io); var modules = std.StringHashMap(ModuleEntry).init(db.gpa); defer { @@ -51,7 +51,7 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void } var it = devices_dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) continue; @@ -60,22 +60,25 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void if (device) |d| { if (std.mem.eql(u8, d, entry.name[0 .. entry.name.len - ".xml".len])) { - try load_device(db, devices_dir, entry.name, &modules); + try load_device(db, io, devices_dir, entry.name, &modules); return; } } else { - try load_device(db, devices_dir, entry.name, &modules); + try load_device(db, io, devices_dir, entry.name, &modules); } } else if (device != null) { return error.DeviceMissing; } } -fn load_device(db: *Database, devices_dir: std.fs.Dir, filename: []const u8, modules: *std.StringHashMap(ModuleEntry)) !void { - const device_file = try devices_dir.openFile(filename, .{}); - defer device_file.close(); - - const device_text = try device_file.readToEndAlloc(db.gpa, 1024 * 1024); +fn load_device( + db: *Database, + io: std.Io, + devices_dir: std.Io.Dir, + filename: []const u8, + modules: *std.StringHashMap(ModuleEntry), +) !void { + const device_text = try devices_dir.readFileAlloc(io, filename, db.gpa, @enumFromInt(1024 * 1024)); defer db.gpa.free(device_text); var doc = try xml.Doc.from_memory(device_text); @@ -125,11 +128,18 @@ fn load_device(db: *Database, devices_dir: std.fs.Dir, filename: []const u8, mod var instance_it = cpu_node.iterate(&.{}, &.{"instance"}); while (instance_it.next()) |instance_node| { - try load_instance(db, device_id, devices_dir, instance_node, modules); + try load_instance(db, io, device_id, devices_dir, instance_node, modules); } } -fn load_instance(db: *Database, device_id: DeviceID, devices_dir: std.fs.Dir, node: xml.Node, modules: *std.StringHashMap(ModuleEntry)) !void { +fn load_instance( + db: *Database, + io: std.Io, + device_id: DeviceID, + devices_dir: std.Io.Dir, + node: xml.Node, + modules: *std.StringHashMap(ModuleEntry), +) !void { const name = node.get_attribute("id") orelse return error.MissingField; const href = node.get_attribute("href") orelse return error.MissingField; @@ -145,10 +155,7 @@ fn load_instance(db: *Database, device_id: DeviceID, devices_dir: std.fs.Dir, no // Load the module file for the first time log.debug("Loading new peripheral type from module file: {s}", .{href}); - const module_file = try devices_dir.openFile(href, .{}); - defer module_file.close(); - - const module_text = try module_file.readToEndAlloc(db.gpa, 1024 * 1024); + const module_text = try devices_dir.readFileAlloc(io, href, db.gpa, @enumFromInt(1024 * 1024)); defer db.gpa.free(module_text); var doc = try xml.Doc.from_memory(module_text); From b5be5c4dc8c6c59751e6b61271d2c96a250f62fa Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 24 May 2026 14:53:00 -0700 Subject: [PATCH 03/61] Remove port cache --- build.zig | 63 +++++++++++++------------------------------------------ 1 file changed, 14 insertions(+), 49 deletions(-) diff --git a/build.zig b/build.zig index 1bd992833..c5b7461b2 100644 --- a/build.zig +++ b/build.zig @@ -100,32 +100,6 @@ pub const PortSelect = struct { } }; -// Don't know if this is required but it doesn't hurt either. -// Helps in case there are multiple microzig instances including the same ports (eg: examples). -pub const PortCache = blk: { - var fields: []const std.builtin.Type.StructField = &.{}; - for (port_list) |port| { - const typ = ?(custom_lazy_import(port.dep_name) orelse struct {}); - fields = fields ++ [_]std.builtin.Type.StructField{.{ - .name = port.name, - .type = typ, - .default_value_ptr = @as(*const anyopaque, @ptrCast(&@as(typ, null))), - .is_comptime = false, - .alignment = @alignOf(typ), - }}; - } - break :blk @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = fields, - .decls = &.{}, - .is_tuple = false, - }, - }); -}; - -var port_cache: PortCache = .{}; - /// The MicroZig build system. /// /// # Example usage: @@ -165,29 +139,23 @@ pub fn MicroBuild(port_select: PortSelect) type { const Self = @This(); const SelectedPorts = blk: { - var fields: []const std.builtin.Type.StructField = &.{}; - - for (port_list) |port| { + var field_names: [port_list.len][]const u8 = undefined; + var field_types: [port_list.len]type = undefined; + var field_attrs: [port_list.len]std.builtin.Type.StructField.Attributes = undefined; + for (port_list, 0..) |port, i| { if (@field(port_select, port.name)) { const typ = custom_lazy_import(port.dep_name) orelse struct {}; - fields = fields ++ [_]std.builtin.Type.StructField{.{ - .name = port.name, - .type = typ, + + field_names[i] = port.name; + field_types[i] = typ; + field_attrs[i] = .{ + .alignment = @alignOf(type), .default_value_ptr = null, - .is_comptime = false, - .alignment = @alignOf(typ), - }}; + }; } } - break :blk @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = fields, - .decls = &.{}, - .is_tuple = false, - }, - }); + break :blk @Struct(.auto, null, field_names, field_types, field_attrs); }; const InitReturnType = blk: { @@ -221,12 +189,9 @@ pub fn MicroBuild(port_select: PortSelect) type { var ports: SelectedPorts = undefined; inline for (port_list) |port| { if (@field(port_select, port.name)) { - @field(ports, port.name) = if (@field(port_cache, port.name)) |cached_port| cached_port else blk: { - const port_dep = dep.builder.lazyDependency(port.dep_name, .{}).?; - const instance = custom_lazy_import(port.dep_name).?.init(port_dep); - @field(port_cache, port.name) = instance; - break :blk instance; - }; + const port_dep = dep.builder.lazyDependency(port.dep_name, .{}).?; + @field(ports, port.name) = + custom_lazy_import(port.dep_name).?.init(port_dep); } } From c8deae41ffe812c61f50b9156b819d2c064ecad3 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 24 May 2026 21:16:31 -0700 Subject: [PATCH 04/61] Aviron moved to 0.16.0 That being said, I'm seeing the following from the build output. It seems to be a compiler bug: error: error: Alias and aliasee types don't match (Producer: 'zig 0.16.0' Reader: 'LLVM 21.1.0') --- sim/aviron/build.zig | 62 ++-- sim/aviron/build.zig.zon | 4 - sim/aviron/src/lib/bus.zig | 36 ++ sim/aviron/src/main.zig | 325 ++++++++++-------- sim/aviron/src/testconfig.zig | 4 +- sim/aviron/src/testrunner.zig | 50 +-- ...enerate-tables.zig => generate_tables.zig} | 83 +++-- 7 files changed, 318 insertions(+), 246 deletions(-) rename sim/aviron/tools/{generate-tables.zig => generate_tables.zig} (68%) diff --git a/sim/aviron/build.zig b/sim/aviron/build.zig index 388b4bfa5..f7269bb12 100644 --- a/sim/aviron/build.zig +++ b/sim/aviron/build.zig @@ -28,11 +28,9 @@ pub fn build(b: *Build) !void { ); // Deps - const args_dep = b.dependency("args", .{}); const ihex_dep = b.dependency("ihex", .{}); // Dep modules - const args_module = args_dep.module("args"); const ihex_module = ihex_dep.module("ihex"); // Options @@ -69,7 +67,6 @@ pub fn build(b: *Build) !void { }), .use_llvm = true, }); - aviron_exe.root_module.addImport("args", args_module); aviron_exe.root_module.addImport("ihex", ihex_module); aviron_exe.root_module.addImport("aviron", aviron_module); b.installArtifact(aviron_exe); @@ -110,7 +107,7 @@ pub fn build(b: *Build) !void { // Set up test scanning - this reads existing JSON files and runs tests // Only set up if we're not exclusively running update-testsuite - try add_test_suite(b, test_step, debug_testsuite_step, target, avr_target, optimize, args_module, aviron_module); + try add_test_suite(b, test_step, debug_testsuite_step, target, avr_target, optimize, aviron_module); } fn add_test_suite( @@ -120,7 +117,6 @@ fn add_test_suite( host_target: ResolvedTarget, avr_target: ResolvedTarget, optimize: std.builtin.OptimizeMode, - args_module: *Build.Module, aviron_module: *Build.Module, ) !void { const unit_tests = b.addTest(.{ @@ -153,21 +149,22 @@ fn add_test_suite( }), .use_llvm = true, }); - testrunner_exe.root_module.addImport("args", args_module); testrunner_exe.root_module.addImport("aviron", aviron_module); debug_step.dependOn(&b.addInstallArtifact(testrunner_exe, .{}).step); + const io = b.graph.io; + // Scan the testsuite directory for files. Based on the extension, either load or compile them. // Files in testsuite.avr-gcc will be compiled with avr-gcc and have the output copied to // this directory. - var walkdir = try b.build_root.handle.openDir("testsuite", .{ .iterate = true }); - defer walkdir.close(); + var walkdir = try b.build_root.handle.openDir(io, "testsuite", .{ .iterate = true }); + defer walkdir.close(io); var walker = try walkdir.walk(b.allocator); defer walker.deinit(); - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; @@ -217,8 +214,8 @@ fn add_test_suite( .ignore => continue, .compile => blk: { - var file = try entry.dir.openFile(entry.basename, .{}); - defer file.close(); + var file = try entry.dir.openFile(io, entry.basename, .{}); + defer file.close(io); const config = try parse_test_suite_config(b, file); @@ -254,7 +251,7 @@ fn add_test_suite( }), .use_llvm = true, }); - test_payload.want_lto = false; // AVR has no LTO support! + test_payload.lto = .none; // AVR has no LTO support! test_payload.verbose_link = true; test_payload.verbose_cc = true; test_payload.bundle_compiler_rt = false; @@ -262,16 +259,16 @@ fn add_test_suite( test_payload.setLinkerScript(b.path("linker.ld")); if (is_c_test or is_asm_test) { - test_payload.addIncludePath(b.path("testsuite")); + test_payload.root_module.addIncludePath(b.path("testsuite")); } if (is_c_test) { - test_payload.addCSourceFile(.{ + test_payload.root_module.addCSourceFile(.{ .file = source_file, .flags = &.{}, }); } if (is_asm_test) { - test_payload.addAssemblyFile(source_file); + test_payload.root_module.addAssemblyFile(source_file); } if (is_zig_test) { test_payload.root_module.addAnonymousImport("testsuite", .{ @@ -294,9 +291,9 @@ fn add_test_suite( }, .load => blk: { const config_path = b.fmt("{s}.json", .{entry.basename}); - const config = if (entry.dir.openFile(config_path, .{})) |file| cfg: { - defer file.close(); - break :cfg try TestSuiteConfig.load(b.allocator, file); + const config = if (entry.dir.openFile(io, config_path, .{})) |file| cfg: { + defer file.close(io); + break :cfg try TestSuiteConfig.load(b.allocator, io, file); } else |_| { // If JSON file doesn't exist, skip this test (likely during testsuite update) std.log.warn("Skipping test {s} - JSON config file {s} not found (run 'zig build update-testsuite' first)", .{ entry.path, config_path }); @@ -347,13 +344,14 @@ fn add_test_suite_update( .use_llvm = true, }).getEmittedBin(); - var walkdir = try b.build_root.handle.openDir("testsuite.avr-gcc", .{ .iterate = true }); - defer walkdir.close(); + const io = b.graph.io; + var walkdir = try b.build_root.handle.openDir(io, "testsuite.avr-gcc", .{ .iterate = true }); + defer walkdir.close(io); var walker = try walkdir.walk(b.allocator); defer walker.deinit(); - while (try walker.next()) |entry| { + while (try walker.next(io)) |entry| { if (entry.kind != .file) continue; @@ -389,8 +387,8 @@ fn add_test_suite_update( .ignore => continue, .compile => { - var file = try entry.dir.openFile(entry.basename, .{}); - defer file.close(); + var file = try entry.dir.openFile(io, entry.basename, .{}); + defer file.close(io); const config = try parse_test_suite_config(b, file); @@ -447,22 +445,20 @@ fn add_test_suite_update( } } -fn parse_test_suite_config(b: *Build, file: std.fs.File) !TestSuiteConfig { +fn parse_test_suite_config(b: *Build, file: std.Io.File) !TestSuiteConfig { + const io = b.graph.io; var code = std.array_list.Managed(u8).init(b.allocator); defer code.deinit(); var read_buf: [4096]u8 = undefined; - var file_reader = file.reader(&read_buf); + var file_reader = file.reader(io, &read_buf); const reader = &file_reader.interface; while (true) { - const line = reader.takeDelimiterExclusive('\n') catch |err| switch (err) { - error.EndOfStream => break, - else => |e| return e, - }; - - if (std.mem.startsWith(u8, line, "//!")) { - try code.appendSlice(line[3..]); + const comment_prefix = "//!"; + const line = try reader.takeDelimiter('\n') orelse break; + if (std.mem.startsWith(u8, line, comment_prefix)) { + try code.appendSlice(line[comment_prefix.len..]); try code.appendSlice("\n"); } } @@ -486,7 +482,7 @@ fn generate_isa_tables(b: *Build, isa_mod: *Build.Module) LazyPath { const generate_tables_exe = b.addExecutable(.{ .name = "aviron-generate-tables", .root_module = b.createModule(.{ - .root_source_file = b.path("tools/generate-tables.zig"), + .root_source_file = b.path("tools/generate_tables.zig"), .target = b.graph.host, .optimize = .Debug, .imports = &.{ diff --git a/sim/aviron/build.zig.zon b/sim/aviron/build.zig.zon index c7075f7cc..9017fdc41 100644 --- a/sim/aviron/build.zig.zon +++ b/sim/aviron/build.zig.zon @@ -3,10 +3,6 @@ .version = "0.1.0", .fingerprint = 0xfc536f957aeaeb54, .dependencies = .{ - .args = .{ - .url = "git+https://github.com/MasterQ32/zig-args#8ae26b44a884ff20dca98ee84c098e8f8e94902f", - .hash = "args-0.0.0-CiLiqojRAACGzDRO7A9dw7kWSchNk29caJZkXuMCb0Cn", - }, .@"bounded-array" = .{ .path = "../../modules/bounded-array" }, .ihex = .{ .url = "git+https://github.com/mattnite/zig-ihex#9deb291104ecd7dcaab0db27bf05252764600947", diff --git a/sim/aviron/src/lib/bus.zig b/sim/aviron/src/lib/bus.zig index 497e0f2a1..70e412d14 100644 --- a/sim/aviron/src/lib/bus.zig +++ b/sim/aviron/src/lib/bus.zig @@ -57,6 +57,42 @@ pub const Flash = struct { } }; } + + pub const Allocated = struct { + gpa: std.mem.Allocator, + data: []u8 align(2), + + pub fn init(gpa: std.mem.Allocator, size: usize) !Allocated { + if ((size & 1) != 0) + return error.InvalidDataSize; + + const data = try gpa.allocWithOptions(u8, size, .@"2", null); + return .{ + .gpa = gpa, + .data = data, + }; + } + + pub fn deinit(self: *Allocated) void { + self.gpa.free(self.data); + } + + pub fn memory(self: *Allocated) Flash { + return Flash{ + .ctx = self, + .vtable = &.{ + .mem_read = mem_read, + }, + .size = @divExact(self.data.len, 2), + }; + } + + pub fn mem_read(ctx: ?*anyopaque, addr: Address) Error!u16 { + const mem: *Allocated = @ptrCast(@alignCast(ctx.?)); + if (addr >= @as(Address, @intCast(@divExact(mem.data.len, 2)))) return error.InvalidAddress; + return std.mem.bytesAsSlice(u16, &mem.data)[addr]; + } + }; }; pub const IO = struct { diff --git a/sim/aviron/src/main.zig b/sim/aviron/src/main.zig index 7c74fd566..d124dc300 100644 --- a/sim/aviron/src/main.zig +++ b/sim/aviron/src/main.zig @@ -1,21 +1,32 @@ const std = @import("std"); const builtin = @import("builtin"); const aviron = @import("aviron"); -const args_parser = @import("args"); const ihex = @import("ihex"); +const log = std.log.scoped(.main); + +const RunWith_MCU_Options = struct { + trace: bool = false, + info: bool = false, + format: FileFormat = .elf, + gas: ?u64 = null, + breakpoint: ?u24 = null, +}; + fn run_with_mcu( - allocator: std.mem.Allocator, - comptime mcu_config: anytype, - options: Cli, + gpa: std.mem.Allocator, + io: std.Io, + comptime mcu_config: aviron.mcu.Config, positionals: []const []const u8, + options: RunWith_MCU_Options, ) !u8 { // Allocate memory based on MCU configuration - var flash_storage = aviron.Flash.Static(mcu_config.flash_size){}; + var flash_storage: aviron.Flash.Static(mcu_config.flash_size) = .{}; var sram = aviron.FixedSizeMemory(mcu_config.sram_size, .{ .address_type = u24 }){}; // TODO: Add support for reading/writing EEPROM through IO - var io = IO{ + var bus_io = IO{ + .io = io, .sreg = undefined, .sp = mcu_config.sram_base + mcu_config.sram_size - 1, }; @@ -24,12 +35,12 @@ fn run_with_mcu( const flash_mem = flash_storage.memory(); // Build Bus interfaces - const io_data_bus = io.bus(); // For memory-mapped data space - const io_io_bus = io.io_bus(); // For direct IO operations + const io_data_bus = bus_io.bus(); // For memory-mapped data space + const io_io_bus = bus_io.io_bus(); // For direct IO operations const sram_bus = sram.bus(); - var spaces = try aviron.mcu.build_spaces(allocator, mcu_config, sram_bus, io_data_bus); - defer spaces.deinit(allocator); + var spaces = try aviron.mcu.build_spaces(gpa, mcu_config, sram_bus, io_data_bus); + defer spaces.deinit(gpa); var cpu = aviron.Cpu{ .trace = options.trace, @@ -46,11 +57,11 @@ fn run_with_mcu( .sio = mcu_config.special_io, }; - io.sreg = &cpu.sreg; + bus_io.sreg = &cpu.sreg; if (options.info) { - var stdout = std.fs.File.stdout().writer(&.{}); - try stdout.interface.print("Information for {s}:\n", .{@tagName(options.mcu)}); + var stdout = std.Io.File.stdout().writer(io, &.{}); + try stdout.interface.print("Information for {s}:\n", .{mcu_config.name}); try stdout.interface.print(" Generation: {s: >11}\n", .{@tagName(cpu.instruction_set)}); try stdout.interface.print(" Code Model: {s: >11}\n", .{@tagName(cpu.code_model)}); try stdout.interface.print(" Flash: {d: >5} bytes\n", .{cpu.flash.size}); @@ -62,12 +73,11 @@ fn run_with_mcu( // Load all provided executables: for (positionals) |file_path| { - var file = try std.fs.cwd().openFile(file_path, .{}); - defer file.close(); + var file = try std.Io.Dir.cwd().openFile(io, file_path, .{}); + defer file.close(io); var file_buf: [4096]u8 = undefined; - var reader = file.reader(&file_buf); - + var reader = file.reader(io, &file_buf); switch (options.format) { .elf => { var header = try std.elf.Header.read(&reader.interface); @@ -122,7 +132,7 @@ fn run_with_mcu( } }, .binary, .bin => { - const size = try file.readAll(&flash_storage.data); + const size = try reader.interface.readSliceShort(&flash_storage.data); @memset(flash_storage.data[size..], 0); }, .ihex, .hex => { @@ -137,44 +147,116 @@ fn run_with_mcu( } const result = try cpu.run(options.gas, options.breakpoint); - if (options.trace) { cpu.dump_system_state(); } std.debug.print("\nSTOP: {s}\n", .{@tagName(result)}); - - // Handle program exit if (result == .program_exit) { - return io.exit_code.?; + return bus_io.exit_code.?; } return 0; } -pub fn main() !u8 { - const allocator = std.heap.page_allocator; +const CLI_Args = struct { + help: bool = false, + trace: bool = false, + mcu: MCU = .atmega328p, + info: bool = false, + format: FileFormat = .elf, + breakpoint: ?u24 = null, + gas: ?u64 = null, - var cli = args_parser.parseForCurrentProcess(Cli, allocator, .print) catch return 1; - defer cli.deinit(); + const default: CLI_Args = .{}; - if (cli.options.help or (cli.positionals.len == 0 and !cli.options.info)) { - var stderr_writer = std.fs.File.stderr().writer(&.{}); - try args_parser.printHelp( - Cli, - cli.executable_name orelse "aviron", - &stderr_writer.interface, - ); + const usage = + \\[--help] [--trace] [--mcu=] [--info] [--format=] [--breakpoint=] [--gas=] ... + \\ + \\AViRon is a simulator for the AVR cpu architecture as well as an basic emulator for several microcontrollers from Microchip/Atmel. + \\ + \\Loads at least a single file into the memory of the system and executes it with the provided MCU. + \\ + \\The code can use certain special registers to perform I/O and exit the emulator. + \\ + \\It accepts the following arguments: + \\ + \\--help + \\--trace + \\--info + \\--mcu= + \\--format= + \\--breakpoint= + \\--gas= + \\ + ; +}; - return if (cli.options.help) @as(u8, 0) else 1; +fn parse_bool(str: []const u8) !bool { + return if (std.mem.eql(u8, str, "true")) + true + else if (std.mem.eql(u8, str, "false")) + false + else + error.InvalidBoolStr; +} + +pub fn main(init: std.process.Init) !u8 { + const gpa = init.gpa; + const args = try init.minimal.args.toSlice(init.arena.allocator()); + + var cli_args: CLI_Args = .default; + const positionals = for (args, 0..) |arg, i| { + if (!std.mem.startsWith(u8, arg, "--")) + break args[i..]; + + const equals = std.mem.findScalar(u8, arg, '='); + const key = arg[2 .. equals orelse arg.len]; + const value = arg[equals orelse arg.len .. arg.len]; + inline for (@typeInfo(CLI_Args).@"struct".fields) |field| { + if (std.mem.eql(u8, key, field.name)) { + @field(cli_args, field.name) = switch (field.type) { + bool => if (equals != null) + try parse_bool(value) + else + true, + + MCU, FileFormat => std.meta.stringToEnum(field.type, value) orelse { + log.err("Invalid value for --{s}: '{s}'", .{ key, value }); + return error.InvalidValue; + }, + ?u24 => try std.fmt.parseInt(u24, value, 0), + ?u64 => try std.fmt.parseInt(u64, value, 0), + else => unreachable, + }; + } + } + + log.err("Unrecognied CLI argument: --{s}", .{key}); + return error.UnrecognizedCliArgument; + } else &.{}; + + const io = init.io; + if (cli_args.help) { + var stdout = std.Io.File.stdout().writer(io, &.{}); + try stdout.interface.print("{s}", .{CLI_Args.usage}); + try stdout.interface.flush(); + return 0; } - // Dispatch to MCU-specific function - return switch (cli.options.mcu) { - .atmega328p => try run_with_mcu(allocator, aviron.mcu.atmega328p, cli.options, cli.positionals), - .attiny816 => try run_with_mcu(allocator, aviron.mcu.attiny816, cli.options, cli.positionals), - .atmega2560 => try run_with_mcu(allocator, aviron.mcu.atmega2560, cli.options, cli.positionals), - .xmega128a4u => try run_with_mcu(allocator, aviron.mcu.xmega128a4u, cli.options, cli.positionals), + const options: RunWith_MCU_Options = .{ + .trace = cli_args.trace, + .info = cli_args.info, + .format = cli_args.format, + .gas = cli_args.gas, + .breakpoint = cli_args.breakpoint, + }; + + return switch (cli_args.mcu) { + .atmega328p => try run_with_mcu(gpa, io, aviron.mcu.atmega328p, positionals, options), + .attiny816 => try run_with_mcu(gpa, io, aviron.mcu.attiny816, positionals, options), + .atmega2560 => try run_with_mcu(gpa, io, aviron.mcu.atmega2560, positionals, options), + .xmega128a4u => try run_with_mcu(gpa, io, aviron.mcu.xmega128a4u, positionals, options), }; } @@ -194,47 +276,8 @@ pub const FileFormat = enum { hex, }; -const Cli = struct { - help: bool = false, - trace: bool = false, - mcu: MCU = .atmega328p, - info: bool = false, - format: FileFormat = .elf, - breakpoint: ?u24 = null, - gas: ?u64 = null, - - pub const shorthands = .{ - .h = "help", - .t = "trace", - .m = "mcu", - .I = "info", - .f = "format", - .b = "breakpoint", - .g = "gas", - }; - pub const meta = .{ - .summary = "[-h] [-t] [-m ] ...", - .full_text = - \\AViRon is a simulator for the AVR cpu architecture as well as an basic emulator for several microcontrollers from Microchip/Atmel. - \\ - \\Loads at least a single file into the memory of the system and executes it with the provided MCU. - \\ - \\The code can use certain special registers to perform I/O and exit the emulator. - , - .option_docs = .{ - .help = "Prints this help text.", - .trace = "Trace all executed instructions.", - .mcu = "Selects the emulated MCU.", - .info = "Prints information about the given MCUs memory.", - .format = "Specify file format.", - .breakpoint = "Break when PC reaches this address (hex or dec)", - .dump_len = "Number of bytes to dump (default 32)", - .gas = "Stop after N instructions executed", - }, - }; -}; - const IO = struct { + io: std.Io, scratch_regs: [16]u8 = @splat(0), sp: u16, @@ -317,45 +360,45 @@ const IO = struct { } fn dev_read(ctx: *anyopaque, addr: IOBusType.Address) u8 { - const io: *IO = @ptrCast(@alignCast(ctx)); + const bus_io: *IO = @ptrCast(@alignCast(ctx)); const reg: Register = @enumFromInt(@as(aviron.IO.Address, @intCast(addr))); return switch (reg) { .exit => 0, .stdio => blk: { - var stdin = std.fs.File.stdin().reader(&.{}); + var stdin = std.Io.File.stdin().reader(bus_io.io, &.{}); var buf: [1]u8 = undefined; stdin.interface.readSliceAll(&buf) catch break :blk 0xFF; // 0xFF = EOF break :blk buf[0]; }, .stderr => 0, - .scratch_0 => io.scratch_regs[0x0], - .scratch_1 => io.scratch_regs[0x1], - .scratch_2 => io.scratch_regs[0x2], - .scratch_3 => io.scratch_regs[0x3], - .scratch_4 => io.scratch_regs[0x4], - .scratch_5 => io.scratch_regs[0x5], - .scratch_6 => io.scratch_regs[0x6], - .scratch_7 => io.scratch_regs[0x7], - .scratch_8 => io.scratch_regs[0x8], - .scratch_9 => io.scratch_regs[0x9], - .scratch_a => io.scratch_regs[0xa], - .scratch_b => io.scratch_regs[0xb], - .scratch_c => io.scratch_regs[0xc], - .scratch_d => io.scratch_regs[0xd], - .scratch_e => io.scratch_regs[0xe], - .scratch_f => io.scratch_regs[0xf], - - .sreg => @bitCast(io.sreg.*), - - .ramp_x => io.ramp_x, - .ramp_y => io.ramp_y, - .ramp_z => io.ramp_z, - .ramp_d => io.ramp_d, - .e_ind => io.e_ind, - - .sp_l => @truncate(io.sp >> 0), - .sp_h => @truncate(io.sp >> 8), + .scratch_0 => bus_io.scratch_regs[0x0], + .scratch_1 => bus_io.scratch_regs[0x1], + .scratch_2 => bus_io.scratch_regs[0x2], + .scratch_3 => bus_io.scratch_regs[0x3], + .scratch_4 => bus_io.scratch_regs[0x4], + .scratch_5 => bus_io.scratch_regs[0x5], + .scratch_6 => bus_io.scratch_regs[0x6], + .scratch_7 => bus_io.scratch_regs[0x7], + .scratch_8 => bus_io.scratch_regs[0x8], + .scratch_9 => bus_io.scratch_regs[0x9], + .scratch_a => bus_io.scratch_regs[0xa], + .scratch_b => bus_io.scratch_regs[0xb], + .scratch_c => bus_io.scratch_regs[0xc], + .scratch_d => bus_io.scratch_regs[0xd], + .scratch_e => bus_io.scratch_regs[0xe], + .scratch_f => bus_io.scratch_regs[0xf], + + .sreg => @bitCast(bus_io.sreg.*), + + .ramp_x => bus_io.ramp_x, + .ramp_y => bus_io.ramp_y, + .ramp_z => bus_io.ramp_z, + .ramp_d => bus_io.ramp_d, + .e_ind => bus_io.e_ind, + + .sp_l => @truncate(bus_io.sp >> 0), + .sp_h => @truncate(bus_io.sp >> 8), _ => std.debug.panic("illegal i/o read from undefined register 0x{X:0>2}", .{addr}), }; @@ -367,47 +410,47 @@ const IO = struct { } fn dev_write_masked(ctx: *anyopaque, addr: IOBusType.Address, mask: u8, value: u8) void { - const io: *IO = @ptrCast(@alignCast(ctx)); + const bus_io: *IO = @ptrCast(@alignCast(ctx)); const reg: Register = @enumFromInt(@as(aviron.IO.Address, @intCast(addr))); switch (reg) { .exit => { - io.exit_code = value & mask; + bus_io.exit_code = value & mask; }, .stdio => { - var stdout = std.fs.File.stdout().writer(&.{}); + var stdout = std.Io.File.stdout().writer(bus_io.io, &.{}); stdout.interface.writeByte(value & mask) catch @panic("i/o failure"); }, .stderr => { - var stderr = std.fs.File.stderr().writer(&.{}); + var stderr = std.Io.File.stderr().writer(bus_io.io, &.{}); stderr.interface.writeByte(value & mask) catch @panic("i/o failure"); }, - .scratch_0 => write_masked(&io.scratch_regs[0x0], mask, value), - .scratch_1 => write_masked(&io.scratch_regs[0x1], mask, value), - .scratch_2 => write_masked(&io.scratch_regs[0x2], mask, value), - .scratch_3 => write_masked(&io.scratch_regs[0x3], mask, value), - .scratch_4 => write_masked(&io.scratch_regs[0x4], mask, value), - .scratch_5 => write_masked(&io.scratch_regs[0x5], mask, value), - .scratch_6 => write_masked(&io.scratch_regs[0x6], mask, value), - .scratch_7 => write_masked(&io.scratch_regs[0x7], mask, value), - .scratch_8 => write_masked(&io.scratch_regs[0x8], mask, value), - .scratch_9 => write_masked(&io.scratch_regs[0x9], mask, value), - .scratch_a => write_masked(&io.scratch_regs[0xa], mask, value), - .scratch_b => write_masked(&io.scratch_regs[0xb], mask, value), - .scratch_c => write_masked(&io.scratch_regs[0xc], mask, value), - .scratch_d => write_masked(&io.scratch_regs[0xd], mask, value), - .scratch_e => write_masked(&io.scratch_regs[0xe], mask, value), - .scratch_f => write_masked(&io.scratch_regs[0xf], mask, value), - - .sp_l => write_masked(low_byte(&io.sp), mask, value), - .sp_h => write_masked(high_byte(&io.sp), mask, value), - .sreg => write_masked(@ptrCast(io.sreg), mask, value), - - .ramp_x => write_masked(&io.ramp_x, mask, value), - .ramp_y => write_masked(&io.ramp_y, mask, value), - .ramp_z => write_masked(&io.ramp_z, mask, value), - .ramp_d => write_masked(&io.ramp_d, mask, value), - .e_ind => write_masked(&io.e_ind, mask, value), + .scratch_0 => write_masked(&bus_io.scratch_regs[0x0], mask, value), + .scratch_1 => write_masked(&bus_io.scratch_regs[0x1], mask, value), + .scratch_2 => write_masked(&bus_io.scratch_regs[0x2], mask, value), + .scratch_3 => write_masked(&bus_io.scratch_regs[0x3], mask, value), + .scratch_4 => write_masked(&bus_io.scratch_regs[0x4], mask, value), + .scratch_5 => write_masked(&bus_io.scratch_regs[0x5], mask, value), + .scratch_6 => write_masked(&bus_io.scratch_regs[0x6], mask, value), + .scratch_7 => write_masked(&bus_io.scratch_regs[0x7], mask, value), + .scratch_8 => write_masked(&bus_io.scratch_regs[0x8], mask, value), + .scratch_9 => write_masked(&bus_io.scratch_regs[0x9], mask, value), + .scratch_a => write_masked(&bus_io.scratch_regs[0xa], mask, value), + .scratch_b => write_masked(&bus_io.scratch_regs[0xb], mask, value), + .scratch_c => write_masked(&bus_io.scratch_regs[0xc], mask, value), + .scratch_d => write_masked(&bus_io.scratch_regs[0xd], mask, value), + .scratch_e => write_masked(&bus_io.scratch_regs[0xe], mask, value), + .scratch_f => write_masked(&bus_io.scratch_regs[0xf], mask, value), + + .sp_l => write_masked(low_byte(&bus_io.sp), mask, value), + .sp_h => write_masked(high_byte(&bus_io.sp), mask, value), + .sreg => write_masked(@ptrCast(bus_io.sreg), mask, value), + + .ramp_x => write_masked(&bus_io.ramp_x, mask, value), + .ramp_y => write_masked(&bus_io.ramp_y, mask, value), + .ramp_z => write_masked(&bus_io.ramp_z, mask, value), + .ramp_d => write_masked(&bus_io.ramp_d, mask, value), + .e_ind => write_masked(&bus_io.e_ind, mask, value), _ => std.debug.panic( "illegal i/o write to undefined register 0x{X:0>2} with value=0x{X:0>2}, mask=0x{X:0>2}", @@ -438,8 +481,8 @@ const IO = struct { } fn dev_check_exit(ctx: *anyopaque) ?u8 { - const io: *IO = @ptrCast(@alignCast(ctx)); - if (io.exit_code) |code| { + const bus_io: *IO = @ptrCast(@alignCast(ctx)); + if (bus_io.exit_code) |code| { return code; } return null; diff --git a/sim/aviron/src/testconfig.zig b/sim/aviron/src/testconfig.zig index 14d3b4375..9ed10aba2 100644 --- a/sim/aviron/src/testconfig.zig +++ b/sim/aviron/src/testconfig.zig @@ -89,9 +89,9 @@ pub const TestSuiteConfig = struct { }) catch @panic("oom"); } - pub fn load(allocator: std.mem.Allocator, file: std.fs.File) !TestSuiteConfig { + pub fn load(allocator: std.mem.Allocator, io: std.Io, file: std.Io.File) !TestSuiteConfig { var buf: [4096]u8 = undefined; - var file_reader = file.reader(&buf); + var file_reader = file.reader(io, &buf); var json_reader = std.json.Reader.init(allocator, &file_reader.interface); return try std.json.parseFromTokenSourceLeaky(TestSuiteConfig, allocator, &json_reader, .{ diff --git a/sim/aviron/src/testrunner.zig b/sim/aviron/src/testrunner.zig index d38adcb77..349295370 100644 --- a/sim/aviron/src/testrunner.zig +++ b/sim/aviron/src/testrunner.zig @@ -1,10 +1,9 @@ const std = @import("std"); const builtin = @import("builtin"); const aviron = @import("aviron"); -const args_parser = @import("args"); const testconfig = @import("testconfig.zig"); -const Cli = struct { +const CLI_Args = struct { help: bool = false, trace: bool = false, @@ -22,33 +21,41 @@ const ExitMode = union(testconfig.ExitType) { system_exit: u8, }; +const RunTestWith_MCU_Options = struct { + +}; + fn run_test_with_mcu( allocator: std.mem.Allocator, mcu_name: []const u8, test_config: testconfig.TestSuiteConfig, - options: Cli, + options: RunTestWith_MCU_Options, elf_paths: []const []const u8, ) !void { - // Use comptime dispatch based on memory sizes (case-insensitive comparison) - if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega328P")) { - try run_test(allocator, aviron.mcu.atmega328p, test_config, options, elf_paths); - } else if (std.ascii.eqlIgnoreCase(mcu_name, "ATtiny816")) { - try run_test(allocator, aviron.mcu.attiny816, test_config, options, elf_paths); - } else if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega2560")) { - try run_test(allocator, aviron.mcu.atmega2560, test_config, options, elf_paths); - } else if (std.ascii.eqlIgnoreCase(mcu_name, "ATxmega128A4U")) { - try run_test(allocator, aviron.mcu.xmega128a4u, test_config, options, elf_paths); - } else { + const mcu = if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega328P")) +aviron.mcu.atmega328p + else if (std.ascii.eqlIgnoreCase(mcu_name, "ATtiny816")) + aviron.mcu.attiny816 + else if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega2560")) + aviron.mcu.atmega2560 + else if (std.ascii.eqlIgnoreCase(mcu_name, "ATxmega128A4U")) + aviron.mcu.xmega128a4u + else { std.debug.print("MCU '{s}' not yet supported in test runner\n", .{mcu_name}); return error.UnsupportedMCU; - } + }; + + try run_test(allocator, mcu, test_config, options, elf_paths); } +const RunTestOptions = struct { +}; + fn run_test( allocator: std.mem.Allocator, - comptime mcu_config: anytype, + mcu_config: aviron.mcu.Config, test_config: testconfig.TestSuiteConfig, - options: Cli, + options: RunTestOptions, elf_paths: []const []const u8, ) !void { var flash_storage = aviron.Flash.Static(mcu_config.flash_size){}; @@ -251,17 +258,14 @@ fn run_test( std.process.exit(if (ok) 0x00 else 0x01); } -pub fn main() !u8 { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); +pub fn main(init: std.process.Init) !u8 { + const arena = init.arena; - var cli = args_parser.parseForCurrentProcess(Cli, allocator, .print) catch return 1; - defer cli.deinit(); + //var cli = args_parser.parseForCurrentProcess(Cli, allocator, .print) catch return 1; + //defer cli.deinit(); const config_path = cli.options.config orelse @panic("missing configuration path!"); - const config = blk: { var file = try std.fs.cwd().openFile(config_path, .{}); defer file.close(); diff --git a/sim/aviron/tools/generate-tables.zig b/sim/aviron/tools/generate_tables.zig similarity index 68% rename from sim/aviron/tools/generate-tables.zig rename to sim/aviron/tools/generate_tables.zig index fb7c9d428..38bf5d442 100644 --- a/sim/aviron/tools/generate-tables.zig +++ b/sim/aviron/tools/generate_tables.zig @@ -13,22 +13,19 @@ fn string_to_enum(comptime T: type, str: []const u8) ?T { return null; } -pub fn main() !void { - const allocator = std.heap.page_allocator; +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); - const argv = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, argv); + if (args.len != 2) @panic("usage: aviron-table-gen "); - if (argv.len != 2) @panic("usage: aviron-table-gen "); + var out = try std.Io.Dir.cwd().createFile(io, args[1], .{}); + defer out.close(io); - var out = try std.fs.cwd().createFile(argv[1], .{}); - defer out.close(); - - var buf = std.array_list.Managed(u8).init(allocator); + var buf: std.Io.Writer.Allocating = .init(gpa); defer buf.deinit(); - const writer = buf.writer(); - var lut = [_]isa.Opcode{.unknown} ** (std.math.maxInt(u16) + 1); var base_number_bit_set = std.bit_set.IntegerBitSet(16).initEmpty(); @@ -38,7 +35,7 @@ pub fn main() !void { var positionals = std.enums.EnumArray(isa.Opcode, std.AutoArrayHashMapUnmanaged(u8, BoundedArray(u8, 16))).initFill(.{}); defer for (&positionals.values) |*map| { - map.deinit(allocator); + map.deinit(gpa); }; var lit = std.mem.splitScalar(u8, isa_def, '\n'); @@ -62,7 +59,7 @@ pub fn main() !void { '0' => {}, '1' => base_number_bit_set.set(index), else => { - const gop = try positionals.getPtr(opcode).getOrPut(allocator, r); + const gop = try positionals.getPtr(opcode).getOrPut(gpa, r); if (!gop.found_existing) { gop.value_ptr.* = try BoundedArray(u8, 16).init(0); } @@ -95,16 +92,16 @@ pub fn main() !void { } } - try writer.writeAll("//! AUTOGENERATED CODE. DO NOT MODIFY!\n\n"); + try buf.writer.writeAll("//! AUTOGENERATED CODE. DO NOT MODIFY!\n\n"); - try writer.writeAll("const isa = @import(\"isa\");\n\n"); + try buf.writer.writeAll("const isa = @import(\"isa\");\n\n"); - try writer.writeAll("pub const Instruction = union(isa.Opcode) {"); + try buf.writer.writeAll("pub const Instruction = union(isa.Opcode) {"); for (positionals.values, 0..) |map, i| { const opcode = std.enums.EnumIndexer(isa.Opcode).keyForIndex(i); - try writer.print("{f}: ", .{std.zig.fmtId(@tagName(opcode))}); + try buf.writer.print("{f}: ", .{std.zig.fmtId(@tagName(opcode))}); const BitSet = struct { name: u8, @@ -116,7 +113,7 @@ pub fn main() !void { } }; - var items = std.array_list.Managed(BitSet).init(allocator); + var items = std.array_list.Managed(BitSet).init(gpa); defer items.deinit(); var it = map.iterator(); @@ -130,70 +127,70 @@ pub fn main() !void { std.sort.block(BitSet, items.items, {}, BitSet.lt); if (items.items.len == 0) { - try writer.writeAll("void"); + try buf.writer.writeAll("void"); } else { - try writer.writeAll("isa.opinfo."); + try buf.writer.writeAll("isa.opinfo."); for (items.items) |key| { - try writer.print("{c}{d}", .{ key.name, key.count }); + try buf.writer.print("{c}{d}", .{ key.name, key.count }); } } - try writer.writeAll(",\n"); + try buf.writer.writeAll(",\n"); } - try writer.writeAll("};\n\n"); + try buf.writer.writeAll("};\n\n"); - try writer.writeAll("pub const lookup = [65536]isa.Opcode {"); + try buf.writer.writeAll("pub const lookup = [65536]isa.Opcode {"); for (lut, 0..) |v, i| { - try writer.print(".{f},", .{std.zig.fmtId(@tagName(v))}); + try buf.writer.print(".{f},", .{std.zig.fmtId(@tagName(v))}); if ((i + 1) % 16 == 0) { - try writer.print("\n", .{}); + try buf.writer.print("\n", .{}); } } - try writer.writeAll("};\n\npub const positionals = .{"); + try buf.writer.writeAll("};\n\npub const positionals = .{"); for (positionals.values, 0..) |map, i| { - try writer.print(".{f} = .{{", .{std.zig.fmtId(@tagName(std.enums.EnumIndexer(isa.Opcode).keyForIndex(i)))}); + try buf.writer.print(".{f} = .{{", .{std.zig.fmtId(@tagName(std.enums.EnumIndexer(isa.Opcode).keyForIndex(i)))}); var it = map.iterator(); while (it.next()) |entry| { - try writer.print(".{{'{c}', .{{", .{entry.key_ptr.*}); + try buf.writer.print(".{{'{c}', .{{", .{entry.key_ptr.*}); const slice = entry.value_ptr.*.slice(); for (slice, 0..) |val, ii| { - try writer.print("{d}", .{val}); + try buf.writer.print("{d}", .{val}); if (ii != slice.len - 1) { - try writer.writeAll(","); + try buf.writer.writeAll(","); } } - try writer.writeAll("}}"); + try buf.writer.writeAll("}}"); if (it.index != it.len) { - try writer.writeAll(","); + try buf.writer.writeAll(","); } } - try writer.writeAll("},"); + try buf.writer.writeAll("},"); if ((i + 1) % 16 == 0) { - try writer.print("\n", .{}); + try buf.writer.print("\n", .{}); } } - try writer.writeAll("};"); + try buf.writer.writeAll("};"); const txt = try buf.toOwnedSliceSentinel(0); - defer allocator.free(txt); + defer gpa.free(txt); - var tree = try std.zig.Ast.parse(allocator, txt, .zig); - defer tree.deinit(allocator); + var tree = try std.zig.Ast.parse(gpa, txt, .zig); + defer tree.deinit(gpa); var stdout_buf: [4096]u8 = undefined; - var stdout = std.fs.File.stdout(); - var stdout_writer = stdout.writer(&stdout_buf); + var stdout = std.Io.File.stdout(); + var stdout_writer = stdout.writer(io, &stdout_buf); var out_buf: [4096]u8 = undefined; - var out_writer = out.writer(&out_buf); + var out_writer = out.writer(io, &out_buf); if (tree.errors.len != 0) { for (tree.errors) |err| { @@ -202,7 +199,7 @@ pub fn main() !void { try out_writer.interface.writeAll(txt); } else { const fixups: std.zig.Ast.Render.Fixups = .{}; - try tree.render(allocator, &out_writer.interface, fixups); + try tree.render(gpa, &out_writer.interface, fixups); } try out_writer.interface.flush(); From 16d3a7d38f75f6a6a399666ab152dd30954f128c Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 24 May 2026 21:29:49 -0700 Subject: [PATCH 05/61] Foundation libc on 0.16.0 --- modules/foundation-libc/build.zig | 9 +-------- modules/foundation-libc/test/build.zig | 28 +++++++++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/modules/foundation-libc/build.zig b/modules/foundation-libc/build.zig index 47d6410ea..c89ba9b5e 100644 --- a/modules/foundation-libc/build.zig +++ b/modules/foundation-libc/build.zig @@ -1,18 +1,11 @@ const std = @import("std"); pub fn build(b: *std.Build) void { - const validation_step = b.step("validate", "Runs the test suite and validates everything. Automatically triggered in Debug builds."); - const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); const single_threaded = b.option(bool, "single_threaded", "Create a single-threaded libc implementation (default: false)") orelse false; - // Run validation in debug builds for convenience: - if (optimize == .Debug) { - b.getInstallStep().dependOn(validation_step); - } - const libc = b.addLibrary(.{ .name = "foundation", .root_module = b.createModule(.{ @@ -23,7 +16,7 @@ pub fn build(b: *std.Build) void { }), }); - libc.addIncludePath(b.path("include")); + libc.root_module.addIncludePath(b.path("include")); for (header_files) |header_name| libc.installHeader( b.path(b.fmt("include/{s}", .{header_name})), diff --git a/modules/foundation-libc/test/build.zig b/modules/foundation-libc/test/build.zig index ef5c6759f..88e9dd217 100644 --- a/modules/foundation-libc/test/build.zig +++ b/modules/foundation-libc/test/build.zig @@ -2,7 +2,7 @@ const std = @import("std"); const Build = std.Build; pub fn build(b: *Build) void { - const validation_step = b.step("validate", "Runs the test suite and validates everything. Automatically triggered in Debug builds."); + const validation_step = b.step("test", "Runs the test suite and validates everything. Automatically triggered in Debug builds."); //const maybe_gcc = b.findProgram(&.{"gcc"}, &.{}) catch null; const maybe_clang = b.findProgram(&.{"clang"}, &.{}) catch null; @@ -28,16 +28,18 @@ pub fn build(b: *Build) void { { // Check if the syntax of all of our header files is valid: - const syntax_validator = b.addStaticLibrary(.{ + const syntax_validator = b.addLibrary(.{ .name = "syntax-validator", - .target = b.graph.host, - .optimize = .Debug, + .root_module = b.createModule(.{ + .target = b.graph.host, + .optimize = .Debug, + }), }); - syntax_validator.addCSourceFile(.{ + syntax_validator.root_module.addCSourceFile(.{ .file = syntax_validator_source, .flags = &common_c_flags, }); - syntax_validator.linkLibrary(foundation); + syntax_validator.root_module.linkLibrary(foundation); _ = syntax_validator.getEmittedBin(); // Just compile, do not install: @@ -69,7 +71,7 @@ pub fn build(b: *Build) void { ext_compiler.addFileArg(syntax_validator_source); ext_compiler.addArg("-o"); - ext_compiler.addArg(b.pathJoin(&.{ b.makeTempPath(), "dummy" })); // we don't really care where this ends up + _ = ext_compiler.addOutputFileArg("dummy"); validation_step.dependOn(&ext_compiler.step); } @@ -82,16 +84,18 @@ pub fn build(b: *Build) void { "FOUNDATION_LIBC_ASSERT_EXPECTED", }) |assert_mode| { // Check if the syntax of all of our header files is valid: - const assert_validator = b.addStaticLibrary(.{ + const assert_validator = b.addLibrary(.{ .name = "assert-validator", - .target = b.graph.host, - .optimize = .Debug, + .root_module = b.createModule(.{ + .target = b.graph.host, + .optimize = .Debug, + }), }); - assert_validator.addCSourceFile(.{ + assert_validator.root_module.addCSourceFile(.{ .file = b.path("src/assert-validator.c"), .flags = &common_c_flags, }); - assert_validator.linkLibrary(foundation); + assert_validator.root_module.linkLibrary(foundation); _ = assert_validator.getEmittedBin(); assert_validator.root_module.addCMacro("FOUNDATION_LIBC_ASSERT", assert_mode); From 5ea643820787c10c1dbcf26929e0eda09282e25d Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 24 May 2026 21:38:32 -0700 Subject: [PATCH 06/61] Freertos for 0.16.0 --- modules/freertos/build.zig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/freertos/build.zig b/modules/freertos/build.zig index 6ba76daad..ccc63db24 100644 --- a/modules/freertos/build.zig +++ b/modules/freertos/build.zig @@ -165,7 +165,7 @@ fn addPicoSDKIncludeDirs( .PICO_SDK_VERSION_REVISION = "0", }); - _ = wf.addCopyFile(cmake_version_file.getOutput(), "picosdk_generated/pico/version.h"); + _ = wf.addCopyFile(cmake_version_file.getOutputFile(), "picosdk_generated/pico/version.h"); // Generate required config_autogen.h (this support custom #include directives) _ = wf.addCopyFile(pico_root.path(b, "bazel/include/pico/config_autogen.h"), "picosdk_generated/pico/config_autogen.h"); @@ -206,16 +206,17 @@ fn addAllIncludeDirs( subdir: []const u8, ) void { const allocator = b.allocator; + const io = b.graph.io; const full = std.fs.path.join(allocator, &.{ base.getPath(b), subdir }) catch @panic("join"); defer allocator.free(full); - var dir = std.fs.openDirAbsolute(full, .{ .iterate = true }) catch return; - defer dir.close(); + var dir = std.Io.Dir.cwd().openDir(io, full, .{ .iterate = true }) catch return; + defer dir.close(io); var walker = dir.walk(allocator) catch @panic("walk"); defer walker.deinit(); - while (walker.next() catch @panic("next")) |e| { + while (walker.next(io) catch @panic("next")) |e| { if (e.kind != .directory) continue; if (!std.mem.eql(u8, std.fs.path.basename(e.path), "include")) continue; From 0829a56453b4eebc720eadb495c2a1cbb753fd5c Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 24 May 2026 21:39:53 -0700 Subject: [PATCH 07/61] lwip 0.16.0 --- modules/lwip/build.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/lwip/build.zig b/modules/lwip/build.zig index 54ad40161..425b0c0c2 100644 --- a/modules/lwip/build.zig +++ b/modules/lwip/build.zig @@ -22,15 +22,15 @@ pub fn build(b: *std.Build) void { .linkage = .static, }); - lwip.addCSourceFiles(.{ + lwip.root_module.addCSourceFiles(.{ .root = upstream.path("src"), .files = &files, .flags = &flags, }); - lwip.addIncludePath(upstream.path("src/include")); + lwip.root_module.addIncludePath(upstream.path("src/include")); if (maybe_include_dir) |include_dir| { - lwip.addIncludePath(include_dir); + lwip.root_module.addIncludePath(include_dir); lwip.installHeadersDirectory(include_dir, "", .{}); } From f346a870864ffa2eb8bba30d41bd76ea8495a735 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 24 May 2026 22:42:11 -0700 Subject: [PATCH 08/61] msp430 examples on 0.16.0 --- build.zig | 40 +++++++++----- core/src/core/usb.zig | 55 +++---------------- core/src/utilities.zig | 75 +++++++++++--------------- port/raspberrypi/rp2xxx/build.zig | 2 +- port/stmicro/stm32/build.zig | 1 - port/texasinstruments/msp430/build.zig | 1 - port/texasinstruments/tm4c/build.zig | 1 - tools/generate_linker_script.zig | 21 +++----- 8 files changed, 74 insertions(+), 122 deletions(-) diff --git a/build.zig b/build.zig index c5b7461b2..e37802a97 100644 --- a/build.zig +++ b/build.zig @@ -139,23 +139,37 @@ pub fn MicroBuild(port_select: PortSelect) type { const Self = @This(); const SelectedPorts = blk: { - var field_names: [port_list.len][]const u8 = undefined; - var field_types: [port_list.len]type = undefined; - var field_attrs: [port_list.len]std.builtin.Type.StructField.Attributes = undefined; - for (port_list, 0..) |port, i| { - if (@field(port_select, port.name)) { - const typ = custom_lazy_import(port.dep_name) orelse struct {}; + const count = count_blk: { + var count: usize = 0; + for (port_list) |port| { + if (@field(port_select, port.name)) { + count += 1; + } + } - field_names[i] = port.name; - field_types[i] = typ; - field_attrs[i] = .{ - .alignment = @alignOf(type), - .default_value_ptr = null, - }; + break :count_blk count; + }; + + var field_names: [count][]const u8 = undefined; + var field_types: [count]type = undefined; + var field_attrs: [count]std.builtin.Type.StructField.Attributes = undefined; + + if (count > 0) { + var i: usize = 0; + for (port_list) |port| { + if (@field(port_select, port.name)) { + const typ = custom_lazy_import(port.dep_name) orelse struct {}; + + field_names[i] = port.name; + field_types[i] = typ; + field_attrs[i] = .{}; + + i += 1; + } } } - break :blk @Struct(.auto, null, field_names, field_types, field_attrs); + break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs); }; const InitReturnType = blk: { diff --git a/core/src/core/usb.zig b/core/src/core/usb.zig index 4d1446b48..a3f45b76e 100644 --- a/core/src/core/usb.zig +++ b/core/src/core/usb.zig @@ -13,41 +13,6 @@ pub const types = @import("usb/types.zig"); pub const ack: []const u8 = ""; pub const nak: ?[]const u8 = null; -/// Meant to make transition to zig 0.16 easier -pub const StructFieldAttributes = struct { - @"comptime": bool = false, - @"align": ?usize = null, - default_value_ptr: ?*const anyopaque = null, -}; - -/// Helper to create a struct, wrapping around @Type, meant to make transition to zig 0.16 easier -pub fn Struct( - layout: std.builtin.Type.ContainerLayout, - BackingInt: ?type, - field_names: []const [:0]const u8, - field_types: *const [field_names.len]type, - field_attrs: *const [field_names.len]StructFieldAttributes, -) type { - var fields: []const std.builtin.Type.StructField = &.{}; - // Iterate over the names, field types, and attributes, creating a new struct field entry - for (field_names, field_types, field_attrs) |n, T, a| { - fields = fields ++ &[1]std.builtin.Type.StructField{.{ - .name = n, - .type = T, - .alignment = a.@"align" orelse @alignOf(T), - .default_value_ptr = a.default_value_ptr, - .is_comptime = a.@"comptime", - }}; - } - return @Type(.{ .@"struct" = .{ - .layout = layout, - .backing_integer = BackingInt, - .decls = &.{}, - .fields = fields, - .is_tuple = false, - } }); -} - // What does this do? It lets you iterate through interfaces and endpoints? pub const DescriptorAllocator = struct { next_ep_num: [2]u8, @@ -173,13 +138,7 @@ pub fn DriverHandlers(Driver: type) type { else => {}, }; - return Struct( - .auto, - null, - field_names, - &@splat(EndpointHandler(Driver)), - &@splat(.{}), - ); + return @Struct(.auto, null, field_names, &@splat(EndpointHandler(Driver)), &@splat(.{})); } pub const Config = struct { @@ -214,7 +173,7 @@ pub const Config = struct { // And save the type of the third field_types[i] = params[2].type.?; } - return Struct(.auto, null, &field_names, &field_types, &@splat(.{})); + return @Struct(.auto, null, &field_names, &field_types, &@splat(.{})); } }; @@ -302,14 +261,14 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { var size = @sizeOf(descriptor.Configuration); var field_names: [driver_fields.len][:0]const u8 = undefined; var field_types: [field_names.len]type = undefined; - var field_attrs: [field_names.len]StructFieldAttributes = undefined; + var field_attrs: [field_names.len]std.builtin.StructField.Attributes = undefined; var ep_handler_types: [2][16]type = @splat(@splat(void)); var ep_handler_names: [2][16][:0]const u8 = undefined; var ep_handler_drivers: [2][16]?usize = @splat(@splat(null)); var itf_handlers: []const DriverEnum = &.{}; var driver_alloc_names: []const [:0]const u8 = &.{}; var driver_alloc_types: []const type = &.{}; - var driver_alloc_attrs: []const StructFieldAttributes = &.{}; + var driver_alloc_attrs: []const std.builtin.StructField.Attributes = &.{}; for (driver_fields, 0..) |drv, drv_id| { // Get descriptor type for the current driver @@ -323,7 +282,7 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { if (result.alloc_bytes) |len| { driver_alloc_names = driver_alloc_names ++ &[_][:0]const u8{drv.name}; driver_alloc_types = driver_alloc_types ++ &[_]type{[len]u8}; - driver_alloc_attrs = driver_alloc_attrs ++ &[_]StructFieldAttributes{.{ .@"align" = result.alloc_align }}; + driver_alloc_attrs = driver_alloc_attrs ++ &[_]std.builtin.StructField.Attributes{.{ .@"align" = result.alloc_align }}; } else { assert(result.alloc_align == null); } @@ -394,7 +353,7 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { } } - const DriverConfig = Struct(.@"extern", null, &field_names, &field_types, &field_attrs); + const DriverConfig = @Struct(.@"extern", null, &field_names, &field_types, &field_attrs); const idx_in = @intFromEnum(types.Dir.In); const idx_out = @intFromEnum(types.Dir.Out); break :blk .{ @@ -417,7 +376,7 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { Out: ep_handlers_types[idx_out] = ep_handlers[idx_out], }{}, .drivers_ep = ep_handler_drivers, - .DriverAlloc = Struct( + .DriverAlloc = @Struct( .auto, null, driver_alloc_names, diff --git a/core/src/utilities.zig b/core/src/utilities.zig index 9bcad56bf..208c0d114 100644 --- a/core/src/utilities.zig +++ b/core/src/utilities.zig @@ -60,24 +60,11 @@ pub fn SliceVector(comptime Slice: type) type { if (type_info.pointer.size != .slice) @compileError("Slice must have a slice type!"); - const item_ptr_info: std.builtin.Type = .{ - .pointer = .{ - .alignment = @min(type_info.pointer.alignment, @alignOf(type_info.pointer.child)), - .size = .one, - .child = type_info.pointer.child, - .address_space = type_info.pointer.address_space, - .is_const = type_info.pointer.is_const, - .is_volatile = type_info.pointer.is_volatile, - .is_allowzero = type_info.pointer.is_allowzero, - .sentinel_ptr = null, - }, - }; - return struct { const Vector = @This(); pub const Item = type_info.pointer.child; - pub const ItemPtr = @Type(item_ptr_info); + pub const ItemPtr = *type_info.pointer.child; /// The slice of slices. The first and the last slice of this slice must /// be non-empty or the slice-of-slices must be empty. @@ -257,21 +244,16 @@ pub fn GenerateInterruptEnum(TagType: type) type { if (microzig.chip.interrupts.len == 0) return enum {}; - var fields: [microzig.chip.interrupts.len]std.builtin.Type.EnumField = undefined; + const count = microzig.chip.interrupts.len; + var field_names: [count][]const u8 = undefined; + var field_values: [count]TagType = undefined; - for (&fields, microzig.chip.interrupts) |*field, interrupt| { - field.* = .{ - .name = interrupt.name, - .value = interrupt.index, - }; + for (microzig.chip.interrupts, &field_names, &field_values) |interrupt, *field_name, *field_value| { + field_name.* = interrupt.name; + field_value.* = interrupt.value; } - return @Type(.{ .@"enum" = .{ - .tag_type = TagType, - .fields = &fields, - .decls = &.{}, - .is_exhaustive = true, - } }); + return @Enum(TagType, .exhaustive, &field_names, &field_values); } pub const Source = struct { @@ -280,30 +262,35 @@ pub const Source = struct { }; pub fn GenerateInterruptOptions(sources: []const Source) type { - var ret_fields: []const std.builtin.Type.StructField = &.{}; + const count = blk: { + var count: usize = 0; + for (sources) |source| { + if (@typeInfo(source.InterruptEnum) != .@"enum") @compileError("expected an enum type"); - for (sources) |source| { - if (@typeInfo(source.InterruptEnum) != .@"enum") @compileError("expected an enum type"); + for (@typeInfo(source.InterruptEnum).@"enum".fields) |_| { + count += 1; + } + } + break :blk count; + }; + + var field_names: [count][]const u8 = undefined; + var field_types: [count]type = undefined; + var field_attrs: [count]std.builtin.Type.StructField.Attributes = undefined; + + var i: usize = 0; + for (sources) |source| { for (@typeInfo(source.InterruptEnum).@"enum".fields) |enum_field| { - ret_fields = ret_fields ++ .{std.builtin.Type.StructField{ - .name = enum_field.name, - .type = ?source.HandlerFn, - .default_value_ptr = @as(*const anyopaque, @ptrCast(&@as(?source.HandlerFn, null))), - .is_comptime = false, - .alignment = @alignOf(?source.HandlerFn), - }}; + field_names[i] = enum_field.name; + field_types[i] = ?source.HandlerFn; + field_attrs[i] = .{ .default_value_ptr = &@as(?source.HandlerFn, null) }; + + i += 1; } } - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = ret_fields, - .decls = &.{}, - .is_tuple = false, - }, - }); + return @Struct(.auto, null, &field_names, &field_types, &field_attrs); } test SliceVector { diff --git a/port/raspberrypi/rp2xxx/build.zig b/port/raspberrypi/rp2xxx/build.zig index 438629544..5242b7458 100644 --- a/port/raspberrypi/rp2xxx/build.zig +++ b/port/raspberrypi/rp2xxx/build.zig @@ -297,7 +297,7 @@ pub fn build(b: *std.Build) !void { }}, }), }); - unit_tests.addIncludePath(b.path("src/hal/pio/assembler")); + unit_tests.root_module.addIncludePath(b.path("src/hal/pio/assembler")); const unit_tests_run = b.addRunArtifact(unit_tests); const test_step = b.step("test", "Run platform agnostic unit tests"); diff --git a/port/stmicro/stm32/build.zig b/port/stmicro/stm32/build.zig index c3c8cece0..c97e326d3 100644 --- a/port/stmicro/stm32/build.zig +++ b/port/stmicro/stm32/build.zig @@ -101,7 +101,6 @@ pub fn build(b: *std.Build) !void { generate_exe.root_module.addImport("regz", regz); const generate_run = b.addRunArtifact(generate_exe); - generate_run.max_stdio_size = std.math.maxInt(usize); generate_run.addFileArg(stm32_data_generated.path(".")); const generate_step = b.step("generate", "Generate chips file 'src/Chips.zig'"); diff --git a/port/texasinstruments/msp430/build.zig b/port/texasinstruments/msp430/build.zig index 1d2dad19c..dea3c9a31 100644 --- a/port/texasinstruments/msp430/build.zig +++ b/port/texasinstruments/msp430/build.zig @@ -58,7 +58,6 @@ pub fn build(b: *std.Build) void { generate_exe.root_module.addImport("regz", regz); const generate_run = b.addRunArtifact(generate_exe); - generate_run.max_stdio_size = std.math.maxInt(usize); generate_run.addFileArg(targetdb); const generate_step = b.step("generate", "Generate chips file 'src/Chips.zig'"); diff --git a/port/texasinstruments/tm4c/build.zig b/port/texasinstruments/tm4c/build.zig index ff43d89bb..3a4d193f6 100644 --- a/port/texasinstruments/tm4c/build.zig +++ b/port/texasinstruments/tm4c/build.zig @@ -50,7 +50,6 @@ pub fn build(b: *std.Build) void { generate_exe.root_module.addImport("regz", regz); const generate_run = b.addRunArtifact(generate_exe); - generate_run.max_stdio_size = std.math.maxInt(usize); generate_run.addFileArg(targetdb); const generate_step = b.step("generate", "Generate chips file 'src/Chips.zig'"); diff --git a/tools/generate_linker_script.zig b/tools/generate_linker_script.zig index 1d5f1d340..9702beaac 100644 --- a/tools/generate_linker_script.zig +++ b/tools/generate_linker_script.zig @@ -14,15 +14,10 @@ pub const Args = struct { var writer_buf: [1024]u8 = undefined; -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - - var arena: std.heap.ArenaAllocator = .init(debug_allocator.allocator()); - defer arena.deinit(); - - const allocator = arena.allocator(); - const args = try std.process.argsAlloc(allocator); +pub fn main(init: std.process.Init) !void { + const io = init.io; + const allocator = init.arena.allocator(); + const args = try init.minimal.args.toSlice(allocator); if (args.len < 3 or args.len > 4) { return error.UsageError; } @@ -33,14 +28,14 @@ pub fn main() !void { const parsed_args = try std.json.parseFromSliceLeaky(Args, allocator, json_args, .{}); const maybe_user_linker_script = if (args.len == 4) - try std.fs.cwd().readFileAlloc(allocator, args[3], 100 * 1024 * 1024) + try std.Io.Dir.cwd().readFileAlloc(io, args[3], allocator, @enumFromInt(100 * 1024 * 1024)) else null; - const file = try std.fs.cwd().createFile(output_path, .{}); - defer file.close(); + const file = try std.Io.Dir.cwd().createFile(io, output_path, .{}); + defer file.close(io); - var writer = file.writer(&writer_buf); + var writer = file.writer(io, &writer_buf); try writer.interface.print( \\/* \\ * Target CPU: {[cpu]s} From d28f527b1c28e324b1a659549408db5698b65e08 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Mon, 25 May 2026 20:56:34 -0700 Subject: [PATCH 09/61] flags library and esp compiling for 0.16.0 --- build.zig | 5 +- build.zig.zon | 1 + core/src/microzig.zig | 28 ++- core/src/utilities.zig | 8 +- port/espressif/esp/build.zig | 14 +- port/espressif/esp/build.zig.zon | 1 + .../esp/ld/esp32_c3/direct_boot_sections.ld | 1 + port/espressif/esp/src/hal/efuse.zig | 4 +- port/espressif/esp/src/hal/radio/wifi.zig | 4 +- port/espressif/esp/src/hal/rtos.zig | 5 +- .../espressif/esp/src/hal/usb_serial_jtag.zig | 10 +- port/espressif/esp/src/tools/cat.zig | 36 +-- port/microchip/atmega/build.zig.zon | 1 + port/microchip/attiny/build.zig.zon | 1 + port/microchip/samd51/build.zig.zon | 1 + port/nordic/nrf5x/build.zig.zon | 1 + port/nxp/mcx/build.zig.zon | 1 + port/raspberrypi/rp2xxx/build.zig.zon | 1 + port/stmicro/stm32/build.zig.zon | 2 + port/texasinstruments/msp430/build.zig | 6 +- port/texasinstruments/msp430/build.zig.zon | 1 + port/texasinstruments/msp430/src/Chips.zig | 4 +- port/texasinstruments/tm4c/build.zig.zon | 1 + sim/aviron/build.zig | 20 +- sim/aviron/build.zig.zon | 1 + sim/aviron/src/main.zig | 44 +--- sim/aviron/src/testrunner.zig | 66 +++--- tools/esp-image/build.zig | 74 +++---- tools/esp-image/build.zig.zon | 5 +- tools/esp-image/src/elf2image.zig | 207 +++++++++--------- tools/esp-image/src/esp_image.zig | 8 +- tools/flags/build.zig | 19 ++ tools/flags/build.zig.zon | 12 + tools/flags/src/root.zig | 78 +++++++ 34 files changed, 375 insertions(+), 296 deletions(-) create mode 100644 tools/flags/build.zig create mode 100644 tools/flags/build.zig.zon create mode 100644 tools/flags/src/root.zig diff --git a/build.zig b/build.zig index e37802a97..d53f2a621 100644 --- a/build.zig +++ b/build.zig @@ -203,9 +203,8 @@ pub fn MicroBuild(port_select: PortSelect) type { var ports: SelectedPorts = undefined; inline for (port_list) |port| { if (@field(port_select, port.name)) { - const port_dep = dep.builder.lazyDependency(port.dep_name, .{}).?; - @field(ports, port.name) = - custom_lazy_import(port.dep_name).?.init(port_dep); + const port_dep = dep.builder.lazyDependency(port.dep_name, .{}) orelse return null; + @field(ports, port.name) = custom_lazy_import(port.dep_name).?.init(port_dep) orelse return null; } } diff --git a/build.zig.zon b/build.zig.zon index 41e32ae25..f8335e835 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -15,6 +15,7 @@ .@"tools/regz" = .{ .path = "tools/regz" }, .@"tools/uf2" = .{ .path = "tools/uf2" }, .@"tools/dfu" = .{ .path = "tools/dfu" }, + .@"tools/flags" = .{ .path = "tools/flags" }, // modules .@"modules/foundation-libc" = .{ .path = "modules/foundation-libc" }, diff --git a/core/src/microzig.zig b/core/src/microzig.zig index 33d9a657b..210d5977e 100644 --- a/core/src/microzig.zig +++ b/core/src/microzig.zig @@ -37,21 +37,25 @@ pub const Allocator = @import("allocator.zig"); pub const panic = std.debug.FullPanic(struct { pub fn panic_fn(message: []const u8, first_trace_address: ?usize) noreturn { std.log.err("panic: {s}", .{message}); + _ = first_trace_address; - var frame_index: usize = 0; - if (@errorReturnTrace()) |trace| frame_index = utilities.dump_stack_trace(trace); + // TODO: sit down and determine if we want to provide our own SelfInfo. + // Is that what plugs into the standard panic? - var iter = std.debug.StackIterator.init(first_trace_address orelse @returnAddress(), null); - while (iter.next()) |address| : (frame_index += 1) { - std.log.err("{d: >3}: 0x{X:0>8}", .{ frame_index, address }); - } + //var frame_index: usize = 0; + //if (@errorReturnTrace()) |trace| frame_index = utilities.dump_stack_trace(trace); - // Attach a breakpoint. this might trigger another panic internally, so - // only do that if requested. - if (options.breakpoint_in_panic) { - std.log.info("triggering breakpoint...", .{}); - @breakpoint(); - } + //var iter = std.debug.StackIterator.init(first_trace_address orelse @returnAddress(), null); + //while (iter.next()) |address| : (frame_index += 1) { + // std.log.err("{d: >3}: 0x{X:0>8}", .{ frame_index, address }); + //} + + //// Attach a breakpoint. this might trigger another panic internally, so + //// only do that if requested. + //if (options.breakpoint_in_panic) { + // std.log.info("triggering breakpoint...", .{}); + // @breakpoint(); + //} hang(); } diff --git a/core/src/utilities.zig b/core/src/utilities.zig index 208c0d114..97c5266d5 100644 --- a/core/src/utilities.zig +++ b/core/src/utilities.zig @@ -64,7 +64,13 @@ pub fn SliceVector(comptime Slice: type) type { const Vector = @This(); pub const Item = type_info.pointer.child; - pub const ItemPtr = *type_info.pointer.child; + pub const ItemPtr = @Pointer(.one, .{ + .@"align" = type_info.pointer.alignment orelse @alignOf(type_info.pointer.child), + .@"addrspace" = type_info.pointer.address_space, + .@"const" = type_info.pointer.is_const, + .@"volatile" = type_info.pointer.is_volatile, + .@"allowzero" = type_info.pointer.is_allowzero, + }, type_info.pointer.child, null); /// The slice of slices. The first and the last slice of this slice must /// be non-empty or the slice-of-slices must be empty. diff --git a/port/espressif/esp/build.zig b/port/espressif/esp/build.zig index 7367b251d..b945aba06 100644 --- a/port/espressif/esp/build.zig +++ b/port/espressif/esp/build.zig @@ -12,7 +12,7 @@ chips: struct { boards: struct {}, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; const esp32_c3_zig_target: std.Target.Query = .{ @@ -34,7 +34,8 @@ pub fn init(dep: *std.Build.Dependency) Self { const esp_image_dep = b.dependency("microzig/tools/esp-image", .{}); const esp_image_mod = esp_image_dep.module("esp_image"); - const esp_wifi_driver_mod = make_esp_wifi_driver_module(b, "esp32c3", esp32_c3_zig_target); + const esp_wifi_sys_dep = b.lazyDependency("esp-wifi-sys", .{}) orelse return null; + const esp_wifi_driver_mod = make_esp_wifi_driver_module(b, esp_wifi_sys_dep, "esp32c3", esp32_c3_zig_target); const chip_esp32_c3: microzig.Target = .{ .dep = dep, @@ -196,9 +197,12 @@ fn generate_linker_script( return run.addOutputFileArg(output_name); } -fn make_esp_wifi_driver_module(b: *std.Build, chip_name: []const u8, target_query: std.Target.Query) *std.Build.Module { - const esp_wifi_sys_dep = b.dependency("esp-wifi-sys", .{}); - +fn make_esp_wifi_driver_module( + b: *std.Build, + esp_wifi_sys_dep: *std.Build.Dependency, + chip_name: []const u8, + target_query: std.Target.Query, +) *std.Build.Module { const esp32_c3_resolved_zig_target = b.resolveTargetQuery(target_query); const translate_c = b.addTranslateC(.{ .root_source_file = esp_wifi_sys_dep.path("c/include/include.h"), diff --git a/port/espressif/esp/build.zig.zon b/port/espressif/esp/build.zig.zon index 45d32550d..5cb647539 100644 --- a/port/espressif/esp/build.zig.zon +++ b/port/espressif/esp/build.zig.zon @@ -9,6 +9,7 @@ .@"esp-wifi-sys" = .{ .url = "git+https://github.com/esp-rs/esp-wifi-sys#7623c8d746b55cd8d9f7473359069aef381b7d3b", .hash = "N-V-__8AANWs5wTMnVsq2oG-zKWSf91LJ6q8Vv6EUD6xNbKJ", + .lazy = true, }, }, .paths = .{ diff --git a/port/espressif/esp/ld/esp32_c3/direct_boot_sections.ld b/port/espressif/esp/ld/esp32_c3/direct_boot_sections.ld index 770c6f2ba..bea7ef207 100644 --- a/port/espressif/esp/ld/esp32_c3/direct_boot_sections.ld +++ b/port/espressif/esp/ld/esp32_c3/direct_boot_sections.ld @@ -5,6 +5,7 @@ SECTIONS _irom_start = .; KEEP(*(microzig_flash_start)) *(.text*) + *(.eh_frame*) . = ALIGN(8); } > IROM diff --git a/port/espressif/esp/src/hal/efuse.zig b/port/espressif/esp/src/hal/efuse.zig index bf302fe62..1f48812e2 100644 --- a/port/espressif/esp/src/hal/efuse.zig +++ b/port/espressif/esp/src/hal/efuse.zig @@ -11,8 +11,8 @@ pub fn read_mac() [6]u8 { return mac; } -pub fn read(comptime what: Item) @Type(.{ .int = .{ .bits = what.bit_length, .signedness = .unsigned } }) { - const OutputType = @Type(.{ .int = .{ .bits = what.bit_length, .signedness = .unsigned } }); +pub fn read(comptime what: Item) @Int(.unsigned, what.bit_length) { + const OutputType = @Int(.unsigned, what.bit_length); const block_byte_offsets = [_]u8{ 0x2C, 0x44, 0x5C }; if (what.block >= block_byte_offsets.len) @compileError("invalid block"); diff --git a/port/espressif/esp/src/hal/radio/wifi.zig b/port/espressif/esp/src/hal/radio/wifi.zig index 3a1f1eeef..476d3604a 100644 --- a/port/espressif/esp/src/hal/radio/wifi.zig +++ b/port/espressif/esp/src/hal/radio/wifi.zig @@ -1248,7 +1248,7 @@ pub const c_patched = struct { sae_h2e_identifier: [32]u8 = std.mem.zeroes([32]u8), // NOTE: maybe a little more imagination - pub const Packed1 = packed struct { + pub const Packed1 = packed struct(u32) { rm_enabled: bool, btm_enabled: bool, mbo_enabled: bool, @@ -1258,7 +1258,7 @@ pub const c_patched = struct { reserved: u26, }; - pub const Packed2 = packed struct { + pub const Packed2 = packed struct(u32) { he_dcm_set: u1, he_dcm_max_constellation_tx: u2, he_dcm_max_constellation_rx: u2, diff --git a/port/espressif/esp/src/hal/rtos.zig b/port/espressif/esp/src/hal/rtos.zig index e21f9e08a..1d58708c0 100644 --- a/port/espressif/esp/src/hal/rtos.zig +++ b/port/espressif/esp/src/hal/rtos.zig @@ -76,10 +76,7 @@ pub const Options = struct { ready_queue_force_no_buckets: bool = false, }; -pub const Priority = enum(@Type(.{ .int = .{ - .bits = rtos_options.priority_bits, - .signedness = .unsigned, -} })) { +pub const Priority = enum(@Int(.unsigned, rtos_options.priority_bits)) { idle = 0, lowest = 1, _, diff --git a/port/espressif/esp/src/hal/usb_serial_jtag.zig b/port/espressif/esp/src/hal/usb_serial_jtag.zig index 8cce3a36f..b74d2d977 100644 --- a/port/espressif/esp/src/hal/usb_serial_jtag.zig +++ b/port/espressif/esp/src/hal/usb_serial_jtag.zig @@ -26,9 +26,6 @@ pub const logger = struct { pub const Error = error{ Timeout, }; - pub const Writer = std.io.GenericWriter(void, Error, generic_writer_fn); - - const writer: Writer = .{ .context = {} }; var timed_out: bool = false; @@ -83,8 +80,13 @@ pub const logger = struct { else => " (" ++ @tagName(scope) ++ "): ", }; + // TODO: do we use debug_io? + _ = format; + _ = args; + _ = prefix; + // TODO: add timestamp to log message - writer.print(prefix ++ format ++ "\r\n", args) catch {}; + //writer.print(prefix ++ format ++ "\r\n", args) catch {}; } }; diff --git a/port/espressif/esp/src/tools/cat.zig b/port/espressif/esp/src/tools/cat.zig index 18dc55df7..ec651ec30 100644 --- a/port/espressif/esp/src/tools/cat.zig +++ b/port/espressif/esp/src/tools/cat.zig @@ -1,29 +1,31 @@ const std = @import("std"); -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - - const allocator = debug_allocator.allocator(); - - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); - +pub fn main(init: std.process.Init) !void { + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len < 2) { std.log.err("usage: ./cat [src_file ...] dst_file", .{}); return error.InvalidArguments; } - const output_file = try std.fs.createFileAbsolute(args[args.len - 1], .{}); - defer output_file.close(); + const src_paths = args[1 .. args.len - 1]; + const dst_path = args[args.len - 1]; - for (args[1 .. args.len - 1]) |arg| { - const file = try std.fs.openFileAbsolute(arg, .{ .mode = .read_only }); - defer file.close(); + const output_file = try std.Io.Dir.cwd().createFile(io, dst_path, .{}); + defer output_file.close(io); - const data = try file.readToEndAlloc(allocator, 1_000_000); - defer allocator.free(data); + var write_buf: [1024 * 1024]u8 = undefined; + var file_writer = output_file.writer(io, &write_buf); + const writer = &file_writer.interface; + for (src_paths) |src_path| { + const file = try std.Io.Dir.openFileAbsolute(io, src_path, .{ .mode = .read_only }); + defer file.close(io); - try output_file.writeAll(data); + var read_buf: [1024 * 1024]u8 = undefined; + var reader = file.reader(io, &read_buf); + + _ = try reader.interface.streamRemaining(writer); } + + try writer.flush(); } diff --git a/port/microchip/atmega/build.zig.zon b/port/microchip/atmega/build.zig.zon index cf02cbfd9..99cf87ed0 100644 --- a/port/microchip/atmega/build.zig.zon +++ b/port/microchip/atmega/build.zig.zon @@ -7,6 +7,7 @@ .atpack = .{ .url = "https://atpack.microzig.tech/Atmel.ATmega_DFP.2.2.509.atpack", .hash = "N-V-__8AALMZ6AaqwABfnUqEWoZX1Ocb7LqjGVZNKB1fJNon", + .lazy = true, }, }, .paths = .{ diff --git a/port/microchip/attiny/build.zig.zon b/port/microchip/attiny/build.zig.zon index 1a07fdf96..39f80dc6c 100644 --- a/port/microchip/attiny/build.zig.zon +++ b/port/microchip/attiny/build.zig.zon @@ -7,6 +7,7 @@ .atpack = .{ .url = "https://atpack.microzig.tech/Atmel.ATtiny_DFP.2.0.368.atpack", .hash = "N-V-__8AAChkfwZp4ZmDp0teMCY8Q-2clc9GmzWHeh7xiKnO", + .lazy = true, }, }, .paths = .{ diff --git a/port/microchip/samd51/build.zig.zon b/port/microchip/samd51/build.zig.zon index 7be141ce2..95c07b6c2 100644 --- a/port/microchip/samd51/build.zig.zon +++ b/port/microchip/samd51/build.zig.zon @@ -7,6 +7,7 @@ .atpack = .{ .url = "https://atpack.microzig.tech/Atmel.SAMD51_DFP.1.2.139.atpack", .hash = "N-V-__8AANARcANIBlLE4tsLRqcfeI8Z4IZL4f5Jiq8DDotY", + .lazy = true, }, }, .paths = .{ diff --git a/port/nordic/nrf5x/build.zig.zon b/port/nordic/nrf5x/build.zig.zon index 352a9973a..4fac1ea9b 100644 --- a/port/nordic/nrf5x/build.zig.zon +++ b/port/nordic/nrf5x/build.zig.zon @@ -7,6 +7,7 @@ .nrfx = .{ .url = "https://github.com/NordicSemiconductor/nrfx/archive/refs/tags/v3.11.0.tar.gz", .hash = "N-V-__8AABC-kgxbmC3Prd8fgisfbLs1giU34ofX1vz9bwaA", + .lazy = true, }, }, .paths = .{ diff --git a/port/nxp/mcx/build.zig.zon b/port/nxp/mcx/build.zig.zon index d037af59f..7120341d3 100644 --- a/port/nxp/mcx/build.zig.zon +++ b/port/nxp/mcx/build.zig.zon @@ -8,6 +8,7 @@ .@"mcux-soc-svd" = .{ .url = "https://github.com/nxp-mcuxpresso/mcux-soc-svd/archive/refs/tags/MCUX_2.16.100.tar.gz", .hash = "N-V-__8AADdFeofKFhsuzMbDdzLAKB4-syMJsHSEOTYGFrlH", + .lazy = true, }, }, .paths = .{ diff --git a/port/raspberrypi/rp2xxx/build.zig.zon b/port/raspberrypi/rp2xxx/build.zig.zon index 6de3e3790..f69ad2304 100644 --- a/port/raspberrypi/rp2xxx/build.zig.zon +++ b/port/raspberrypi/rp2xxx/build.zig.zon @@ -8,6 +8,7 @@ .@"pico-sdk" = .{ .url = "https://github.com/raspberrypi/pico-sdk/archive/refs/tags/2.1.1.tar.gz", .hash = "N-V-__8AAPtGbwGQkp_3ej_icp5z6qgvjmwoE1AvAcZlh57Z", + .lazy = true, }, .@"bounded-array" = .{ .path = "../../../modules/bounded-array" }, }, diff --git a/port/stmicro/stm32/build.zig.zon b/port/stmicro/stm32/build.zig.zon index 274211ce2..c52f5e0b1 100644 --- a/port/stmicro/stm32/build.zig.zon +++ b/port/stmicro/stm32/build.zig.zon @@ -8,10 +8,12 @@ .@"stm32-data-generated" = .{ .url = "git+https://github.com/embassy-rs/stm32-data-generated.git#5198a6e36b24f6d79c4ac91af5e61e8d54667d88", .hash = "N-V-__8AAFi8WBlOh-NikHFVBjzQE0F1KixgKjVWYnlijPNm", + .lazy = true, }, .ClockHelper = .{ .url = "git+https://github.com/ZigEmbeddedGroup/ClockHelper#252a3d81f80915dcd0ac280b1ef6be455447d1c5", .hash = "ClockHelper-2.0.0-RcMaOYpcIwHRJCnKF3AVSXrDyMpUlmIpZprAHjqflyzy", + .lazy = true, }, }, .paths = .{ diff --git a/port/texasinstruments/msp430/build.zig b/port/texasinstruments/msp430/build.zig index dea3c9a31..a0457641c 100644 --- a/port/texasinstruments/msp430/build.zig +++ b/port/texasinstruments/msp430/build.zig @@ -12,8 +12,8 @@ const Boards = struct { launch_pad_msp430g2553: *microzig.Target, }; -pub fn init(dep: *std.Build.Dependency) Self { - const chips = Chips.init(dep); +pub fn init(dep: *std.Build.Dependency) ?Self { + const chips = Chips.init(dep) orelse return null; const boards = Boards{ .launch_pad_msp430f5529 = chips.MSP430F5529.derive(.{ .board = .{ @@ -38,7 +38,7 @@ pub fn init(dep: *std.Build.Dependency) Self { } pub fn build(b: *std.Build) void { - const ti_data = b.dependency("ti_data", .{}); + const ti_data = b.lazyDependency("ti_data", .{}) orelse return; const targetdb = ti_data.path("targetdb"); const generate_optimize = .ReleaseSafe; diff --git a/port/texasinstruments/msp430/build.zig.zon b/port/texasinstruments/msp430/build.zig.zon index b9a39c0db..5f6ffaec5 100644 --- a/port/texasinstruments/msp430/build.zig.zon +++ b/port/texasinstruments/msp430/build.zig.zon @@ -9,6 +9,7 @@ .ti_data = .{ .url = "git+https://github.com/ZigEmbeddedGroup/texasinstruments-data.git#2bdd0ff770ea4070caf25e2d33e9744374c75b21", .hash = "N-V-__8AAEUAg0HJNVCziuaLjHq479tsKsXb4GbNf5ye38oi", + .lazy = true, }, }, .paths = .{ diff --git a/port/texasinstruments/msp430/src/Chips.zig b/port/texasinstruments/msp430/src/Chips.zig index 3e49d3694..672e8c78f 100644 --- a/port/texasinstruments/msp430/src/Chips.zig +++ b/port/texasinstruments/msp430/src/Chips.zig @@ -6,9 +6,9 @@ const Self = @This(); MSP430F5529: *microzig.Target, MSP430G2553: *microzig.Target, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const ti_data = b.dependency("ti_data", .{}); + const ti_data = b.lazyDependency("ti_data", .{}) orelse return null; const targetdb = ti_data.path("targetdb"); var ret: Self = undefined; diff --git a/port/texasinstruments/tm4c/build.zig.zon b/port/texasinstruments/tm4c/build.zig.zon index b7d4f3c0f..6eb6aec58 100644 --- a/port/texasinstruments/tm4c/build.zig.zon +++ b/port/texasinstruments/tm4c/build.zig.zon @@ -9,6 +9,7 @@ .ti_data = .{ .url = "git+https://github.com/ZigEmbeddedGroup/texasinstruments-data.git#2bdd0ff770ea4070caf25e2d33e9744374c75b21", .hash = "N-V-__8AAEUAg0HJNVCziuaLjHq479tsKsXb4GbNf5ye38oi", + .lazy = true, }, }, .paths = .{ diff --git a/sim/aviron/build.zig b/sim/aviron/build.zig index f7269bb12..fdc329d1a 100644 --- a/sim/aviron/build.zig +++ b/sim/aviron/build.zig @@ -18,7 +18,9 @@ const avr_target_query = std.Target.Query{ }; pub fn build(b: *Build) !void { - // Targets + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + const test_step = b.step("test", "Run test suite"); const run_step = b.step("run", "Run the app"); const debug_testsuite_step = b.step("debug-testsuite", "Installs all testsuite examples"); @@ -27,17 +29,12 @@ pub fn build(b: *Build) !void { "Updates the folder testsuite with the data in testsuite.avr-gcc. Requires avr-gcc to be present!", ); - // Deps const ihex_dep = b.dependency("ihex", .{}); + const flags_dep = b.dependency("flags", .{}); - // Dep modules const ihex_module = ihex_dep.module("ihex"); + const flags_module = flags_dep.module("flags"); - // Options - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); - - // Modules const isa_module = b.createModule(.{ .root_source_file = b.path("src/shared/isa.zig") }); const isa_tables_module = b.createModule(.{ .root_source_file = generate_isa_tables(b, isa_module), @@ -64,11 +61,14 @@ pub fn build(b: *Build) !void { .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, + .imports = &.{ + .{ .name = "ihex", .module = ihex_module }, + .{ .name = "aviron", .module = aviron_module }, + .{ .name = "flags", .module = flags_module }, + }, }), .use_llvm = true, }); - aviron_exe.root_module.addImport("ihex", ihex_module); - aviron_exe.root_module.addImport("aviron", aviron_module); b.installArtifact(aviron_exe); const run_cmd = b.addRunArtifact(aviron_exe); diff --git a/sim/aviron/build.zig.zon b/sim/aviron/build.zig.zon index 9017fdc41..35f0f6440 100644 --- a/sim/aviron/build.zig.zon +++ b/sim/aviron/build.zig.zon @@ -4,6 +4,7 @@ .fingerprint = 0xfc536f957aeaeb54, .dependencies = .{ .@"bounded-array" = .{ .path = "../../modules/bounded-array" }, + .flags = .{ .path = "../../tools/flags" }, .ihex = .{ .url = "git+https://github.com/mattnite/zig-ihex#9deb291104ecd7dcaab0db27bf05252764600947", .hash = "ihex-0.1.0-1POu25EyAADaasaxKmaex5A6D_4cohzZkOW4qpn_mav0", diff --git a/sim/aviron/src/main.zig b/sim/aviron/src/main.zig index d124dc300..a06ccaa93 100644 --- a/sim/aviron/src/main.zig +++ b/sim/aviron/src/main.zig @@ -2,6 +2,7 @@ const std = @import("std"); const builtin = @import("builtin"); const aviron = @import("aviron"); const ihex = @import("ihex"); +const flags = @import("flags"); const log = std.log.scoped(.main); @@ -168,7 +169,7 @@ const CLI_Args = struct { breakpoint: ?u24 = null, gas: ?u64 = null, - const default: CLI_Args = .{}; + pub const default: CLI_Args = .{}; const usage = \\[--help] [--trace] [--mcu=] [--info] [--format=] [--breakpoint=] [--gas=] ... @@ -192,49 +193,10 @@ const CLI_Args = struct { ; }; -fn parse_bool(str: []const u8) !bool { - return if (std.mem.eql(u8, str, "true")) - true - else if (std.mem.eql(u8, str, "false")) - false - else - error.InvalidBoolStr; -} - pub fn main(init: std.process.Init) !u8 { const gpa = init.gpa; const args = try init.minimal.args.toSlice(init.arena.allocator()); - - var cli_args: CLI_Args = .default; - const positionals = for (args, 0..) |arg, i| { - if (!std.mem.startsWith(u8, arg, "--")) - break args[i..]; - - const equals = std.mem.findScalar(u8, arg, '='); - const key = arg[2 .. equals orelse arg.len]; - const value = arg[equals orelse arg.len .. arg.len]; - inline for (@typeInfo(CLI_Args).@"struct".fields) |field| { - if (std.mem.eql(u8, key, field.name)) { - @field(cli_args, field.name) = switch (field.type) { - bool => if (equals != null) - try parse_bool(value) - else - true, - - MCU, FileFormat => std.meta.stringToEnum(field.type, value) orelse { - log.err("Invalid value for --{s}: '{s}'", .{ key, value }); - return error.InvalidValue; - }, - ?u24 => try std.fmt.parseInt(u24, value, 0), - ?u64 => try std.fmt.parseInt(u64, value, 0), - else => unreachable, - }; - } - } - - log.err("Unrecognied CLI argument: --{s}", .{key}); - return error.UnrecognizedCliArgument; - } else &.{}; + const cli_args, const positionals = try flags.parse(CLI_Args, init.arena.allocator(), args); const io = init.io; if (cli_args.help) { diff --git a/sim/aviron/src/testrunner.zig b/sim/aviron/src/testrunner.zig index 349295370..00dae9456 100644 --- a/sim/aviron/src/testrunner.zig +++ b/sim/aviron/src/testrunner.zig @@ -2,6 +2,7 @@ const std = @import("std"); const builtin = @import("builtin"); const aviron = @import("aviron"); const testconfig = @import("testconfig.zig"); +const flags = @import("flags"); const CLI_Args = struct { help: bool = false, @@ -9,6 +10,8 @@ const CLI_Args = struct { name: []const u8 = "", config: ?[]const u8 = null, + + pub const default: CLI_Args = .{}; }; const ExitMode = union(testconfig.ExitType) { @@ -21,38 +24,35 @@ const ExitMode = union(testconfig.ExitType) { system_exit: u8, }; -const RunTestWith_MCU_Options = struct { - -}; - fn run_test_with_mcu( - allocator: std.mem.Allocator, + gpa: std.mem.Allocator, mcu_name: []const u8, test_config: testconfig.TestSuiteConfig, - options: RunTestWith_MCU_Options, + options: RunTestOptions, elf_paths: []const []const u8, ) !void { - const mcu = if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega328P")) -aviron.mcu.atmega328p - else if (std.ascii.eqlIgnoreCase(mcu_name, "ATtiny816")) - aviron.mcu.attiny816 - else if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega2560")) - aviron.mcu.atmega2560 - else if (std.ascii.eqlIgnoreCase(mcu_name, "ATxmega128A4U")) - aviron.mcu.xmega128a4u - else { + const mcu = if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega328P")) + aviron.mcu.atmega328p + else if (std.ascii.eqlIgnoreCase(mcu_name, "ATtiny816")) + aviron.mcu.attiny816 + else if (std.ascii.eqlIgnoreCase(mcu_name, "ATmega2560")) + aviron.mcu.atmega2560 + else if (std.ascii.eqlIgnoreCase(mcu_name, "ATxmega128A4U")) + aviron.mcu.xmega128a4u + else { std.debug.print("MCU '{s}' not yet supported in test runner\n", .{mcu_name}); return error.UnsupportedMCU; }; - try run_test(allocator, mcu, test_config, options, elf_paths); + try run_test(gpa, mcu, test_config, options, elf_paths); } const RunTestOptions = struct { + trace: bool = false, }; fn run_test( - allocator: std.mem.Allocator, + gpa: std.mem.Allocator, mcu_config: aviron.mcu.Config, test_config: testconfig.TestSuiteConfig, options: RunTestOptions, @@ -61,10 +61,10 @@ fn run_test( var flash_storage = aviron.Flash.Static(mcu_config.flash_size){}; var sram = aviron.FixedSizeMemory(mcu_config.sram_size, .{ .address_type = u24 }){}; - var stdout = std.array_list.Managed(u8).init(allocator); + var stdout = std.array_list.Managed(u8).init(gpa); defer stdout.deinit(); - var stderr = std.array_list.Managed(u8).init(allocator); + var stderr = std.array_list.Managed(u8).init(gpa); defer stderr.deinit(); var io = IO{ @@ -83,8 +83,8 @@ fn run_test( const io_io_bus = io.io_bus(); // For direct IO operations // Build memory spaces via MCU helper - var spaces = try aviron.mcu.build_spaces(allocator, mcu_config, sram.bus(), io_data_bus); - defer spaces.deinit(allocator); + var spaces = try aviron.mcu.build_spaces(gpa, mcu_config, sram.bus(), io_data_bus); + defer spaces.deinit(gpa); var cpu = aviron.Cpu{ .trace = options.trace, @@ -258,35 +258,43 @@ fn run_test( std.process.exit(if (ok) 0x00 else 0x01); } - pub fn main(init: std.process.Init) !u8 { const arena = init.arena; + const gpa = init.gpa; + const args = try init.minimal.args.toSlice(arena.allocator()); + const cli_args, const positionals = try flags.parse(CLI_Args, arena.allocator(), args); - //var cli = args_parser.parseForCurrentProcess(Cli, allocator, .print) catch return 1; - //defer cli.deinit(); + if (cli_args.help) { + // TODO: usage + return 0; + } - const config_path = cli.options.config orelse @panic("missing configuration path!"); + const config_path = cli_args.config orelse @panic("missing configuration path!"); const config = blk: { var file = try std.fs.cwd().openFile(config_path, .{}); defer file.close(); - break :blk try testconfig.TestSuiteConfig.load(allocator, file); + break :blk try testconfig.TestSuiteConfig.load(arena.allocator(), file); }; - if (cli.positionals.len == 0) + if (positionals.len == 0) @panic("usage: aviron [--trace] "); + const options: RunTestOptions = .{ + .trace = cli_args.trace, + }; + // Determine which MCU(s) to test with if (config.cpus) |cpus| { // Run test against multiple MCUs for (cpus) |mcu_name| { std.debug.print("Running test with MCU: {s}\n", .{mcu_name}); - try run_test_with_mcu(allocator, mcu_name, config, cli.options, cli.positionals); + try run_test_with_mcu(gpa, mcu_name, config, positionals, options); } } else { // Run test against a single MCU (default to ATmega328P if not specified) const mcu_name = config.cpu orelse "ATmega328P"; - try run_test_with_mcu(allocator, mcu_name, config, cli.options, cli.positionals); + try run_test_with_mcu(gpa, mcu_name, config, positionals, options); } return 0; diff --git a/tools/esp-image/build.zig b/tools/esp-image/build.zig index 13900418b..cbd81e53f 100644 --- a/tools/esp-image/build.zig +++ b/tools/esp-image/build.zig @@ -4,7 +4,7 @@ pub const ChipId = esp_image.ChipId; pub const FlashMode = esp_image.FlashMode; pub const FlashFreq = esp_image.FlashFreq; pub const FlashSize = esp_image.FlashSize; -pub const FlashMMU_PageSize = esp_image.FlashMMU_PageSize; +pub const Flash_MMU_PageSize = esp_image.Flash_MMU_PageSize; pub const Options = struct { chip_id: ChipId, @@ -14,7 +14,7 @@ pub const Options = struct { flash_freq: ?FlashFreq = null, flash_mode: ?FlashMode = null, flash_size: ?FlashSize = null, - flash_mmu_page_size: ?FlashMMU_PageSize = null, + flash_mmu_page_size: ?Flash_MMU_PageSize = null, use_segments: ?bool = null, }; @@ -24,67 +24,47 @@ pub fn from_elf(dep: *std.Build.Dependency, elf_file: std.Build.LazyPath, option const elf2image_exe = dep.artifact("elf2image"); const run = b.addRunArtifact(elf2image_exe); - run.addFileArg(elf_file); - - run.addArgs(&.{ - "--chip-id", - @tagName(options.chip_id), - }); + run.addArg(b.fmt("--chip_id={s}", .{@tagName(options.chip_id)})); + if (options.min_rev) |min_rev| + run.addArg(b.fmt("--min_rev={}", .{min_rev})); - if (options.min_rev) |min_rev| { - run.addArgs(&.{ - "--min-rev-full", - b.fmt("{}", .{min_rev}), - }); - } - - if (options.max_rev) |max_rev| { - run.addArgs(&.{ - "--max-rev-full", - b.fmt("{}", .{max_rev}), - }); - } + if (options.max_rev) |max_rev| + run.addArg(b.fmt("--max_rev={}", .{max_rev})); if (options.dont_append_digest) |dont_append_digest| { - if (dont_append_digest) { - run.addArg("--dont-append-digest"); - } + if (dont_append_digest) + run.addArg("--no_digest"); } - if (options.flash_freq) |flash_freq| { - run.addArg("--flash-freq"); - run.addArg(@tagName(flash_freq)); - } + if (options.flash_freq) |flash_freq| + run.addArg(b.fmt("--flash_freq={s}", .{@tagName(flash_freq)})); - if (options.flash_mode) |flash_mode| { - run.addArg("--flash-mode"); - run.addArg(@tagName(flash_mode)); - } + if (options.flash_mode) |flash_mode| + run.addArg(b.fmt("--flash_mode={s}", .{@tagName(flash_mode)})); - if (options.flash_size) |flash_size| { - run.addArg("--flash-size"); - run.addArg(@tagName(flash_size)); - } + if (options.flash_size) |flash_size| + run.addArg(b.fmt("--flash_size={s}", .{@tagName(flash_size)})); if (options.use_segments) |use_segments| { - if (use_segments) { - run.addArg("--use-segments"); - } + if (use_segments) + run.addArg("--segments"); } - if (options.flash_mmu_page_size) |flash_mmu_page_size| { - run.addArg("--flash-mmu-page-size"); - run.addArg(@tagName(flash_mmu_page_size)); - } + if (options.flash_mmu_page_size) |flash_mmu_page_size| + run.addArg(b.fmt("--flash_mmu_page_size={s}", .{@tagName(flash_mmu_page_size)})); - run.addArg("--output"); - return run.addOutputFileArg("output.bin"); + const output = run.addPrefixedOutputFileArg("--output=", "output.bin"); + run.addFileArg(elf_file); + return output; } pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); + const flags_dep = b.dependency("flags", .{}); + const flags_module = flags_dep.module("flags"); + const esp_image_mod = b.addModule("esp_image", .{ .root_source_file = b.path("src/esp_image.zig"), }); @@ -97,13 +77,11 @@ pub fn build(b: *std.Build) void { .optimize = optimize, .imports = &.{ .{ .name = "esp_image", .module = esp_image_mod }, + .{ .name = "flags", .module = flags_module }, }, }), }); - const clap = b.dependency("clap", .{}); - elf2image_exe.root_module.addImport("clap", clap.module("clap")); - const elf2image_test = b.addTest(.{ .name = "elf2image", .root_module = b.createModule(.{ diff --git a/tools/esp-image/build.zig.zon b/tools/esp-image/build.zig.zon index 8fe07d7b4..57c726962 100644 --- a/tools/esp-image/build.zig.zon +++ b/tools/esp-image/build.zig.zon @@ -3,10 +3,7 @@ .fingerprint = 0x7e1bc55e5a45fa73, .version = "0.1.0", .dependencies = .{ - .clap = .{ - .url = "git+https://github.com/Hejsil/zig-clap.git#5289e0753cd274d65344bef1c114284c633536ea", - .hash = "clap-0.11.0-oBajB-HnAQDPCKYzwF7rO3qDFwRcD39Q0DALlTSz5H7e", - }, + .flags = .{ .path = "../flags" }, }, .paths = .{ "README.md", diff --git a/tools/esp-image/src/elf2image.zig b/tools/esp-image/src/elf2image.zig index b013ad042..2adc77189 100644 --- a/tools/esp-image/src/elf2image.zig +++ b/tools/esp-image/src/elf2image.zig @@ -1,8 +1,14 @@ const std = @import("std"); const Sha256 = std.crypto.hash.sha2.Sha256; -const clap = @import("clap"); +const flags = @import("flags"); const esp_image = @import("esp_image"); +const ChipId = esp_image.ChipId; +const FlashFreq = esp_image.FlashFreq; +const FlashMode = esp_image.FlashMode; +const FlashSize = esp_image.FlashSize; +const Flash_MMU_PageSize = esp_image.Flash_MMU_PageSize; + pub const std_options: std.Options = .{ .log_level = .warn, }; @@ -11,72 +17,65 @@ var elf_file_reader_buf: [1024]u8 = undefined; var elf_file_hashing_buf: [std.crypto.hash.sha2.Sha256.digest_length]u8 = undefined; var output_writer_buf: [1024]u8 = undefined; -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - const allocator = debug_allocator.allocator(); - - const args = comptime clap.parseParamsComptime( +const CLI_Args = struct { + help: bool = false, + output: ?[]const u8 = null, + chip_id: ?ChipId = null, + min_rev: u16 = 0x0000, + max_rev: u16 = 0xFFFF, + no_digest: bool = false, + flash_freq: ?FlashFreq = null, + flash_mode: ?FlashMode = null, + flash_size: ?FlashSize = null, + flash_mmu_page_size: ?Flash_MMU_PageSize = null, + segments: bool = false, + + pub const default: CLI_Args = .{}; + + pub const usage = \\--help Show this message - \\--output Path to save the generated file - \\--chip-id Chip id - \\--min-rev-full Minimal chip revision (in format: major * 100 + minor) - \\--max-rev-full Maximal chip revision (in format: major * 100 + minor) - \\--dont-append-digest Don't append a SHA256 digest of the entire image after the checksum - \\--flash-freq SPI Flash frequency - \\--flash-mode SPI Flash mode - \\--flash-size SPI Flash size in megabytes - \\--flash-mmu-page-size Flash MMU page size - \\--use-segments Use program headers instead of section headers + \\--output= Path to save the generated file + \\--chip_id= Chip id + \\--min_rev= Minimal chip revision (in format: major * 100 + minor) + \\--max_rev= Maximal chip revision (in format: major * 100 + minor) + \\--no_digest Don't append a SHA256 digest of the entire image after the checksum + \\--flash_freq= SPI Flash frequency + \\--flash_mode= SPI Flash mode + \\--flash_size= SPI Flash size in megabytes + \\--flash_mmu-page_size= Flash MMU page size + \\--segments Use program headers instead of section headers \\ \\ - ); - - const stderr = std.fs.File.stderr(); - var stderr_writer = stderr.writer(&.{}); - - var diag: clap.Diagnostic = .{}; - var res = clap.parse(clap.Help, &args, .{ - .u16 = clap.parsers.int(u16, 10), - .str = clap.parsers.string, - .ChipId = clap.parsers.enumeration(esp_image.ChipId), - .FlashFreq = clap.parsers.enumeration(esp_image.FlashFreq), - .FlashMode = clap.parsers.enumeration(esp_image.FlashMode), - .FlashSize = clap.parsers.enumeration(esp_image.FlashSize), - .FlashMMU_PageSize = clap.parsers.enumeration(esp_image.FlashMMU_PageSize), - }, .{ - .diagnostic = &diag, - .allocator = allocator, - }) catch |err| { - diag.report(&stderr_writer.interface, err) catch {}; - return err; - }; - defer res.deinit(); + ; +}; - if (res.args.help != 0) { - return clap.help(&stderr_writer.interface, clap.Help, &args, .{}); - } +pub fn main(init: std.process.Init) !void { + const io = init.io; + const gpa = init.gpa; + const args = try init.minimal.args.toSlice(init.arena.allocator()); + const cli_args, const positionals = try flags.parse(CLI_Args, init.arena.allocator(), args); - const elf_path = res.positionals[0] orelse return error.MissingInputFile; - const output_path = res.args.output orelse return error.MissingOutputFile; + var stdout = std.Io.File.stderr().writer(io, &.{}); + if (cli_args.help) { + try stdout.interface.print("{s}", .{CLI_Args.usage}); + return; + } - const chip_id = res.args.@"chip-id" orelse return error.MissingChipId; + const elf_path = if (positionals.len > 0) positionals[0] else return error.MissingInputFile; + const output_path = cli_args.output orelse return error.MissingOutputFile; + const chip_id = cli_args.chip_id orelse return error.MissingChipId; const chip = chips.get(chip_id) orelse { std.log.err("support for chip `{s}` is not implemented yet", .{@tagName(chip_id)}); return error.UnimplementedChip; }; - const min_rev: u16 = res.args.@"min-rev-full" orelse 0x0000; - const max_rev: u16 = res.args.@"max-rev-full" orelse 0xffff; - const no_digest = res.args.@"dont-append-digest" != 0; - const flash_freq: esp_image.FlashFreq = res.args.@"flash-freq" orelse .@"40m"; - const flash_mode: esp_image.FlashMode = res.args.@"flash-mode" orelse .dio; - const flash_size: esp_image.FlashSize = res.args.@"flash-size" orelse .@"4mb"; - - var flash_mmu_page_size: esp_image.FlashMMU_PageSize = esp_image.DEFAULT_FLASH_MMU_PAGE_SIZE; - if (res.args.@"flash-mmu-page-size") |page_size_override| { + const flash_freq = cli_args.flash_freq orelse return error.MissingFlashFreq; + const flash_mode = cli_args.flash_mode orelse return error.MissingFlashMode; + const flash_size = cli_args.flash_size orelse return error.MissingFlashSize; + var flash_mmu_page_size: Flash_MMU_PageSize = esp_image.DEFAULT_FLASH_MMU_PAGE_SIZE; + if (cli_args.flash_mmu_page_size) |page_size_override| { if (chip.supported_flash_mmu_page_sizes) |supported_flash_mmu_page_sizes| { - if (std.mem.indexOfScalar(esp_image.FlashMMU_PageSize, supported_flash_mmu_page_sizes, page_size_override) != null) { + if (std.mem.indexOfScalar(Flash_MMU_PageSize, supported_flash_mmu_page_sizes, page_size_override) != null) { flash_mmu_page_size = page_size_override; } else { std.log.err("flash mmu page size `{t}` is not supported by chip `{t}`... using default `{t}`", .{ @@ -88,12 +87,10 @@ pub fn main() !void { } } - const use_segments = res.args.@"use-segments" != 0; - - const elf_file = try std.fs.cwd().openFile(elf_path, .{}); - defer elf_file.close(); - var elf_file_reader = elf_file.reader(&elf_file_reader_buf); + const elf_file = try std.Io.Dir.cwd().openFile(io, elf_path, .{}); + defer elf_file.close(io); + var elf_file_reader = elf_file.reader(io, &elf_file_reader_buf); var elf_file_hash: [std.crypto.hash.sha2.Sha256.digest_length]u8 = undefined; { var hashing: std.Io.Writer.Hashing(std.crypto.hash.sha2.Sha256) = .init(&elf_file_hashing_buf); @@ -107,26 +104,26 @@ pub fn main() !void { const entry_point: u32 = @intCast(elf_header.entry); var flash_segments: std.ArrayList(Segment) = .empty; - defer flash_segments.deinit(allocator); + defer flash_segments.deinit(gpa); defer for (flash_segments.items) |segment| { - segment.deinit(allocator); + segment.deinit(gpa); }; var ram_segments: std.ArrayList(Segment) = .empty; - defer ram_segments.deinit(allocator); + defer ram_segments.deinit(gpa); defer for (ram_segments.items) |segment| { - segment.deinit(allocator); + segment.deinit(gpa); }; { var info_list: std.ArrayList(SegmentInfo) = .empty; - defer info_list.deinit(allocator); + defer info_list.deinit(gpa); - if (use_segments) { + if (cli_args.segments) { var it = elf_header.iterateProgramHeaders(&elf_file_reader); while (try it.next()) |hdr| { if (hdr.p_type == std.elf.PT_LOAD and hdr.p_memsz > 0 and hdr.p_filesz > 0) { - try info_list.append(allocator, .{ + try info_list.append(gpa, .{ .addr = @as(u32, @intCast(hdr.p_paddr)), .file_offset = @as(u32, @intCast(hdr.p_offset)), .size = @as(u32, @intCast(hdr.p_filesz)), @@ -137,7 +134,7 @@ pub fn main() !void { var it = elf_header.iterateSectionHeaders(&elf_file_reader); while (try it.next()) |hdr| { if (hdr.sh_type == std.elf.SHT_PROGBITS and hdr.sh_flags & std.elf.SHF_ALLOC != 0 and hdr.sh_size > 0) { - try info_list.append(allocator, .{ + try info_list.append(gpa, .{ .addr = @as(u32, @intCast(hdr.sh_addr)), .file_offset = @as(u32, @intCast(hdr.sh_offset)), .size = @as(u32, @intCast(hdr.sh_size)), @@ -156,9 +153,9 @@ pub fn main() !void { if ((chip.irom_map_start <= segment_info.addr and segment_info.addr < chip.irom_map_end) or (chip.drom_map_start <= segment_info.addr and segment_info.addr < chip.drom_map_end)) { - try flash_segments.append(allocator, try .init(allocator, segment_info, &elf_file_reader)); + try flash_segments.append(gpa, try .init(gpa, segment_info, &elf_file_reader)); } else { - try ram_segments.append(allocator, try .init(allocator, segment_info, &elf_file_reader)); + try ram_segments.append(gpa, try .init(gpa, segment_info, &elf_file_reader)); } } } @@ -170,8 +167,8 @@ pub fn main() !void { // TODO: maybe also check if sections overlap // merge segments - try do_segment_merge(allocator, &flash_segments); - try do_segment_merge(allocator, &ram_segments); + try do_segment_merge(gpa, &flash_segments); + try do_segment_merge(gpa, &ram_segments); for (flash_segments.items) |segment| { std.log.debug("flash segment at addr 0x{x} of size 0x{x}", .{ segment.addr, segment.size }); @@ -190,15 +187,15 @@ pub fn main() !void { var writer: std.Io.Writer = .fixed(flash_segments.items[0].data); // TODO: override time and date - app_desc.min_efuse_blk_rev_full = min_rev; - app_desc.max_efuse_blk_rev_full = max_rev; + app_desc.min_efuse_blk_rev_full = cli_args.min_rev; + app_desc.max_efuse_blk_rev_full = cli_args.max_rev; app_desc.mmu_page_size = flash_mmu_page_size; app_desc.app_elf_sha256 = elf_file_hash; try writer.writeStruct(app_desc, .little); } } - var segment_data: std.Io.Writer.Allocating = .init(allocator); + var segment_data: std.Io.Writer.Allocating = .init(gpa); defer segment_data.deinit(); var segment_count: u8 = 0; @@ -208,31 +205,31 @@ pub fn main() !void { while (segment.get_flash_align_padding_len(segment_data.writer.end + esp_image.IMAGE_HEADER_LEN, flash_mmu_page_size)) |pad_len| { if (ram_segments.items.len > 0 and pad_len > esp_image.SEGMENT_HEADER_LEN) { const ram_seg = &ram_segments.items[ram_segments.items.len - 1]; - try ram_seg.write_to(allocator, &segment_data.writer, pad_len, &checksum); + try ram_seg.write_to(gpa, &segment_data.writer, pad_len, &checksum); if (ram_seg.size == 0) { ram_segments.items.len -= 1; } } else { - var padding_seg: Segment = try .init_padding(allocator, pad_len); - defer padding_seg.deinit(allocator); - try padding_seg.write_to(allocator, &segment_data.writer, null, &checksum); + var padding_seg: Segment = try .init_padding(gpa, pad_len); + defer padding_seg.deinit(gpa); + try padding_seg.write_to(gpa, &segment_data.writer, null, &checksum); } segment_count += 1; } - try segment.write_to(allocator, &segment_data.writer, null, &checksum); + try segment.write_to(gpa, &segment_data.writer, null, &checksum); segment_count += 1; } for (ram_segments.items) |*segment| { - try segment.write_to(allocator, &segment_data.writer, null, &checksum); + try segment.write_to(gpa, &segment_data.writer, null, &checksum); segment_count += 1; } } - const output_file = try std.fs.cwd().createFile(output_path, .{}); - defer output_file.close(); - var output_file_writer = output_file.writer(&.{}); + const output_file = try std.Io.Dir.cwd().createFile(io, output_path, .{}); + defer output_file.close(io); + var output_file_writer = output_file.writer(io, &.{}); var sha256_hasher = output_file_writer.interface.hashed(Sha256.init(.{}), &output_writer_buf); @@ -248,9 +245,9 @@ pub fn main() !void { .wp = .disabled, .flash_pins_drive_settings = 0, // TODO: figure out what to set this to .chip_id = chip_id, - .min_rev = min_rev, - .max_rev = max_rev, - .hash = !no_digest, + .min_rev = cli_args.min_rev, + .max_rev = cli_args.max_rev, + .hash = !cli_args.no_digest, }; try file_header.write_to(&sha256_hasher.writer); @@ -266,21 +263,21 @@ pub fn main() !void { try sha256_hasher.writer.flush(); - if (!no_digest) { + if (!cli_args.no_digest) { try output_file_writer.interface.writeAll(&sha256_hasher.hasher.finalResult()); try output_file_writer.interface.flush(); } } -fn do_segment_merge(allocator: std.mem.Allocator, segment_list: *std.ArrayList(Segment)) !void { +fn do_segment_merge(gpa: std.mem.Allocator, segment_list: *std.ArrayList(Segment)) !void { if (segment_list.items.len >= 2) { var i: usize = segment_list.items.len - 1; while (i > 0) : (i -= 1) { const seg_a = &segment_list.items[i - 1]; const seg_b = segment_list.items[i]; if (seg_a.addr + seg_a.size == seg_b.addr) { - try seg_a.merge(allocator, seg_b); - seg_b.deinit(allocator); + try seg_a.merge(gpa, seg_b); + seg_b.deinit(gpa); _ = segment_list.orderedRemove(i); } } @@ -301,7 +298,7 @@ const Chip = struct { irom_map_end: usize, drom_map_start: usize, drom_map_end: usize, - supported_flash_mmu_page_sizes: ?[]const esp_image.FlashMMU_PageSize = null, + supported_flash_mmu_page_sizes: ?[]const esp_image.Flash_MMU_PageSize = null, }; const FileHeader = struct { @@ -361,11 +358,11 @@ const Segment = struct { size: usize, data: []u8, - pub fn init(allocator: std.mem.Allocator, segment_info: SegmentInfo, elf_file_reader: *std.fs.File.Reader) !Segment { + pub fn init(gpa: std.mem.Allocator, segment_info: SegmentInfo, elf_file_reader: *std.Io.File.Reader) !Segment { try elf_file_reader.seekTo(segment_info.file_offset); - const data = try allocator.alloc(u8, segment_info.size + segment_info.size % 4); - errdefer allocator.free(data); + const data = try gpa.alloc(u8, segment_info.size + segment_info.size % 4); + errdefer gpa.free(data); try elf_file_reader.interface.readSliceAll(data[0..segment_info.size]); @memset(data[segment_info.size..], 0); @@ -377,9 +374,9 @@ const Segment = struct { }; } - pub fn init_padding(allocator: std.mem.Allocator, size: usize) !Segment { - const data = try allocator.alloc(u8, size); - errdefer allocator.free(data); + pub fn init_padding(gpa: std.mem.Allocator, size: usize) !Segment { + const data = try gpa.alloc(u8, size); + errdefer gpa.free(data); @memset(data, 0); return .{ @@ -389,11 +386,11 @@ const Segment = struct { }; } - pub fn deinit(self: Segment, allocator: std.mem.Allocator) void { - allocator.free(self.data); + pub fn deinit(self: Segment, gpa: std.mem.Allocator) void { + gpa.free(self.data); } - pub fn get_flash_align_padding_len(self: Segment, file_pos: usize, flash_mmu_page_size: esp_image.FlashMMU_PageSize) ?usize { + pub fn get_flash_align_padding_len(self: Segment, file_pos: usize, flash_mmu_page_size: Flash_MMU_PageSize) ?usize { const align_to = flash_mmu_page_size.in_bytes(); const align_past: i32 = @as(i32, @intCast(self.addr % align_to)) - esp_image.SEGMENT_HEADER_LEN; @@ -409,16 +406,16 @@ const Segment = struct { return @intCast(pad_len); } - pub fn merge(self: *Segment, allocator: std.mem.Allocator, other: Segment) !void { + pub fn merge(self: *Segment, gpa: std.mem.Allocator, other: Segment) !void { std.debug.assert(self.addr + self.size == other.addr); const new_size = self.size + other.size; - self.data = try allocator.realloc(self.data, new_size); + self.data = try gpa.realloc(self.data, new_size); @memcpy(self.data[self.size..], other.data[0..other.size]); self.size = new_size; } - pub fn write_to(self: *Segment, allocator: std.mem.Allocator, writer: anytype, len: ?usize, checksum: *u8) !void { + pub fn write_to(self: *Segment, gpa: std.mem.Allocator, writer: anytype, len: ?usize, checksum: *u8) !void { if (self.size != 0) { const consume_len = if (len) |consume_len| @min(self.size, consume_len) else self.size; try writer.writeInt(u32, @intCast(self.addr), .little); @@ -431,7 +428,7 @@ const Segment = struct { const remaining_len = self.size - consume_len; std.mem.copyBackwards(u8, self.data[0..remaining_len], self.data[consume_len..self.size]); - if (allocator.resize(self.data, remaining_len)) { + if (gpa.resize(self.data, remaining_len)) { self.data.len = remaining_len; } diff --git a/tools/esp-image/src/esp_image.zig b/tools/esp-image/src/esp_image.zig index 56f60768b..611de4590 100644 --- a/tools/esp-image/src/esp_image.zig +++ b/tools/esp-image/src/esp_image.zig @@ -6,7 +6,7 @@ const std = @import("std"); pub const SEGMENT_HEADER_LEN = 0x8; pub const IMAGE_HEADER_LEN = 0x18; pub const CHECKSUM_XOR_BYTE = 0xEF; -pub const DEFAULT_FLASH_MMU_PAGE_SIZE: FlashMMU_PageSize = .@"64k"; +pub const DEFAULT_FLASH_MMU_PAGE_SIZE: Flash_MMU_PageSize = .@"64k"; pub const FlashMode = enum(u8) { qio = 0, @@ -30,13 +30,13 @@ pub const FlashFreq = enum(u4) { @"80m" = 3, }; -pub const FlashMMU_PageSize = enum(u8) { +pub const Flash_MMU_PageSize = enum(u8) { @"8k" = 13, @"16k" = 14, @"32k" = 15, @"64k" = 16, - pub fn in_bytes(self: FlashMMU_PageSize) usize { + pub fn in_bytes(self: Flash_MMU_PageSize) usize { return @as(usize, 1) << @intCast(@intFromEnum(self)); } }; @@ -66,7 +66,7 @@ pub const AppDesc = extern struct { app_elf_sha256: [32]u8 = std.mem.zeroes([32]u8), min_efuse_blk_rev_full: u16 = 0, max_efuse_blk_rev_full: u16 = 0xffff, - mmu_page_size: FlashMMU_PageSize = DEFAULT_FLASH_MMU_PAGE_SIZE, + mmu_page_size: Flash_MMU_PageSize = DEFAULT_FLASH_MMU_PAGE_SIZE, reserved1: [3]u8 = std.mem.zeroes([3]u8), reserved2: [18]u32 = std.mem.zeroes([18]u32), }; diff --git a/tools/flags/build.zig b/tools/flags/build.zig new file mode 100644 index 000000000..44e2f388d --- /dev/null +++ b/tools/flags/build.zig @@ -0,0 +1,19 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + const flags_module = b.addModule("flags", .{ + .root_source_file = b.path("src/root.zig"), + .target = target, + .optimize = optimize, + }); + + const unit_tests = b.addTest(.{ + .root_module = flags_module, + }); + + const tests_run = b.addRunArtifact(unit_tests); + const test_step = b.step("test", ""); + test_step.dependOn(&tests_run.step); +} diff --git a/tools/flags/build.zig.zon b/tools/flags/build.zig.zon new file mode 100644 index 000000000..4e9eee514 --- /dev/null +++ b/tools/flags/build.zig.zon @@ -0,0 +1,12 @@ +.{ + .name = .mz_tools_flags, + .version = "0.0.1", + .minimum_zig_version = "0.16.0", + .fingerprint = 0xa32e1a54c66c4a49, + .paths = .{ + "README.md", + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/tools/flags/src/root.zig b/tools/flags/src/root.zig new file mode 100644 index 000000000..272da358d --- /dev/null +++ b/tools/flags/src/root.zig @@ -0,0 +1,78 @@ +//! Opinionated and maintainable flags library for MicroZig. +//! +//! - Flag arguments MUST precede positionals +//! - Flags must be started with `--`, as soon as this isn't the case the parser +//! assumes it's a positional +//! - There must be an '=' joining the flag's label and its value. No spaces. +//! - If there are allocations they are saved to an arena. +const std = @import("std"); +const Allocator = std.mem.Allocator; + +const log = std.log.scoped(.flags); + +/// Positionals are the arguments following any flags. Flags are of the form: +/// +/// ``` +/// --flag= +/// --flag +/// ``` +pub const Positionals = []const []const u8; + +const label_prefix = "--"; + +/// Flags must have a `default` decl. +/// +/// - Integers can use decimal, octal, or hexidecimal formats +pub fn parse(comptime Flags: type, arena: Allocator, args: []const []const u8) !struct { Flags, Positionals } { + _ = arena; + var flags: Flags = .default; + return outer: for (args[1..], 1..) |arg, i| { + if (!std.mem.startsWith(u8, arg, label_prefix)) + break .{ flags, args[i..] }; + + const equals = std.mem.findScalar(u8, arg, '='); + const key = arg[label_prefix.len .. equals orelse arg.len]; + const value = arg[if (equals) |eq| eq + 1 else arg.len..arg.len]; + inline for (@typeInfo(Flags).@"struct".fields) |field| { + if (std.mem.eql(u8, key, field.name)) { + @field(flags, field.name) = try parse_value(field.type, key, value, equals); + continue :outer; + } + } + + log.err("Unrecognied CLI argument: {s}{s}", .{ label_prefix, key }); + return error.UnrecognizedCliArgument; + } else .{ flags, &.{} }; +} + +fn parse_value(comptime T: type, key: []const u8, value: []const u8, equals: ?usize) !T { + const field_info = @typeInfo(T); + return switch (T) { + []const u8 => value, + else => switch (field_info) { + .bool => if (equals != null) try parse_bool(value) else true, + .int => |int| try std.fmt.parseInt(@Int(int.signedness, int.bits), value, 0), + .optional => |optional| if (std.mem.eql(u8, value, "null")) + null + else + try parse_value(optional.child, key, value, equals), + .@"enum" => std.meta.stringToEnum(T, value) orelse { + log.err("Invalid value for {s}: '{s}'", .{ key, value }); + return error.InvalidValue; + }, + else => { + @compileLog(field_info); + @compileError("TODO"); + }, + }, + }; +} + +fn parse_bool(str: []const u8) !bool { + return if (std.mem.eql(u8, str, "true")) + true + else if (std.mem.eql(u8, str, "false")) + false + else + error.InvalidBoolStr; +} From d118ca472c254c1bcd6e0728050c1cbf54cc9c51 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Tue, 26 May 2026 14:02:00 -0700 Subject: [PATCH 10/61] stm32 compiling on 0.16.0 --- build.zig | 9 -- build.zig.zon | 17 +-- core/src/cpus/cortex_m.zig | 47 +++----- core/src/utilities.zig | 7 +- examples/stmicro/stm32/src/stm32f1xx/rcc.zig | 3 +- .../stmicro/stm32/src/stm32f1xx/uart_echo.zig | 4 +- modules/rtt/src/rtt.zig | 54 ++++----- port/gigadevice/gd32/build.zig | 2 +- .../gd32/src/hals/GD32VF103/pins.zig | 54 ++++----- port/microchip/atmega/build.zig | 5 +- port/microchip/attiny/build.zig | 5 +- port/microchip/samd51/build.zig | 6 +- port/nordic/nrf5x/build.zig | 4 +- port/nxp/lpc/build.zig | 2 +- port/nxp/mcx/build.zig | 4 +- port/raspberrypi/rp2xxx/build.zig | 6 +- port/raspberrypi/rp2xxx/src/hal/bootmeta.zig | 4 +- port/raspberrypi/rp2xxx/src/hal/pins.zig | 56 ++++----- port/stmicro/stm32/build.zig | 11 +- port/stmicro/stm32/src/Chips.zig | 5 +- port/stmicro/stm32/src/generate.zig | 43 +++---- .../stmicro/stm32/src/hals/STM32F103/pins.zig | 46 +++----- .../stmicro/stm32/src/hals/STM32F103/uart.zig | 91 ++++++++++++--- .../stmicro/stm32/src/hals/common/pins_v2.zig | 56 ++++----- port/stmicro/stm32/src/hals/common/util.zig | 73 ++++-------- port/texasinstruments/tm4c/build.zig | 6 +- port/texasinstruments/tm4c/src/Chips.zig | 4 +- port/wch/ch32v/build.zig | 2 +- tools/regz/src/embassy.zig | 107 ++++++++---------- website/content/docs/contributing.smd | 11 -- 30 files changed, 330 insertions(+), 414 deletions(-) diff --git a/build.zig b/build.zig index d53f2a621..75a61853f 100644 --- a/build.zig +++ b/build.zig @@ -55,15 +55,6 @@ pub fn build(b: *Build) void { ); b.installArtifact(generate_linker_script_exe); - - const boxzer_dep = b.dependency("boxzer", .{}); - const boxzer_exe = boxzer_dep.artifact("boxzer"); - const boxzer_run = b.addRunArtifact(boxzer_exe); - if (b.args) |args| - boxzer_run.addArgs(args); - - const package_step = b.step("package", "Package monorepo using boxzer"); - package_step.dependOn(&boxzer_run.step); } pub const PortSelect = struct { diff --git a/build.zig.zon b/build.zig.zon index f8335e835..14632863e 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -3,7 +3,7 @@ // Note: This should be changed if you fork microzig! .fingerprint = 0x605a83a849186d0f, .version = "0.15.2", - .minimum_zig_version = "0.15.1", + .minimum_zig_version = "0.16.0", .dependencies = .{ .@"build-internals" = .{ .path = "build-internals" }, .core = .{ .path = "core" }, @@ -42,12 +42,6 @@ .@"port/texasinstruments/msp430" = .{ .path = "port/texasinstruments/msp430", .lazy = true }, .@"port/texasinstruments/tm4c" = .{ .path = "port/texasinstruments/tm4c", .lazy = true }, .@"port/wch/ch32v" = .{ .path = "port/wch/ch32v", .lazy = true }, - - // used for creating package tarballs - .boxzer = .{ - .url = "git+https://codeberg.org/mattnite/boxzer.git#4021540de4b07c11102dd4d46383ce0066f838bb", - .hash = "boxzer-0.1.0--ed-MPrnAAAQAwXnfMJuSkgAsw4FseHEHKcn7OMKXGZS", - }, }, .paths = .{ "README.md", @@ -64,13 +58,4 @@ "drivers", "modules", }, - .boxzer_ignore_paths = .{ - "tools", - "port", - "examples", - "build-internals", - "core", - "drivers", - "modules", - }, } diff --git a/core/src/cpus/cortex_m.zig b/core/src/cpus/cortex_m.zig index 51c223631..cda6eae15 100644 --- a/core/src/cpus/cortex_m.zig +++ b/core/src/cpus/cortex_m.zig @@ -67,25 +67,18 @@ pub const ExternalInterrupt = blk: { if (result_len == 0) break :blk enum {}; - var fields: [result_len]std.builtin.Type.EnumField = undefined; - var field_index: usize = 0; - + var field_names: [result_len][]const u8 = undefined; + var field_values: [result_len]u8 = undefined; + var i: usize = 0; for (microzig.chip.interrupts) |intr| { if (intr.index >= 0) { - fields[field_index] = .{ - .name = intr.name, - .value = intr.index, - }; - field_index += 1; + field_names[i] = intr.name; + field_values[i] = intr.index; + i += 1; } } - break :blk @Type(.{ .@"enum" = .{ - .tag_type = u8, - .fields = &fields, - .decls = &.{}, - .is_exhaustive = true, - } }); + break :blk @Enum(u8, .exhaustive, &field_names, &field_values); }; /// Machine exceptions. @@ -98,30 +91,22 @@ pub const Exception = blk: { var result_len: usize = 0; for (vector_fields) |field| { - if (field.value < 0) result_len += 1; + if (field.value < 0) + result_len += 1; } - if (result_len == 0) break :blk enum {}; - - var fields: [result_len]std.builtin.Type.EnumField = undefined; - var field_index: usize = 0; - + var field_names: [result_len][]const u8 = undefined; + var field_values: [result_len]u4 = undefined; + var i: usize = 0; for (microzig.chip.interrupts) |intr| { if (intr.index < 0) { - fields[field_index] = .{ - .name = intr.name, - .value = 16 + intr.index, // Cortex-M exceptions are mapped to vector table slots 0 - 15 - }; - field_index += 1; + field_names[i] = intr.name; + field_values[i] = 16 + intr.index; // Cortex-M exceptions are mapped to vector table slots 0 - 15 + i += 1; } } - break :blk @Type(.{ .@"enum" = .{ - .tag_type = u4, - .fields = &fields, - .decls = &.{}, - .is_exhaustive = true, - } }); + break :blk @Enum(u4, .exhaustive, &field_names, &field_values); }; pub const interrupt = struct { diff --git a/core/src/utilities.zig b/core/src/utilities.zig index 97c5266d5..65d3323e2 100644 --- a/core/src/utilities.zig +++ b/core/src/utilities.zig @@ -246,9 +246,8 @@ pub fn max_enum_tag(T: type) @typeInfo(T).@"enum".tag_type { } pub fn GenerateInterruptEnum(TagType: type) type { - if (@typeInfo(TagType) != .int) @compileError("expected an int type"); - - if (microzig.chip.interrupts.len == 0) return enum {}; + if (@typeInfo(TagType) != .int) + @compileError("expected an int type"); const count = microzig.chip.interrupts.len; var field_names: [count][]const u8 = undefined; @@ -256,7 +255,7 @@ pub fn GenerateInterruptEnum(TagType: type) type { for (microzig.chip.interrupts, &field_names, &field_values) |interrupt, *field_name, *field_value| { field_name.* = interrupt.name; - field_value.* = interrupt.value; + field_value.* = interrupt.index; } return @Enum(TagType, .exhaustive, &field_names, &field_values); diff --git a/examples/stmicro/stm32/src/stm32f1xx/rcc.zig b/examples/stmicro/stm32/src/stm32f1xx/rcc.zig index 924dd0c4c..9496106fc 100644 --- a/examples/stmicro/stm32/src/stm32f1xx/rcc.zig +++ b/examples/stmicro/stm32/src/stm32f1xx/rcc.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const microzig = @import("microzig"); const stm32 = microzig.hal; @@ -48,7 +49,7 @@ pub fn main() !void { stm32.uart.init_logger(&uart); //the value seen in the uart should be equal to the value of the MCO - try uart.writer().print("sys freq: {d}", .{rcc.get_sys_clk()}); + std.log.info("sys freq: {d}", .{rcc.get_sys_clk()}); MCO.set_output_mode(.alternate_function_push_pull, .max_50MHz); while (true) {} diff --git a/examples/stmicro/stm32/src/stm32f1xx/uart_echo.zig b/examples/stmicro/stm32/src/stm32f1xx/uart_echo.zig index 041ae068a..ae3f3c884 100644 --- a/examples/stmicro/stm32/src/stm32f1xx/uart_echo.zig +++ b/examples/stmicro/stm32/src/stm32f1xx/uart_echo.zig @@ -32,6 +32,8 @@ pub fn main() !void { .clock_speed = rcc.get_clock(.USART1), }); + var uart_writer = uart.writer(&.{}); + var byte: [100]u8 = undefined; //simple USART echo @@ -40,7 +42,7 @@ pub fn main() !void { @memset(&byte, 0); const len = uart.read_blocking(&byte, Duration.from_ms(100)) catch |err| { if (err != error.Timeout) { - uart.writer().print("Got error {any}\n", .{err}) catch unreachable; + uart_writer.intf.print("Got error {any}\n", .{err}) catch unreachable; uart.clear_errors(); } continue; diff --git a/modules/rtt/src/rtt.zig b/modules/rtt/src/rtt.zig index 9956f6141..b2723ad85 100644 --- a/modules/rtt/src/rtt.zig +++ b/modules/rtt/src/rtt.zig @@ -422,39 +422,29 @@ pub const channel = struct { /// /// Fields follow the naming convention "up_buffer_N" for up channels, and "down_buffer_N" for down channels. fn BuildBufferStorageType(comptime up_channels: []const channel.Config, comptime down_channels: []const channel.Config) type { - const fields: []const std.builtin.Type.StructField = comptime v: { - var fields_temp: [up_channels.len + down_channels.len]std.builtin.Type.StructField = undefined; - for (up_channels, 0..) |up_cfg, idx| { - const buffer_type = [up_cfg.buffer_size]u8; - fields_temp[idx] = .{ - .name = std.fmt.comptimePrint("up_buffer_{d}", .{idx}), - .type = buffer_type, - .is_comptime = false, - .alignment = @alignOf(buffer_type), - .default_value_ptr = null, - }; - } - for (down_channels, 0..) |down_cfg, idx| { - const buffer_type = [down_cfg.buffer_size]u8; - fields_temp[up_channels.len + idx] = .{ - .name = std.fmt.comptimePrint("down_buffer_{d}", .{idx}), - .type = buffer_type, - .is_comptime = false, - .alignment = @alignOf(buffer_type), - .default_value_ptr = null, - }; - } - break :v &fields_temp; - }; + const count = up_channels.len + down_channels.len; + var field_names: [count][]const u8 = undefined; + var field_types: [count]type = undefined; + var field_attrs: [count]std.builtin.Type.StructField.Attributes = undefined; + + var i: usize = 0; + for (up_channels, 0..) |up_cfg, idx| { + field_names[i] = std.fmt.comptimePrint("up_buffer_{d}", .{idx}); + field_types[i] = [up_cfg.buffer_size]u8; + field_attrs[i] = .{}; + + i += 1; + } + + for (down_channels, 0..) |down_cfg, idx| { + field_names[i] = std.fmt.comptimePrint("down_buffer_{d}", .{idx}); + field_types[i] = [down_cfg.buffer_size]u8; + field_attrs[i] = .{}; + + i += 1; + } - return @Type(.{ - .@"struct" = .{ - .layout = .@"extern", - .fields = fields, - .decls = &[_]std.builtin.Type.Declaration{}, - .is_tuple = false, - }, - }); + return @Struct(.@"extern", null, &field_names, &field_types, &field_attrs); } /// Creates a control block struct for the given channel configs. Buffer storage is also contained within this struct, although diff --git a/port/gigadevice/gd32/build.zig b/port/gigadevice/gd32/build.zig index 6f5b75ffa..579b5f807 100644 --- a/port/gigadevice/gd32/build.zig +++ b/port/gigadevice/gd32/build.zig @@ -14,7 +14,7 @@ boards: struct { }, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; const hal_f103: microzig.HardwareAbstractionLayer = .{ diff --git a/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig b/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig index 8964e952e..82d55608c 100644 --- a/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig +++ b/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig @@ -83,41 +83,37 @@ pub fn GPIO(comptime port: u3, comptime num: u4, comptime mode: gpio.Mode) type } pub fn Pins(comptime config: GlobalConfiguration) type { - comptime { - var fields: []const StructField = &.{}; - for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { - if (@field(config, port_field.name)) |port_config| { - for (@typeInfo(Port.Configuration).@"struct".fields) |field| { - if (@field(port_config, field.name)) |pin_config| { - var pin_field = StructField{ - .is_comptime = false, - .default_value_ptr = null, - - // initialized below: - .name = undefined, - .type = undefined, - .alignment = undefined, - }; + var count: usize = 0; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { + if (@field(config, port_field.name)) |port_config| { + for (@typeInfo(Port.Configuration).@"struct".fields) |field| { + if (@field(port_config, field.name) != null) { + count += 1; + } + } + } + } - pin_field.name = pin_config.name orelse field.name; - pin_field.type = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); - pin_field.alignment = @alignOf(field.type); + var field_names: [count][]const u8 = undefined; + var field_types: [count]type = undefined; + var field_attrs: [count]std.builtin.Type.StructField.Attributes = undefined; - fields = fields ++ &[_]StructField{pin_field}; - } + var i: usize = 0; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { + if (@field(config, port_field.name)) |port_config| { + for (@typeInfo(Port.Configuration).@"struct".fields) |field| { + if (@field(port_config, field.name)) |pin_config| { + field_names[i] = pin_config.name orelse field.name; + field_types[i] = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); + field_attrs[i] = .{}; + + i += 1; } } } - - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = fields, - .decls = &.{}, - }, - }); } + + return @Struct(.auto, null, &field_names, &field_types, &field_attrs); } pub const Port = enum { diff --git a/port/microchip/atmega/build.zig b/port/microchip/atmega/build.zig index c01b9cbd0..ae12e756c 100644 --- a/port/microchip/atmega/build.zig +++ b/port/microchip/atmega/build.zig @@ -18,11 +18,10 @@ boards: struct { }, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const atpack = b.dependency("atpack", .{}); - + const atpack = b.lazyDependency("atpack", .{}) orelse return null; const avr5_target: std.Target.Query = .{ .cpu_arch = .avr, .cpu_model = .{ .explicit = &std.Target.avr.cpu.avr5 }, diff --git a/port/microchip/attiny/build.zig b/port/microchip/attiny/build.zig index 4cf9150a8..ff5291819 100644 --- a/port/microchip/attiny/build.zig +++ b/port/microchip/attiny/build.zig @@ -13,11 +13,10 @@ boards: struct { }, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const atpack = b.dependency("atpack", .{}); - + const atpack = b.lazyDependdency("atpack", .{}) orelse return null; const avr25_target: std.Target.Query = .{ .cpu_arch = .avr, .cpu_model = .{ .explicit = &std.Target.avr.cpu.avr25 }, diff --git a/port/microchip/samd51/build.zig b/port/microchip/samd51/build.zig index 022fabf8b..2371f82e8 100644 --- a/port/microchip/samd51/build.zig +++ b/port/microchip/samd51/build.zig @@ -9,10 +9,10 @@ chips: struct { boards: struct {}, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const atpack_dep = b.dependency("atpack", .{}); + const atpack = b.lazyDependency("atpack", .{}) orelse return null; const chip_atsamd51j19: microzig.Target = .{ .dep = dep, @@ -28,7 +28,7 @@ pub fn init(dep: *std.Build.Dependency) Self { .name = "ATSAMD51J19A", .url = "https://www.microchip.com/en-us/product/ATSAMD51J19A", .register_definition = .{ - .atdf = atpack_dep.path("samd51a/atdf/ATSAMD51J19A.atdf"), + .atdf = atpack.path("samd51a/atdf/ATSAMD51J19A.atdf"), }, .memory_regions = &.{ .{ .tag = .flash, .offset = 0x00000000, .length = 512 * 1024, .access = .rx }, // Embedded Flash diff --git a/port/nordic/nrf5x/build.zig b/port/nordic/nrf5x/build.zig index f51c41796..1004c36e7 100644 --- a/port/nordic/nrf5x/build.zig +++ b/port/nordic/nrf5x/build.zig @@ -22,10 +22,10 @@ boards: struct { }, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const nrfx = b.dependency("nrfx", .{}); + const nrfx = b.lazyDependency("nrfx", .{}) orelse return null; const hal: microzig.HardwareAbstractionLayer = .{ .root_source_file = b.path("src/hal.zig"), diff --git a/port/nxp/lpc/build.zig b/port/nxp/lpc/build.zig index 5495047e8..70859a90e 100644 --- a/port/nxp/lpc/build.zig +++ b/port/nxp/lpc/build.zig @@ -13,7 +13,7 @@ boards: struct { }, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; const chip_lpc176x5x: microzig.Target = .{ diff --git a/port/nxp/mcx/build.zig b/port/nxp/mcx/build.zig index 04577d640..129124b1b 100644 --- a/port/nxp/mcx/build.zig +++ b/port/nxp/mcx/build.zig @@ -13,10 +13,10 @@ boards: struct { frdm_mcxn947: *const microzig.Target, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const mcux_soc_svd = b.dependency("mcux-soc-svd", .{}); + const mcux_soc_svd = b.lazyDependency("mcux-soc-svd", .{}) orelse return null; const chip_mcxa153: microzig.Target = .{ .dep = dep, diff --git a/port/raspberrypi/rp2xxx/build.zig b/port/raspberrypi/rp2xxx/build.zig index 5242b7458..2cb9aaa95 100644 --- a/port/raspberrypi/rp2xxx/build.zig +++ b/port/raspberrypi/rp2xxx/build.zig @@ -30,11 +30,11 @@ boards: struct { }, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; const riscv32_common_dep = b.dependency("microzig/modules/riscv32-common", .{}); - const pico_sdk = b.dependency("pico-sdk", .{}); + const pico_sdk = b.lazyDependency("pico-sdk", .{}) orelse return null; const bounded_array_dep = b.dependency("bounded-array", .{}); const hal: microzig.HardwareAbstractionLayer = .{ @@ -330,7 +330,7 @@ fn get_bootrom(b: *std.Build, target: *const microzig.Target, rom: BootROM) std. //rom_exe.linkage = .static; rom_exe.build_id = .none; rom_exe.setLinkerScript(b.path(b.fmt("src/bootroms/{s}/shared/stage2.ld", .{target.chip.name}))); - rom_exe.addAssemblyFile(b.path(b.fmt("src/bootroms/{s}/{s}.S", .{ target.chip.name, @tagName(rom) }))); + rom_exe.root_module.addAssemblyFile(b.path(b.fmt("src/bootroms/{s}/{s}.S", .{ target.chip.name, @tagName(rom) }))); rom_exe.entry = .{ .symbol_name = "_stage2_boot" }; const rom_objcopy = b.addObjCopy(rom_exe.getEmittedBin(), .{ diff --git a/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig b/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig index 4c8f2cafc..4d63925a8 100644 --- a/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig +++ b/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig @@ -60,12 +60,12 @@ pub fn Block(Items: type) type { }; } -pub const ImageDef = packed struct { +pub const ImageDef = packed struct(u32) { item_type: u8 = 0x42, block_size: u8 = 0x01, image_type_flags: ImageTypeFlags, - pub const ImageTypeFlags = packed struct { + pub const ImageTypeFlags = packed struct(u16) { image_type: ImageType, exe_security: ExeSecurity, reserved0: u2 = 0, diff --git a/port/raspberrypi/rp2xxx/src/hal/pins.zig b/port/raspberrypi/rp2xxx/src/hal/pins.zig index a5a850722..9eb711bca 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pins.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pins.zig @@ -767,44 +767,38 @@ pub const GlobalConfiguration = struct { } pub fn PinsType(self: GlobalConfiguration) type { - var fields: []const StructField = &.{}; + var count: usize = 0; for (@typeInfo(GlobalConfiguration).@"struct".fields) |field| { - if (@field(self, field.name)) |pin_config| { - var pin_field = StructField{ - .is_comptime = false, - .default_value_ptr = null, - - // initialized below: - .name = undefined, - .type = undefined, - .alignment = undefined, - }; + if (@field(self, field.name) != null) { + count += 1; + } + } - pin_field.name = pin_config.name orelse field.name; - if (pin_config.function == .SIO) { - pin_field.type = gpio.Pin; - } else if (pin_config.function.is_pwm()) { - pin_field.type = pwm.Pwm; - } else if (pin_config.function.is_adc()) { - pin_field.type = adc.Input; - } else { - continue; - } + var field_names: [count][]const u8 = undefined; + var field_types: [count]type = undefined; + var field_attrs: [count]std.builtin.Type.StructField.Attributes = undefined; - pin_field.alignment = @alignOf(field.type); + var i: usize = 0; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |field| { + if (@field(self, field.name)) |pin_config| { + field_names[i] = pin_config.name orelse field.name; + field_attrs[i] = .{}; + field_types[i] = if (pin_config.function == .SIO) + gpio.Pin + else if (pin_config.function.is_pwm()) + pwm.Pwm + else if (pin_config.function.is_adc()) + adc.Input + else + // TODO: what does this mean? should this be a compilation + // error? + continue; - fields = fields ++ &[_]StructField{pin_field}; + i += 1; } } - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = fields, - .decls = &.{}, - }, - }); + return @Struct(.auto, null, &field_names, &field_types, &field_attrs); } /// Populate and return the PinsType struct diff --git a/port/stmicro/stm32/build.zig b/port/stmicro/stm32/build.zig index c97e326d3..d4ea01374 100644 --- a/port/stmicro/stm32/build.zig +++ b/port/stmicro/stm32/build.zig @@ -14,20 +14,19 @@ boards: struct { stm32f303nucleo: *const microzig.Target, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const clockhelper_dep = b.dependency("ClockHelper", .{}).module("clockhelper"); - + const clockhelper_dep = b.lazyDependency("ClockHelper", .{}) orelse return null; + const clockhelper_module = clockhelper_dep.module("clockhelper"); const hal_imports: []std.Build.Module.Import = b.allocator.dupe(std.Build.Module.Import, &.{ .{ .name = "ClockTree", - .module = clockhelper_dep, + .module = clockhelper_module, }, }) catch @panic("out of memory"); - const chips = Chips.init(dep, hal_imports); - + const chips = Chips.init(dep, hal_imports) orelse return null; return .{ .chips = chips, .boards = .{ diff --git a/port/stmicro/stm32/src/Chips.zig b/port/stmicro/stm32/src/Chips.zig index 21ed3b635..eb0357b87 100644 --- a/port/stmicro/stm32/src/Chips.zig +++ b/port/stmicro/stm32/src/Chips.zig @@ -1407,9 +1407,10 @@ STM32WLE5J8: *microzig.Target, STM32WLE5JB: *microzig.Target, STM32WLE5JC: *microzig.Target, -pub fn init(dep: *std.Build.Dependency, hal_imports: []std.Build.Module.Import) Self { +pub fn init(dep: *std.Build.Dependency, hal_imports: []std.Build.Module.Import) ?Self { const b = dep.builder; - const embassy = b.dependency("stm32-data-generated", .{}).path("."); + const embassy_dep = b.lazyDependency("stm32-data-generated", .{}) orelse return null; + const embassy = embassy_dep.path("."); var ret: Self = undefined; ret.STM32C011D6 = b.allocator.create(microzig.Target) catch @panic("out of memory"); diff --git a/port/stmicro/stm32/src/generate.zig b/port/stmicro/stm32/src/generate.zig index fc22c17d3..5ba27bccc 100644 --- a/port/stmicro/stm32/src/generate.zig +++ b/port/stmicro/stm32/src/generate.zig @@ -6,17 +6,10 @@ pub const std_options = std.Options{ .log_level = .info, }; -pub fn main() !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - - var arena = std.heap.ArenaAllocator.init(gpa.allocator()); - defer arena.deinit(); - - const allocator = arena.allocator(); - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); - +pub fn main(init: std.process.Init) !void { + const io = init.io; + const allocator = init.arena.allocator(); + const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len < 2) return error.InvalidArgs; @@ -24,11 +17,11 @@ pub fn main() !void { std.log.info("package path: {s}", .{package_path}); - var package_dir = try std.fs.cwd().openDir(package_path, .{}); - defer package_dir.close(); + var package_dir = try std.Io.Dir.cwd().openDir(io, package_path, .{}); + defer package_dir.close(io); - var data_dir = try package_dir.openDir("data", .{}); - defer data_dir.close(); + var data_dir = try package_dir.openDir(io, "data", .{}); + defer data_dir.close(io); var chip_files = std.array_list.Managed(std.json.Parsed(ChipFile)).init(allocator); defer { @@ -37,17 +30,17 @@ pub fn main() !void { chip_files.deinit(); } - var chips_dir = try data_dir.openDir("chips", .{ .iterate = true }); - defer chips_dir.close(); + var chips_dir = try data_dir.openDir(io, "chips", .{ .iterate = true }); + defer chips_dir.close(io); var it = chips_dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) continue; std.log.info("file: {s}", .{entry.name}); - const chip_file_text = try chips_dir.readFileAlloc(allocator, entry.name, std.math.maxInt(usize)); + const chip_file_text = try chips_dir.readFileAlloc(io, entry.name, allocator, .unlimited); defer allocator.free(chip_file_text); var scanner = std.json.Scanner.initCompleteInput(allocator, chip_file_text); @@ -70,12 +63,11 @@ pub fn main() !void { // sort to try to keep things somewhat in order std.sort.insertion(std.json.Parsed(ChipFile), chip_files.items, {}, ChipFile.less_than); - const chips_file = try std.fs.cwd().createFile("src/Chips.zig", .{}); - - defer chips_file.close(); + const chips_file = try std.Io.Dir.cwd().createFile(io, "src/Chips.zig", .{}); + defer chips_file.close(io); var buf: [4096]u8 = undefined; - var writer = chips_file.writer(&buf); + var writer = chips_file.writer(io, &buf); try generate_chips_file(allocator, &writer.interface, chip_files.items); } @@ -108,9 +100,10 @@ fn generate_chips_file( try writer.writeAll( \\ - \\pub fn init(dep: *std.Build.Dependency, hal_imports: []std.Build.Module.Import) Self { + \\pub fn init(dep: *std.Build.Dependency, hal_imports: []std.Build.Module.Import) ?Self { \\ const b = dep.builder; - \\ const embassy = b.dependency("stm32-data-generated", .{}).path("."); + \\ const embassy_dep = b.lazyDependency("stm32-data-generated", .{}) orelse return null; + \\ const embassy = embassy_dep.path("."); \\ var ret: Self = undefined; \\ \\ diff --git a/port/stmicro/stm32/src/hals/STM32F103/pins.zig b/port/stmicro/stm32/src/hals/STM32F103/pins.zig index addd87f7a..2d993de05 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/pins.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/pins.zig @@ -83,41 +83,25 @@ pub fn GPIO(comptime port: u3, comptime num: u4, comptime mode: gpio.Mode) type } pub fn Pins(comptime config: GlobalConfiguration) type { - comptime { - var fields: []const StructField = &.{}; - for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { - if (@field(config, port_field.name)) |port_config| { - for (@typeInfo(Port.Configuration).@"struct".fields) |field| { - if (@field(port_config, field.name)) |pin_config| { - var pin_field = StructField{ - .is_comptime = false, - .default_value_ptr = null, - - // initialized below: - .name = undefined, - .type = undefined, - .alignment = undefined, - }; - - pin_field.name = pin_config.name orelse field.name; - pin_field.type = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); - pin_field.alignment = @alignOf(field.type); - - fields = fields ++ &[_]StructField{pin_field}; - } + const Attributes = std.builtin.Type.StructField.Attributes; + var field_names: []const []const u8 = &.{}; + var field_types: []const type = &.{}; + var field_attrs: []const std.builtin.Type.StructField.Attributes = &.{}; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { + if (@field(config, port_field.name)) |port_config| { + for (@typeInfo(Port.Configuration).@"struct".fields) |field| { + if (@field(port_config, field.name)) |pin_config| { + const name: []const u8 = pin_config.name orelse field.name; + const typ: type = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); + field_names = field_names ++ .{name}; + field_types = field_types ++ .{typ}; + field_attrs = field_attrs ++ .{Attributes{}}; } } } - - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = fields, - .decls = &.{}, - }, - }); } + + return @Struct(.auto, null, field_names, field_types[0..], field_attrs[0..]); } pub const Port = enum { diff --git a/port/stmicro/stm32/src/hals/STM32F103/uart.zig b/port/stmicro/stm32/src/hals/STM32F103/uart.zig index 3a2a373e1..2cfae299f 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/uart.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/uart.zig @@ -6,6 +6,8 @@ const time = @import("time.zig"); const microzig = @import("microzig"); const enums = @import("../common/enums.zig"); +const assert = std.debug.assert; + const mdf = microzig.drivers; const drivers = mdf.base; const Duration = mdf.time.Duration; @@ -87,9 +89,6 @@ fn comptime_fail_or_error(msg: []const u8, fmt_args: anytype, err: ConfigError) pub const Instances = enums.UART_Type; pub const UART = struct { - pub const Writer = std.io.GenericWriter(*const UART, TransmitError, generic_writer_fn); - pub const Reader = std.io.GenericReader(*const UART, ReceiveError, generic_reader_fn); - regs: *volatile USART_Peripheral, ///Returns an error at runtime, and raises a compile error at comptime. fn validate_baudrate(baud_rate: u32, peri_freq: u32) ConfigError!void { @@ -296,19 +295,79 @@ pub const UART = struct { return uart.readv_blocking(&.{data}, timeout); } - pub fn writer(uart: *const UART) Writer { - return .{ .context = uart }; + pub fn writer(uart: *const UART, buffer: []u8) Writer { + return Writer{ + .uart = uart, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .drain = drain, + }, + }, + }; } - pub fn reader(uart: *const UART) Reader { - return .{ .context = uart }; + pub fn reader(uart: *const UART, buffer: []u8) Reader { + return .{ + .uart = uart, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .stream = stream, + }, + }, + }; } - fn generic_writer_fn(uart: *const UART, buffer: []const u8) TransmitError!usize { - return uart.write_blocking(buffer, null); + + pub const Writer = struct { + uart: *const UART, + intf: std.Io.Writer, + }; + + pub const Reader = struct { + uart: *const UART, + intf: std.Io.Reader, + }; + + fn drain(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { + const uart_writer: *Writer = @fieldParentPtr("intf", w); + const uart = uart_writer.uart; + + // bytes from buffer are not included in count. + w.end -= uart.write_blocking(w.buffer[0..w.end], null) catch |err| switch (err) { + error.Timeout => unreachable, + }; + assert(w.end == 0); + + var n: usize = 0; + n += uart.writev_blocking(data[0 .. data.len - 1], null) catch |err| switch (err) { + error.Timeout => unreachable, + }; + for (0..splat) |_| + n += uart.write_blocking(data[data.len - 1], null) catch |err| switch (err) { + error.Timeout => unreachable, + }; + + return n; } - fn generic_reader_fn(uart: *const UART, buffer: []u8) ReceiveError!usize { - return uart.read_blocking(buffer, null); + fn stream(io_reader: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { + const r: *Reader = @fieldParentPtr("intf", io_reader); + return switch (limit) { + .nothing => 0, + else => blk: { + var buf: [1]u8 = undefined; + const n = r.uart.read_blocking(&buf, null) catch |err| switch (err) { + error.ReceiveError => return error.ReadError, + }; + + break :blk switch (n) { + 0 => 0, + 1 => try w.writeByte(buf[0]), + else => unreachable, + }; + }, + }; } pub fn init(comptime uart: Instances) UART { @@ -325,9 +384,9 @@ var uart_logger: ?UART.Writer = null; /// .logFn = hal.uart.log, /// }; pub fn init_logger(uart: *const UART) void { - uart_logger = uart.writer(); - if (uart_logger) |logger| { - logger.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; + uart_logger = uart.writer(&.{}); + if (uart_logger) |*writer| { + writer.intf.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; } } @@ -342,7 +401,7 @@ pub fn log(comptime level: std.log.Level, comptime scope: @TypeOf(.EnumLiteral), else => " (" ++ @tagName(scope) ++ "): ", }; - if (uart_logger) |uart| { - uart.print(prefix ++ format ++ "\r\n", args) catch {}; + if (uart_logger) |*writer| { + writer.intf.print(prefix ++ format ++ "\r\n", args) catch {}; } } diff --git a/port/stmicro/stm32/src/hals/common/pins_v2.zig b/port/stmicro/stm32/src/hals/common/pins_v2.zig index 198831cfd..1aacb9e6a 100644 --- a/port/stmicro/stm32/src/hals/common/pins_v2.zig +++ b/port/stmicro/stm32/src/hals/common/pins_v2.zig @@ -148,42 +148,36 @@ pub fn GPIO(comptime mode: gpio.Mode) type { } pub fn Pins(comptime config: GlobalConfiguration) type { - comptime { - var fields: []const StructField = &.{}; - for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { - if (@field(config, port_field.name)) |port_config| { - for (@typeInfo(Port.Configuration).@"struct".fields) |field| { - if (@field(port_config, field.name)) |pin_config| { - var pin_field = StructField{ - .is_comptime = false, - .default_value_ptr = null, - - // initialized below: - .name = undefined, - .type = undefined, - .alignment = undefined, - }; - - const default_name = "P" ++ port_field.name[4..5] ++ field.name[3..]; - pin_field.name = pin_config.name orelse default_name; - pin_field.type = GPIO(pin_config.mode orelse .{ .input = .{.floating} }); - pin_field.alignment = @alignOf(field.type); - - fields = fields ++ &[_]StructField{pin_field}; - } + var count: usize = 0; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { + if (@field(config, port_field.name)) |port_config| { + for (@typeInfo(Port.Configuration).@"struct".fields) |field| { + if (@field(port_config, field.name) != null) { + count += 1; } } } + } - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = fields, - .decls = &.{}, - }, - }); + var field_names: [count][]const u8 = undefined; + var field_types: [count]type = undefined; + var field_attrs: [count]std.builtin.Type.StructField.Attributes = undefined; + var i: usize = 0; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { + if (@field(config, port_field.name)) |port_config| { + for (@typeInfo(Port.Configuration).@"struct".fields) |field| { + if (@field(port_config, field.name)) |pin_config| { + const default_name = "P" ++ port_field.name[4..5] ++ field.name[3..]; + field_names[i] = pin_config.name orelse default_name; + field_types[i] = GPIO(pin_config.mode orelse .{ .input = .{.floating} }); + field_attrs[i] = .{}; + i += 1; + } + } + } } + + return @Struct(.auto, null, &field_names, &field_types, &field_attrs); } pub const Port = enum { diff --git a/port/stmicro/stm32/src/hals/common/util.zig b/port/stmicro/stm32/src/hals/common/util.zig index 8713df969..1619e18b1 100644 --- a/port/stmicro/stm32/src/hals/common/util.zig +++ b/port/stmicro/stm32/src/hals/common/util.zig @@ -12,69 +12,36 @@ pub fn match_name(heystack: []const u8, needles: []const []const u8) bool { } pub fn create_peripheral_enum(comptime bases_name: []const []const u8) type { - var names: [70]std.builtin.Type.EnumField = undefined; - var names_index = 0; - const peripheral = @typeInfo(peripherals); + var field_names: []const []const u8 = &.{}; + var field_values: []const usize = &.{}; @setEvalBranchQuota(10_000); - switch (peripheral) { - .@"struct" => |data| { - for (data.decls) |decls| { - const decl_name = decls.name; - if (match_name(decl_name, bases_name)) { - names[names_index] = std.builtin.Type.EnumField{ - .name = decls.name, - .value = names_index, - }; - names_index += 1; - } - } - }, - else => unreachable, + for (@typeInfo(peripherals).@"struct".decls, 0..) |decl, i| { + if (match_name(decl.name, bases_name)) { + field_names = field_names ++ .{decl.name}; + field_values = field_values ++ .{i}; + } } - const peri_enum = std.builtin.Type{ .@"enum" = .{ - .tag_type = usize, - .is_exhaustive = true, - .decls = &[_]std.builtin.Type.Declaration{}, - .fields = names[0..names_index], - } }; - - return @Type(peri_enum); + return @Enum(usize, .exhaustive, field_names, field_values[0..]); } pub fn sub_peripheral_enum(comptime T: type, comptime keep_name: []const []const u8, match_type: ?[]const u8) type { - const enum_info = @typeInfo(T); - var names_index = 0; - - var names: [10]std.builtin.Type.EnumField = undefined; - + var field_names: []const []const u8 = &.{}; + var field_values: []const usize = &.{}; @setEvalBranchQuota(10_000); - switch (enum_info) { - .@"enum" => |data| { - for (data.fields) |field| { - if (match_name(field.name, keep_name)) { - if (match_type) |match| { - const type_name = @typeName(@TypeOf(@field(peripherals, field.name))); - _ = std.mem.indexOf(u8, type_name, match) orelse continue; - } - names[names_index] = std.builtin.Type.EnumField{ - .name = field.name, - .value = field.value, - }; - names_index += 1; - } + for (@typeInfo(T).@"enum".fields) |field| { + if (match_name(field.name, keep_name)) { + if (match_type) |match| { + const type_name = @typeName(@TypeOf(@field(peripherals, field.name))); + _ = std.mem.indexOf(u8, type_name, match) orelse continue; } - }, - else => unreachable, + + field_names = field_names ++ .{field.name}; + field_values = field_values ++ .{field.value}; + } } - const new_enum = std.builtin.Type{ .@"enum" = .{ - .tag_type = usize, - .is_exhaustive = true, - .decls = &[_]std.builtin.Type.Declaration{}, - .fields = names[0..names_index], - } }; - return @Type(new_enum); + return @Enum(usize, .exhaustive, field_names, field_values[0..]); } pub fn load_timer_interrupt(handler: *const fn () callconv(.c) void) microzig.cpu.InterruptOptions { diff --git a/port/texasinstruments/tm4c/build.zig b/port/texasinstruments/tm4c/build.zig index 3a4d193f6..65fa782dc 100644 --- a/port/texasinstruments/tm4c/build.zig +++ b/port/texasinstruments/tm4c/build.zig @@ -11,8 +11,8 @@ const Boards = struct { launch_pad_tm4c123g: *microzig.Target, }; -pub fn init(dep: *std.Build.Dependency) Self { - const chips = Chips.init(dep); +pub fn init(dep: *std.Build.Dependency) ?Self { + const chips = Chips.init(dep) orelse return null; const boards = Boards{ .launch_pad_tm4c123g = chips.TM4C123GH6PM.derive(.{ .board = .{ @@ -30,7 +30,7 @@ pub fn init(dep: *std.Build.Dependency) Self { } pub fn build(b: *std.Build) void { - const ti_data = b.dependency("ti_data", .{}); + const ti_data = b.lazyDependency("ti_data", .{}) orelse return; const targetdb = ti_data.path("targetdb"); const generate_optimize = .ReleaseSafe; diff --git a/port/texasinstruments/tm4c/src/Chips.zig b/port/texasinstruments/tm4c/src/Chips.zig index f18484d4c..fff82798c 100644 --- a/port/texasinstruments/tm4c/src/Chips.zig +++ b/port/texasinstruments/tm4c/src/Chips.zig @@ -5,9 +5,9 @@ const Self = @This(); TM4C123GH6PM: *microzig.Target, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const ti_data = b.dependency("ti_data", .{}); + const ti_data = b.lazyDependency("ti_data", .{}) orelse return null; const targetdb = ti_data.path("targetdb"); var ret: Self = undefined; diff --git a/port/wch/ch32v/build.zig b/port/wch/ch32v/build.zig index 71f1c917e..8f0a60b89 100644 --- a/port/wch/ch32v/build.zig +++ b/port/wch/ch32v/build.zig @@ -108,7 +108,7 @@ boards: struct { }, }, -pub fn init(dep: *std.Build.Dependency) Self { +pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; const chip_ch32v003_base: BaseChip = .{ diff --git a/tools/regz/src/embassy.zig b/tools/regz/src/embassy.zig index d52e792b7..d736f6f8d 100644 --- a/tools/regz/src/embassy.zig +++ b/tools/regz/src/embassy.zig @@ -1,3 +1,8 @@ +const std = @import("std"); +const Database = @import("Database.zig"); +const Arch = @import("arch.zig").Arch; +const arm = @import("arch/arm.zig"); + pub const core_to_cpu = std.StaticStringMap([]const u8).initComptime(&.{ .{ "cm0", "cortex_m0" }, .{ "cm0p", "cortex_m0plus" }, @@ -217,11 +222,6 @@ pub fn load_into_db(db: *Database, io: std.Io, path: []const u8, device: ?[]cons var registers_dir = try data_dir.openDir(io, "registers", .{ .iterate = true }); defer registers_dir.close(io); - //This holds extra data for extended registers - var extends_list_arena = std.heap.ArenaAllocator.init(allocator); - defer extends_list_arena.deinit(); - const extends_list_allocator = extends_list_arena.allocator(); - it = registers_dir.iterate(); while (try it.next(io)) |entry| { if (entry.kind != .file) @@ -246,7 +246,7 @@ pub fn load_into_db(db: *Database, io: std.Io, path: []const u8, device: ?[]cons }); errdefer register_file.deinit(); - try handle_extends(allocator, extends_list_allocator, ®ister_file.value); + try handle_extends(allocator, ®ister_file.value); const register_name = try allocator.dupe(u8, entry.name[0 .. entry.name.len - std.fs.path.extension(entry.name).len]); try register_files.put(allocator, register_name, register_file); @@ -590,51 +590,45 @@ pub fn load_into_db(db: *Database, io: std.Io, path: []const u8, device: ?[]cons } } -/// Reads throught the json data handles the "extends" inheritance. -fn handle_extends(allocator: std.mem.Allocator, extends_allocator: std.mem.Allocator, root_json: *std.json.Value) !void { - // TODO: fix later - _ = allocator; - _ = extends_allocator; - _ = root_json; - //var root_json_clone = std.json.Value{ .object = try root_json.object.clone(extends_allocator) }; - //var itr = root_json.object.iterator(); - //while (itr.next()) |entry| { - // const item_name = entry.key_ptr.*; - // const item_value = entry.value_ptr; - - // if (item_value.*.object.contains("extends")) { - - // // This Collects unique items from the ancestors. - // var arr: std.json.ObjectMap = std.json.ObjectMap.init(allocator); - // defer arr.deinit(); - - // // Get child value and kind holder of inherting items - // var child = root_json.object.get(item_name).?; - // const list_name = get_section(item_name); - - // // Add child items to dictionary so they are not overwritten. - // for (child.object.get(list_name).?.array.items) |child_item| { - // const child_item_name = child_item.object.get("name").?.string; - // try arr.put(child_item_name, child_item); - // } - - // // Handle all parents and grandparents of the current child. - // try resolve_inheritance_recursively(allocator, &root_json_clone, item_name, &arr); - - // // Replacement items will go here and should be released via the arena extends allocator - // var new_list = std.json.Array.init(extends_allocator); - // for (arr.values()) |value| { - // try new_list.append(value); - // } - // try child.object.put(list_name, std.json.Value{ .array = new_list }); - // try root_json_clone.object.put(item_name, child); - // } - //} - //root_json.* = root_json_clone; +/// Reads through the json data handles the "extends" inheritance. +fn handle_extends(gpa: std.mem.Allocator, root_json: *std.json.Value) !void { + var it = root_json.object.iterator(); + while (it.next()) |entry| { + const item_name = entry.key_ptr.*; + const item_value = entry.value_ptr; + + if (item_value.*.object.contains("extends")) { + + // This Collects unique items from the ancestors. + var arr: std.json.ObjectMap = .empty; + defer arr.deinit(gpa); + + // Get child value and kind holder of inherting items + var child = root_json.object.get(item_name).?; + const list_name = get_section(item_name); + + // Add child items to dictionary so they are not overwritten. + for (child.object.get(list_name).?.array.items) |child_item| { + const child_item_name = child_item.object.get("name").?.string; + try arr.put(gpa, child_item_name, child_item); + } + + // Handle all parents and grandparents of the current child. + try resolve_inheritance_recursively(gpa, root_json, item_name, &arr); + + var new_list = std.json.Array.init(gpa); + for (arr.values()) |value| { + try new_list.append(value); + } + + try child.object.put(gpa, list_name, std.json.Value{ .array = new_list }); + try root_json.object.put(gpa, item_name, child); + } + } } // General function to handle inheritance -fn resolve_inheritance_recursively(allocator: std.mem.Allocator, json_data: *std.json.Value, child_full_name: []const u8, accumulator: *std.json.ObjectMap) !void { +fn resolve_inheritance_recursively(gpa: std.mem.Allocator, json_data: *std.json.Value, child_full_name: []const u8, accumulator: *std.json.ObjectMap) !void { const child = json_data.object.get(child_full_name).?; const list_name = get_section(child_full_name); @@ -643,31 +637,31 @@ fn resolve_inheritance_recursively(allocator: std.mem.Allocator, json_data: *std if (extended) |parent_unqualified_name| { //Get access to the parent and its list of items. - const parent = try get_parent(allocator, json_data, child_full_name, parent_unqualified_name.string); + const parent = try get_parent(gpa, json_data, child_full_name, parent_unqualified_name.string); const parent_section_array = parent.value_ptr.object.get(list_name).?.array; // If our dictionary doesn't contain an item present in the child add it to the list for (parent_section_array.items) |parent_element| { const parent_element_name = if (parent_element.object.get("name")) |name| name.string else @panic("No Name exist in array properties"); if (!accumulator.contains(parent_element_name)) { - try accumulator.put(parent_element_name, parent_element); + try accumulator.put(gpa, parent_element_name, parent_element); } } if (parent.value_ptr.object.contains("extends")) { - try resolve_inheritance_recursively(allocator, json_data, parent.key_ptr.*, accumulator); + try resolve_inheritance_recursively(gpa, json_data, parent.key_ptr.*, accumulator); } } } -fn get_parent(allocator: std.mem.Allocator, json_data: *std.json.Value, child_full_name: []const u8, parent_name: []const u8) !std.json.ObjectMap.Entry { +fn get_parent(gpa: std.mem.Allocator, json_data: *std.json.Value, child_full_name: []const u8, parent_name: []const u8) !std.json.ObjectMap.Entry { //Get Family name eg Block, Fieldset var name_iterator = std.mem.splitScalar(u8, child_full_name, '/'); const family_name = name_iterator.first(); //Get qualified parent name - const parent_full_name = try std.fmt.allocPrint(allocator, "{s}/{s}", .{ family_name, parent_name }); - defer allocator.free(parent_full_name); + const parent_full_name = try std.fmt.allocPrint(gpa, "{s}/{s}", .{ family_name, parent_name }); + defer gpa.free(parent_full_name); return json_data.object.getEntry(parent_full_name).?; } @@ -698,8 +692,3 @@ fn get_section(child_full_name: []const u8) []const u8 { } @panic("Unhandled extends Type"); } - -const std = @import("std"); -const Database = @import("Database.zig"); -const Arch = @import("arch.zig").Arch; -const arm = @import("arch/arm.zig"); diff --git a/website/content/docs/contributing.smd b/website/content/docs/contributing.smd index f37796330..458129620 100644 --- a/website/content/docs/contributing.smd +++ b/website/content/docs/contributing.smd @@ -53,17 +53,6 @@ Here is an overview of the top level directories of the monorepo: for flashing MCUs. - `website`: This website, which is built using [zine](https://zine-ssg.io). -### Packaging - -MicroZig does not force users to download the entire codebase if they use a -released version. This is done through a small project called -[boxzer](https://github.com/mattnite/boxzer), which creates a separate tarball -for each package in MicroZig. With the use of lazy dependencies in the Zig -build system, a user will download the `esp` package for their hardware, but -nothing related to `stm32`. This will enable us to support a lot of hardware -without MicroZig users needing to download gigabytes everytime they run their -CI. - ## Naming Sub-packages We try to keep package names identical to their path in the project, with From f1a48227bb2cfccb022dfb255bd105ced969a077 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 27 May 2026 17:29:29 -0700 Subject: [PATCH 11/61] rp2xxx and ch32v compiling on 0.16.0 --- core/src/core/usb.zig | 33 ++++-- core/src/utilities.zig | 2 +- drivers/base/DateTime.zig | 2 +- examples/raspberrypi/rp2xxx/build.zig | 25 ++-- examples/raspberrypi/rp2xxx/src/uart_echo.zig | 2 +- modules/rtt/src/rtt.zig | 2 +- port/nordic/nrf5x/src/hal/uart.zig | 11 +- port/raspberrypi/rp2xxx/src/hal/bootmeta.zig | 4 +- port/raspberrypi/rp2xxx/src/hal/pins.zig | 26 ++--- port/raspberrypi/rp2xxx/src/hal/uart.zig | 107 ++++++++++++++---- port/wch/ch32v/src/hals/ch32v003/pins.zig | 46 +++----- port/wch/ch32v/src/hals/pins.zig | 47 +++----- port/wch/ch32v/src/hals/usart.zig | 102 ++++++++++++++--- 13 files changed, 258 insertions(+), 151 deletions(-) diff --git a/core/src/core/usb.zig b/core/src/core/usb.zig index a3f45b76e..3328b0b6d 100644 --- a/core/src/core/usb.zig +++ b/core/src/core/usb.zig @@ -61,6 +61,11 @@ pub const DescriptorAllocator = struct { ret = ret ++ [1]descriptor.String{.from_str(s)}; return ret; } + + pub fn to_const(self: *DescriptorAllocator) DescriptorAllocator { + defer self.* = undefined; + return self.*; + } }; /// Wraps a Descriptor type. Returned by the `create` method of the Descriptor. @@ -243,6 +248,9 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { assert(std.math.isPowerOfTwo(max_psize)); var alloc: DescriptorAllocator = .init(config.unique_endpoints); + const manufacturer_s = alloc.string(config.vendor.str); + const product_s = alloc.string(config.product.str); + const serial_s = alloc.string(config.serial); const desc_device: descriptor.Device = .{ .bcd_usb = config.bcd_usb, @@ -251,9 +259,9 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { .vendor = .from(config.vendor.id), .product = .from(config.product.id), .bcd_device = config.bcd_device, - .manufacturer_s = alloc.string(config.vendor.str), - .product_s = alloc.string(config.product.str), - .serial_s = alloc.string(config.serial), + .manufacturer_s = manufacturer_s, + .product_s = product_s, + .serial_s = serial_s, .num_configurations = config.configurations.len, }; const configuration_s = alloc.string(config0.name); @@ -261,14 +269,14 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { var size = @sizeOf(descriptor.Configuration); var field_names: [driver_fields.len][:0]const u8 = undefined; var field_types: [field_names.len]type = undefined; - var field_attrs: [field_names.len]std.builtin.StructField.Attributes = undefined; + var field_attrs: [field_names.len]std.builtin.Type.StructField.Attributes = undefined; var ep_handler_types: [2][16]type = @splat(@splat(void)); var ep_handler_names: [2][16][:0]const u8 = undefined; var ep_handler_drivers: [2][16]?usize = @splat(@splat(null)); var itf_handlers: []const DriverEnum = &.{}; var driver_alloc_names: []const [:0]const u8 = &.{}; var driver_alloc_types: []const type = &.{}; - var driver_alloc_attrs: []const std.builtin.StructField.Attributes = &.{}; + var driver_alloc_attrs: []const std.builtin.Type.StructField.Attributes = &.{}; for (driver_fields, 0..) |drv, drv_id| { // Get descriptor type for the current driver @@ -282,7 +290,7 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { if (result.alloc_bytes) |len| { driver_alloc_names = driver_alloc_names ++ &[_][:0]const u8{drv.name}; driver_alloc_types = driver_alloc_types ++ &[_]type{[len]u8}; - driver_alloc_attrs = driver_alloc_attrs ++ &[_]std.builtin.StructField.Attributes{.{ .@"align" = result.alloc_align }}; + driver_alloc_attrs = driver_alloc_attrs ++ &[_]std.builtin.Type.StructField.Attributes{.{ .@"align" = result.alloc_align }}; } else { assert(result.alloc_align == null); } @@ -353,6 +361,11 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { } } + // alloc is invalidated after this point. It will cause a compile + // error if mutated. + const const_alloc = alloc.to_const(); + const const_ep_handlers = ep_handlers; + const DriverConfig = @Struct(.@"extern", null, &field_names, &field_types, &field_attrs); const idx_in = @intFromEnum(types.Dir.In); const idx_out = @intFromEnum(types.Dir.Out); @@ -361,7 +374,7 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { .config_descriptor = extern struct { first: descriptor.Configuration = .{ .total_length = .from(size), - .num_interfaces = alloc.next_itf_num, + .num_interfaces = const_alloc.next_itf_num, .configuration_value = 1, .configuration_s = configuration_s, .attributes = config0.attributes, @@ -369,11 +382,11 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { }, drv: DriverConfig = .{}, }{}, - .string_descriptors = alloc.string_descriptors(config.language), + .string_descriptors = const_alloc.string_descriptors(config.language), .handlers_itf = itf_handlers, .handlers_ep = struct { - In: ep_handlers_types[idx_in] = ep_handlers[idx_in], - Out: ep_handlers_types[idx_out] = ep_handlers[idx_out], + In: ep_handlers_types[idx_in] = const_ep_handlers[idx_in], + Out: ep_handlers_types[idx_out] = const_ep_handlers[idx_out], }{}, .drivers_ep = ep_handler_drivers, .DriverAlloc = @Struct( diff --git a/core/src/utilities.zig b/core/src/utilities.zig index 65d3323e2..cb8a7871a 100644 --- a/core/src/utilities.zig +++ b/core/src/utilities.zig @@ -289,7 +289,7 @@ pub fn GenerateInterruptOptions(sources: []const Source) type { for (@typeInfo(source.InterruptEnum).@"enum".fields) |enum_field| { field_names[i] = enum_field.name; field_types[i] = ?source.HandlerFn; - field_attrs[i] = .{ .default_value_ptr = &@as(?source.HandlerFn, null) }; + field_attrs[i] = .{ .default_value_ptr = @ptrCast(&@as(?source.HandlerFn, null)) }; i += 1; } diff --git a/drivers/base/DateTime.zig b/drivers/base/DateTime.zig index e2005769b..e8aea784d 100644 --- a/drivers/base/DateTime.zig +++ b/drivers/base/DateTime.zig @@ -343,7 +343,7 @@ pub const Timezone = enum(i16) { /// * `separator` - An optional separator to add between the hours and minutes /// defaults to ":" if null pub fn to_string(self: Timezone, out_string: []u8, separator: ?[]const u8) Error!usize { - if (out_string.len < 5 + (separator orelse ":").len) return error.NotEnoughSpace; + if (out_string.len < 5 + (separator orelse @as([]const u8, ":")).len) return error.NotEnoughSpace; const minus = @intFromEnum(self) < 0; diff --git a/examples/raspberrypi/rp2xxx/build.zig b/examples/raspberrypi/rp2xxx/build.zig index ad5cd7bfd..364ef186d 100644 --- a/examples/raspberrypi/rp2xxx/build.zig +++ b/examples/raspberrypi/rp2xxx/build.zig @@ -23,15 +23,15 @@ pub fn build(b: *std.Build) void { .{ .target = raspberrypi.pico, .name = "pico_hd44780", .file = "src/rp2040_only/hd44780.zig" }, .{ .target = raspberrypi.pico, .name = "pico_pcf8574", .file = "src/rp2040_only/pcf8574.zig" }, .{ .target = raspberrypi.pico, .name = "pico_i2c_slave", .file = "src/rp2040_only/i2c_slave.zig" }, - .{ .target = raspberrypi.pico, .name = "pico_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, - .{ .target = raspberrypi.pico, .name = "pico_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, - .{ .target = raspberrypi.pico, .name = "pico_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, + //.{ .target = raspberrypi.pico, .name = "pico_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, + //.{ .target = raspberrypi.pico, .name = "pico_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, + //.{ .target = raspberrypi.pico, .name = "pico_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_multicore", .file = "src/blinky_core1.zig" }, .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_board_blinky", .file = "src/board_blinky.zig" }, - .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, - .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, - .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, + //.{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, + //.{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, + //.{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, .{ .target = raspberrypi.pico_flashless, .name = "pico_flashless_blinky", .file = "src/blinky.zig" }, @@ -101,12 +101,13 @@ pub fn build(b: *std.Build) void { .{ .name = "font8x8", .module = font8x8_dep.module("font8x8") }, } }, .{ .name = "st7789", .file = "src/st7789_lcd.zig" }, - .{ .name = "net-pong", .file = "src/net/pong.zig" }, - .{ .name = "net-irq", .file = "src/net/irq.zig" }, - .{ .name = "net-scan", .file = "src/net/scan.zig" }, - .{ .name = "net-udp", .file = "src/net/udp.zig" }, - .{ .name = "net-tcp_client", .file = "src/net/tcp_client.zig" }, - .{ .name = "net-tcp_server", .file = "src/net/tcp_server.zig" }, + // TODO: foundation libc and 0.16 + //.{ .name = "net-pong", .file = "src/net/pong.zig" }, + //.{ .name = "net-irq", .file = "src/net/irq.zig" }, + //.{ .name = "net-scan", .file = "src/net/scan.zig" }, + //.{ .name = "net-udp", .file = "src/net/udp.zig" }, + //.{ .name = "net-tcp_client", .file = "src/net/tcp_client.zig" }, + //.{ .name = "net-tcp_server", .file = "src/net/tcp_server.zig" }, .{ .name = "board-id", .file = "src/board_id.zig" }, .{ .name = "flash-program", .file = "src/flash_program.zig" }, }; diff --git a/examples/raspberrypi/rp2xxx/src/uart_echo.zig b/examples/raspberrypi/rp2xxx/src/uart_echo.zig index cdba9f21e..35f1b9ad7 100644 --- a/examples/raspberrypi/rp2xxx/src/uart_echo.zig +++ b/examples/raspberrypi/rp2xxx/src/uart_echo.zig @@ -39,7 +39,7 @@ pub fn main() !void { }; //tries to write one byte with 100ms timeout - uart.write_blocking(&data, time.deadline_in_ms(100)) catch { + _ = uart.write_blocking(&data, time.deadline_in_ms(100)) catch { uart.clear_errors(); }; // Toggle the led every time we think we've received a character so we diff --git a/modules/rtt/src/rtt.zig b/modules/rtt/src/rtt.zig index b2723ad85..f81c09fdd 100644 --- a/modules/rtt/src/rtt.zig +++ b/modules/rtt/src/rtt.zig @@ -91,7 +91,7 @@ pub const channel = struct { } fn mode(self: *Self) Mode { - return std.meta.intToEnum(Mode, self.flags & 3) catch unreachable; + return @enumFromInt(self.flags & 3); } fn set_mode(self: *Self, mode_: Mode) void { diff --git a/port/nordic/nrf5x/src/hal/uart.zig b/port/nordic/nrf5x/src/hal/uart.zig index ffa637e4f..7181fc315 100644 --- a/port/nordic/nrf5x/src/hal/uart.zig +++ b/port/nordic/nrf5x/src/hal/uart.zig @@ -103,8 +103,15 @@ pub const BaudRate = enum { pub const UART = enum(u1) { _, - pub const Writer = std.io.GenericWriter(UART, TransmitError, generic_writer_fn); - pub const Reader = std.io.GenericReader(UART, ReceiveError, generic_reader_fn); + pub const Writer = struct { + uart: UART, + intf: std.Io.Writer, + }; + + pub const Reader = struct { + uart: UART, + intf: std.Io.Reader, + }; const TransmitError = error{}; const ReceiveError = error{}; diff --git a/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig b/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig index 4d63925a8..24e67eaa9 100644 --- a/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig +++ b/port/raspberrypi/rp2xxx/src/hal/bootmeta.zig @@ -101,7 +101,7 @@ pub const ImageDef = packed struct(u32) { pub fn EntryPoint(with_stack_limit: bool) type { if (with_stack_limit) { return extern struct { - header: packed struct { + header: packed struct(u32) { item_type: u8 = 0x44, block_size: u8 = 0x04, padding: u16 = 0, @@ -112,7 +112,7 @@ pub fn EntryPoint(with_stack_limit: bool) type { }; } else { return extern struct { - header: packed struct { + header: packed struct(u32) { item_type: u8 = 0x44, block_size: u8 = 0x03, padding: u16 = 0, diff --git a/port/raspberrypi/rp2xxx/src/hal/pins.zig b/port/raspberrypi/rp2xxx/src/hal/pins.zig index 9eb711bca..655a56090 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pins.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pins.zig @@ -767,23 +767,15 @@ pub const GlobalConfiguration = struct { } pub fn PinsType(self: GlobalConfiguration) type { - var count: usize = 0; - for (@typeInfo(GlobalConfiguration).@"struct".fields) |field| { - if (@field(self, field.name) != null) { - count += 1; - } - } - - var field_names: [count][]const u8 = undefined; - var field_types: [count]type = undefined; - var field_attrs: [count]std.builtin.Type.StructField.Attributes = undefined; + const Attributes = std.builtin.Type.StructField.Attributes; - var i: usize = 0; + var field_names: []const []const u8 = &.{}; + var field_types: []const type = &.{}; + var field_attrs: []const Attributes = &.{}; for (@typeInfo(GlobalConfiguration).@"struct".fields) |field| { if (@field(self, field.name)) |pin_config| { - field_names[i] = pin_config.name orelse field.name; - field_attrs[i] = .{}; - field_types[i] = if (pin_config.function == .SIO) + const name: []const u8 = pin_config.name orelse field.name; + const typ: type = if (pin_config.function == .SIO) gpio.Pin else if (pin_config.function.is_pwm()) pwm.Pwm @@ -794,11 +786,13 @@ pub const GlobalConfiguration = struct { // error? continue; - i += 1; + field_names = field_names ++ .{name}; + field_types = field_types ++ .{typ}; + field_attrs = field_attrs ++ .{Attributes{}}; } } - return @Struct(.auto, null, &field_names, &field_types, &field_attrs); + return @Struct(.auto, null, field_names, field_types[0..], field_attrs[0..]); } /// Populate and return the PinsType struct diff --git a/port/raspberrypi/rp2xxx/src/hal/uart.zig b/port/raspberrypi/rp2xxx/src/hal/uart.zig index fcb96054e..a901cc36e 100644 --- a/port/raspberrypi/rp2xxx/src/hal/uart.zig +++ b/port/raspberrypi/rp2xxx/src/hal/uart.zig @@ -1,4 +1,6 @@ const std = @import("std"); +const assert = std.debug.assert; + const microzig = @import("microzig"); const mdf = microzig.drivers; const peripherals = microzig.chip.peripherals; @@ -144,20 +146,83 @@ pub const instance = struct { pub const UART = enum(u1) { _, - pub const UART_With_Timeout = struct { - instance: UART, + pub const Writer = struct { + uart: UART, deadline: mdf.time.Deadline, + intf: std.Io.Writer, }; - pub const Writer = std.io.GenericWriter(UART_With_Timeout, TransmitError, generic_writer_fn); - pub const Reader = std.io.GenericReader(UART_With_Timeout, ReceiveError, generic_reader_fn); + pub const Reader = struct { + uart: UART, + deadline: mdf.time.Deadline, + intf: std.Io.Reader, + }; - pub fn writer(uart: UART, deadline: mdf.time.Deadline) Writer { - return .{ .context = .{ .instance = uart, .deadline = deadline } }; + pub fn writer(uart: UART, deadline: mdf.time.Deadline, buffer: []u8) Writer { + return .{ + .uart = uart, + .deadline = deadline, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .drain = drain, + }, + }, + }; + } + + pub fn reader(uart: UART, deadline: mdf.time.Deadline, buffer: []u8) Reader { + return .{ + .uart = uart, + .deadline = deadline, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .stream = stream, + }, + }, + }; } - pub fn reader(uart: UART, deadline: mdf.time.Deadline) Reader { - return .{ .context = .{ .instance = uart, .deadline = deadline } }; + fn drain(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { + const uart_writer: *Writer = @alignCast(@fieldParentPtr("intf", w)); + const uart = uart_writer.uart; + + // bytes from buffer are not included in count. + w.end -= uart.write_blocking(w.buffer[0..w.end], uart_writer.deadline) catch |err| switch (err) { + error.Timeout => unreachable, + }; + assert(w.end == 0); + + var n: usize = 0; + n += uart.writev_blocking(data[0 .. data.len - 1], uart_writer.deadline) catch |err| switch (err) { + error.Timeout => unreachable, + }; + for (0..splat) |_| + n += uart.write_blocking(data[data.len - 1], uart_writer.deadline) catch |err| switch (err) { + error.Timeout => unreachable, + }; + + return n; + } + + fn stream(io_reader: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { + const r: *Reader = @fieldParentPtr("intf", io_reader); + return switch (limit) { + .nothing => 0, + else => blk: { + var buf: [1]u8 = undefined; + const n = r.uart.read_blocking(&buf, null) catch |err| switch (err) { + error.ReceiveError => return error.ReadError, + }; + + break :blk switch (n) { + 0 => 0, + 1 => try w.writeByte(buf[0]), + else => unreachable, + }; + }, + }; } pub inline fn get_regs(uart: UART) *volatile UartRegs { @@ -283,7 +348,7 @@ pub const UART = enum(u1) { /// /// Note that this does NOT disable reception while this is happening, /// so if this takes too long the RX FIFO can potentially overflow. - pub fn write_blocking(uart: UART, payload: []const u8, deadline: mdf.time.Deadline) TransmitError!void { + pub fn write_blocking(uart: UART, payload: []const u8, deadline: mdf.time.Deadline) TransmitError!usize { return try uart.writev_blocking(&.{payload}, deadline); } @@ -296,9 +361,10 @@ pub const UART = enum(u1) { /// /// Note that this does NOT disable reception while this is happening, /// so if this takes too long the RX FIFO can potentially overflow. - pub fn writev_blocking(uart: UART, payloads: []const []const u8, deadline: mdf.time.Deadline) TransmitError!void { + pub fn writev_blocking(uart: UART, payloads: []const []const u8, deadline: mdf.time.Deadline) TransmitError!usize { const uart_regs = uart.get_regs(); + var written: usize = 0; var iter = microzig.utilities.SliceVector([]const u8).init(payloads).iterator(); while (iter.next_chunk(null)) |payload| { var offset: usize = uart.prime_tx_fifo(payload); @@ -308,18 +374,15 @@ pub const UART = enum(u1) { } uart_regs.UARTDR.write_raw(payload[offset]); offset += 1; + written += 1; } } while (uart.is_busy()) { try deadline.check(time.get_time_since_boot()); } - } - /// Wraps write_blocking() for use as a GenericWriter - fn generic_writer_fn(uart: UART_With_Timeout, buffer: []const u8) TransmitError!usize { - try uart.instance.write_blocking(buffer, uart.deadline); - return buffer.len; + return written; } // TODO: Will potentially be modified in a future DMA overhaul @@ -414,12 +477,6 @@ pub const UART = enum(u1) { return try uart.read_rx_fifo_with_error_check(); } - /// Wraps read_blocking() for use as a GenericReader - fn generic_reader_fn(uart: UART_With_Timeout, buffer: []u8) ReceiveBlockingError!usize { - try uart.instance.read_blocking(buffer, uart.deadline); - return buffer.len; - } - pub fn set_format( uart: UART, word_bits: WordBits, @@ -499,8 +556,8 @@ var uart_logger: ?UART.Writer = null; /// .logFn = hal.uart.log, /// }; pub fn init_logger(uart: UART) void { - uart_logger = uart.writer(.no_deadline); - uart_logger.?.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; + uart_logger = uart.writer(.no_deadline, &.{}); + uart_logger.?.intf.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; } /// Disables logging via the uart instance. @@ -520,12 +577,12 @@ pub fn log( else => " (" ++ @tagName(scope) ++ "): ", }; - if (uart_logger) |uart| { + if (uart_logger) |*writer| { const current_time = time.get_time_since_boot(); const seconds = current_time.to_us() / std.time.us_per_s; const microseconds = current_time.to_us() % std.time.us_per_s; - uart.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; + writer.intf.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; } } diff --git a/port/wch/ch32v/src/hals/ch32v003/pins.zig b/port/wch/ch32v/src/hals/ch32v003/pins.zig index 2050fdd5e..ccf3f2573 100644 --- a/port/wch/ch32v/src/hals/ch32v003/pins.zig +++ b/port/wch/ch32v/src/hals/ch32v003/pins.zig @@ -86,41 +86,25 @@ fn get_tag_name_by_index(comptime T: type, comptime index: usize) []const u8 { } pub fn Pins(comptime config: GlobalConfiguration) type { - comptime { - var fields: []const StructField = &.{}; - for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { - if (@field(config, port_field.name)) |port_config| { - for (@typeInfo(Port.Configuration).@"struct".fields) |field| { - if (@field(port_config, field.name)) |pin_config| { - var pin_field = StructField{ - .is_comptime = false, - .default_value_ptr = null, - - // initialized below: - .name = undefined, - .type = undefined, - .alignment = undefined, - }; - - pin_field.name = pin_config.name orelse get_tag_name_by_index(PortName, @intFromEnum(@field(Port, port_field.name))) ++ @tagName(@field(Pin, field.name))[3..]; - pin_field.type = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); - pin_field.alignment = @alignOf(field.type); - - fields = fields ++ &[_]StructField{pin_field}; - } + const Attributes = std.builtin.Type.StructField.Attributes; + var field_names: []const []const u8 = &.{}; + var field_types: []const type = &.{}; + var field_attrs: []const Attributes = &.{}; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { + if (@field(config, port_field.name)) |port_config| { + for (@typeInfo(Port.Configuration).@"struct".fields) |field| { + if (@field(port_config, field.name)) |pin_config| { + const name: []const u8 = pin_config.name orelse get_tag_name_by_index(PortName, @intFromEnum(@field(Port, port_field.name))) ++ @tagName(@field(Pin, field.name))[3..]; + const typ: type = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); + field_names = field_names ++ .{name}; + field_types = field_types ++ .{typ}; + field_attrs = field_attrs ++ .{Attributes{}}; } } } - - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = fields, - .decls = &.{}, - }, - }); } + + return @Struct(.auto, null, field_names, field_types[0..], field_attrs[0..]); } pub const PortName = enum { diff --git a/port/wch/ch32v/src/hals/pins.zig b/port/wch/ch32v/src/hals/pins.zig index 4bdbaa0f8..d6c3dadd4 100644 --- a/port/wch/ch32v/src/hals/pins.zig +++ b/port/wch/ch32v/src/hals/pins.zig @@ -94,41 +94,26 @@ fn get_tag_name_by_index(comptime T: type, comptime index: usize) []const u8 { } pub fn Pins(comptime config: GlobalConfiguration) type { - comptime { - var fields: []const StructField = &.{}; - for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { - if (@field(config, port_field.name)) |port_config| { - for (@typeInfo(Port.Configuration).@"struct".fields) |field| { - if (@field(port_config, field.name)) |pin_config| { - var pin_field = StructField{ - .is_comptime = false, - .default_value_ptr = null, - - // initialized below: - .name = undefined, - .type = undefined, - .alignment = undefined, - }; - - pin_field.name = pin_config.name orelse get_tag_name_by_index(PortName, @intFromEnum(@field(Port, port_field.name))) ++ @tagName(@field(Pin, field.name))[3..]; - pin_field.type = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); - pin_field.alignment = @alignOf(field.type); - - fields = fields ++ &[_]StructField{pin_field}; - } + const Attributes = std.builtin.Type.StructField.Attributes; + + var field_names: []const []const u8 = &.{}; + var field_types: []const type = &.{}; + var field_attrs: []const Attributes = &.{}; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |port_field| { + if (@field(config, port_field.name)) |port_config| { + for (@typeInfo(Port.Configuration).@"struct".fields) |field| { + if (@field(port_config, field.name)) |pin_config| { + const name: []const u8 = pin_config.name orelse get_tag_name_by_index(PortName, @intFromEnum(@field(Port, port_field.name))) ++ @tagName(@field(Pin, field.name))[3..]; + const typ: type = GPIO(@intFromEnum(@field(Port, port_field.name)), @intFromEnum(@field(Pin, field.name)), pin_config.mode orelse .{ .input = .{.floating} }); + field_names = field_names ++ .{name}; + field_types = field_types ++ .{typ}; + field_attrs = field_attrs ++ .{Attributes{}}; } } } - - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = fields, - .decls = &.{}, - }, - }); } + + return @Struct(.auto, null, field_names, field_types[0..], field_attrs[0..]); } pub const PortName = enum { diff --git a/port/wch/ch32v/src/hals/usart.zig b/port/wch/ch32v/src/hals/usart.zig index f71655363..a6fc86c1d 100644 --- a/port/wch/ch32v/src/hals/usart.zig +++ b/port/wch/ch32v/src/hals/usart.zig @@ -4,6 +4,7 @@ //! Based on the WCH CH32V20x USART peripheral implementation. //! const std = @import("std"); +const assert = std.debug.assert; const microzig = @import("microzig"); const mdf = microzig.drivers; const hal = microzig.hal; @@ -109,15 +110,82 @@ pub const USART = enum(u2) { deadline: mdf.time.Deadline, }; - pub const Writer = std.io.GenericWriter(USART_With_Timeout, TransmitError, generic_writer_fn); - pub const Reader = std.io.GenericReader(USART_With_Timeout, ReceiveError, generic_reader_fn); + pub const Writer = struct { + usart: USART, + deadline: mdf.time.Deadline, + intf: std.Io.Writer, + }; + + pub const Reader = struct { + usart: USART, + deadline: mdf.time.Deadline, + intf: std.Io.Reader, + }; + + pub fn writer(usart: USART, deadline: mdf.time.Deadline, buffer: []u8) Writer { + return .{ + .usart = usart, + .deadline = deadline, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .drain = drain, + }, + }, + }; + } + + pub fn reader(usart: USART, deadline: mdf.time.Deadline, buffer: []u8) Reader { + return .{ + .usart = usart, + .deadline = deadline, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .stream = stream, + }, + }, + }; + } + + fn drain(io_writer: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { + const w: *Writer = @alignCast(@fieldParentPtr("intf", io_writer)); - pub fn writer(usart: USART, deadline: mdf.time.Deadline) Writer { - return .{ .context = .{ .instance = usart, .deadline = deadline } }; + // bytes from buffer are not included in count. + io_writer.end -= w.usart.write_blocking(io_writer.buffer[0..io_writer.end], w.deadline) catch |err| switch (err) { + error.Timeout => unreachable, + }; + assert(io_writer.end == 0); + + var n: usize = 0; + n += w.usart.writev_blocking(data[0 .. data.len - 1], w.deadline) catch |err| switch (err) { + error.Timeout => unreachable, + }; + for (0..splat) |_| + n += w.usart.write_blocking(data[data.len - 1], w.deadline) catch |err| switch (err) { + error.Timeout => unreachable, + }; + + return n; } - pub fn reader(usart: USART, deadline: mdf.time.Deadline) Reader { - return .{ .context = .{ .instance = usart, .deadline = deadline } }; + fn stream(io_reader: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { + const r: *Reader = @fieldParentPtr("intf", io_reader); + return switch (limit) { + .nothing => 0, + else => blk: { + var buf: [1]u8 = undefined; + const n = r.usart.read_blocking(&buf, r.deadline) catch |err| switch (err) { + error.ReceiveError => return error.ReadError, + }; + + break :blk switch (n) { + 0 => 0, + 1 => try w.writeByte(buf[0]), + else => unreachable, + }; + }, + }; } pub inline fn get_regs(usart: USART) *volatile UsartRegs { @@ -301,12 +369,13 @@ pub const USART = enum(u2) { } /// Write bytes to USART TX and block until complete - pub fn write_blocking(usart: USART, payload: []const u8, deadline: mdf.time.Deadline) TransmitError!void { - return try usart.writev_blocking(&.{payload}, deadline); + pub fn write_blocking(usart: USART, payload: []const u8, deadline: mdf.time.Deadline) TransmitError!usize { + return usart.writev_blocking(&.{payload}, deadline); } /// Vectored write - writes multiple buffers in sequence - pub fn writev_blocking(usart: USART, payloads: []const []const u8, deadline: mdf.time.Deadline) TransmitError!void { + pub fn writev_blocking(usart: USART, payloads: []const []const u8, deadline: mdf.time.Deadline) TransmitError!usize { + var written: usize = 0; var iter = microzig.utilities.SliceVector([]const u8).init(payloads).iterator(); while (iter.next_chunk(null)) |payload| { for (payload) |byte| { @@ -317,6 +386,7 @@ pub const USART = enum(u2) { } } usart.write_byte(byte); + written += 1; } } @@ -326,12 +396,8 @@ pub const USART = enum(u2) { return TransmitError.Timeout; } } - } - /// Wrap write_blocking() for use as a GenericWriter - fn generic_writer_fn(usart: USART_With_Timeout, buffer: []const u8) TransmitError!usize { - try usart.instance.write_blocking(buffer, usart.deadline); - return buffer.len; + return written; } /// Read bytes from USART RX and block until complete @@ -384,8 +450,8 @@ var usart_logger: ?USART.Writer = null; /// Set a specific USART instance to be used for logging pub fn init_logger(usart: USART) void { - usart_logger = usart.writer(.no_deadline); - usart_logger.?.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; + usart_logger = usart.writer(.no_deadline, &.{}); + usart_logger.?.intf.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; } /// Disables logging via the USART instance @@ -405,11 +471,11 @@ pub fn log( else => " (" ++ @tagName(scope) ++ "): ", }; - if (usart_logger) |usart| { + if (usart_logger) |*writer| { const current_time = hal.time.get_time_since_boot(); const seconds = current_time.to_us() / std.time.us_per_s; const microseconds = current_time.to_us() % std.time.us_per_s; - usart.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; + writer.intf.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; } } From 997b17345f9e25ea6d274ab020e0c38e5c0afcb3 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 27 May 2026 17:50:10 -0700 Subject: [PATCH 12/61] Examples that don't depend on libc building on 0.16.0 --- examples/nordic/nrf5x/src/uart.zig | 4 +- port/nordic/nrf5x/src/hal/uart.zig | 79 +++++++++++++++++++++++------ port/nxp/lpc/src/tools/patchelf.zig | 24 ++++----- 3 files changed, 77 insertions(+), 30 deletions(-) diff --git a/examples/nordic/nrf5x/src/uart.zig b/examples/nordic/nrf5x/src/uart.zig index 6b15eb7aa..15fcdeaa1 100644 --- a/examples/nordic/nrf5x/src/uart.zig +++ b/examples/nordic/nrf5x/src/uart.zig @@ -30,7 +30,7 @@ pub fn main() !void { // now echo any bytes sent var buf: [1]u8 = undefined; while (true) { - uart.read_blocking(&buf); - uart.write_blocking(buf[0..]); + const n = uart.read_blocking(&buf); + _ = uart.write_blocking(buf[0..n]); } } diff --git a/port/nordic/nrf5x/src/hal/uart.zig b/port/nordic/nrf5x/src/hal/uart.zig index 7181fc315..c0c387e9f 100644 --- a/port/nordic/nrf5x/src/hal/uart.zig +++ b/port/nordic/nrf5x/src/hal/uart.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const assert = std.debug.assert; const microzig = @import("microzig"); const peripherals = microzig.chip.peripherals; @@ -33,8 +34,8 @@ pub fn num(n: u1) UART { /// .logFn = hal.uart.log, /// }; pub fn init_logger(uart: UART) void { - uart_logger = uart.writer(); - uart_logger.?.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; + uart_logger = uart.writer(&.{}); + uart_logger.?.intf.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; } pub fn deinit_logger() void { @@ -53,12 +54,12 @@ pub fn log( else => " (" ++ @tagName(scope) ++ "): ", }; - if (uart_logger) |uart| { + if (uart_logger) |*writer| { const current_time = time.get_time_since_boot(); const seconds = current_time.to_us() / std.time.us_per_s; const microseconds = current_time.to_us() % std.time.us_per_s; - uart.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; + writer.intf.print(prefix ++ format ++ "\r\n", .{ seconds, microseconds } ++ args) catch {}; } } @@ -241,7 +242,7 @@ pub const UART = enum(u1) { regs.ENABLE.write(.{ .ENABLE = .Disabled }); } - pub fn read_blocking(uart: UART, buffer: []u8) void { + pub fn read_blocking(uart: UART, buffer: []u8) usize { uart.start_rx_task(); defer uart.stop_rx_task(); @@ -254,9 +255,11 @@ pub const UART = enum(u1) { b.* = uart.read_rxd(); } + + return buffer.len; } - pub fn write_blocking(uart: UART, buffer: []const u8) void { + pub fn write_blocking(uart: UART, buffer: []const u8) usize { uart.start_tx_task(); defer uart.stop_tx_task(); @@ -267,24 +270,68 @@ pub const UART = enum(u1) { while (!uart.have_tx_rdy_event()) {} } + + return buffer.len; } - pub fn reader(uart: UART) Reader { - return .{ .context = uart }; + pub fn reader(uart: UART, buffer: []u8) Reader { + return .{ + .uart = uart, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .stream = stream, + }, + }, + }; } - pub fn writer(uart: UART) Writer { - return .{ .context = uart }; + pub fn writer(uart: UART, buffer: []u8) Writer { + return .{ + .uart = uart, + .intf = .{ + .buffer = buffer, + .vtable = &.{ + .drain = drain, + }, + }, + }; } - fn generic_writer_fn(uart: UART, buffer: []const u8) TransmitError!usize { - uart.write_blocking(buffer); - return buffer.len; + fn drain(io_writer: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { + const w: *Writer = @fieldParentPtr("intf", io_writer); + + // bytes from buffer are not included in count. + w.intf.end -= w.uart.write_blocking(w.intf.buffer[0..w.intf.end]); + assert(w.intf.end == 0); + + var n: usize = 0; + for (data[0 .. data.len - 1]) |chunk| + n += w.uart.write_blocking(chunk); + + for (0..splat) |_| + n += w.uart.write_blocking(data[data.len - 1]); + + return n; } - fn generic_reader_fn(uart: UART, buffer: []u8) ReceiveError!usize { - uart.read_blocking(buffer); - return buffer.len; + fn stream(io_reader: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { + const r: *Reader = @fieldParentPtr("intf", io_reader); + return switch (limit) { + .nothing => 0, + else => blk: { + var buf: [1]u8 = undefined; + const n = r.uart.read_blocking(&buf) catch |err| switch (err) { + error.ReceiveError => return error.ReadError, + }; + + break :blk switch (n) { + 0 => 0, + 1 => try w.writeByte(buf[0]), + else => unreachable, + }; + }, + }; } pub fn read_rxd(uart: UART) u8 { diff --git a/port/nxp/lpc/src/tools/patchelf.zig b/port/nxp/lpc/src/tools/patchelf.zig index e60a9e212..58bbf94f9 100644 --- a/port/nxp/lpc/src/tools/patchelf.zig +++ b/port/nxp/lpc/src/tools/patchelf.zig @@ -1,9 +1,8 @@ const std = @import("std"); -pub fn main() !u8 { - const argv = try std.process.argsAlloc(std.heap.page_allocator); - defer std.process.argsFree(std.heap.page_allocator, argv); - +pub fn main(init: std.process.Init) !u8 { + const io = init.io; + const argv = try init.minimal.args.toSlice(init.arena.allocator()); if (argv.len != 3) { std.log.err("usage: lpc-patchelf ", .{}); return 1; @@ -12,21 +11,22 @@ pub fn main() !u8 { const input_file_name = argv[1]; const output_file_name = argv[2]; - try std.fs.Dir.copyFile( - std.fs.cwd(), + try std.Io.Dir.copyFile( + std.Io.Dir.cwd(), input_file_name, - std.fs.cwd(), + std.Io.Dir.cwd(), output_file_name, + io, .{}, ); - var file = try std.fs.cwd().openFile(output_file_name, .{ .mode = .read_write }); - defer file.close(); + var file = try std.Io.Dir.cwd().openFile(io, output_file_name, .{ .mode = .read_write }); + defer file.close(io); var read_buf: [4096]u8 = undefined; var write_buf: [4096]u8 = undefined; - var file_reader = file.reader(&read_buf); - var file_writer = file.writer(&write_buf); + var file_reader = file.reader(io, &read_buf); + var file_writer = file.writer(io, &write_buf); const header = try std.elf.Header.read(&file_reader.interface); @@ -52,7 +52,7 @@ pub fn main() !u8 { continue; } - try file.seekTo(phdr.p_offset); + try file_reader.seekTo(phdr.p_offset); var checksum: u32 = 0; From ea24e661cecd1af5d39d82127c7f6b89ef578cc6 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 27 May 2026 17:57:11 -0700 Subject: [PATCH 13/61] Linter building on 0.16.0 --- tools/linter/src/main.zig | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/tools/linter/src/main.zig b/tools/linter/src/main.zig index d4768c452..70fc16a2b 100644 --- a/tools/linter/src/main.zig +++ b/tools/linter/src/main.zig @@ -11,31 +11,19 @@ const Issue = struct { message: []const u8, }; -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - - var arena = std.heap.ArenaAllocator.init(debug_allocator.allocator()); - defer arena.deinit(); - - const allocator = arena.allocator(); - - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); - - var issues: std.ArrayListUnmanaged(Issue) = .{}; - defer issues.deinit(allocator); +pub fn main(init: std.process.Init) !void { + const io = init.io; + const allocator = init.arena.allocator(); + const args = try init.minimal.args.toSlice(allocator); + var issues: std.ArrayList(Issue) = .empty; for (args[1..]) |path| { - const source = std.fs.cwd().readFileAllocOptions(allocator, path, 100 * 1024 * 1024, null, .@"1", 0) catch |err| { + const source = std.Io.Dir.cwd().readFileAllocOptions(io, path, allocator, .unlimited, .@"1", 0) catch |err| { std.log.err("Failed to read file '{s}': {}", .{ path, err }); return err; }; - defer allocator.free(source); var ast = try std.zig.Ast.parse(allocator, source, .zig); - defer ast.deinit(allocator); - for (ast.nodes.items(.tag), ast.nodes.items(.main_token)) |node_tag, main_tok_idx| { switch (node_tag) { .fn_proto_simple, @@ -83,9 +71,9 @@ pub fn main() !void { } } - const stdout = std.fs.File.stdout(); + const stdout = std.Io.File.stdout(); var buf: [4096]u8 = undefined; - var file_writer = stdout.writer(&buf); + var file_writer = stdout.writer(io, &buf); const writer = &file_writer.interface; try std.json.Stringify.value(issues.items, .{}, writer); @@ -107,7 +95,7 @@ const TypenameComponent = union(TypenameComponentTag) { }; const TypenameComponents = struct { - list: std.ArrayList(TypenameComponent) = .{}, + list: std.ArrayList(TypenameComponent) = .empty, pub fn format(components: *const TypenameComponents, writer: *std.Io.Writer) !void { try writer.print("Components:\n", .{}); @@ -210,7 +198,7 @@ fn has_lower(str: []const u8) bool { } fn from_string(gpa: Allocator, typename: []const u8) !TypenameComponents { - var components: std.ArrayList(TypenameComponent) = .{}; + var components: std.ArrayList(TypenameComponent) = .empty; errdefer components.deinit(gpa); var buf: []const u8 = &.{}; @@ -346,7 +334,7 @@ fn should_transform_typename(gpa: Allocator, typename: []const u8) !?[]const u8 } } - var new_components: std.ArrayList(TypenameComponent) = .{}; + var new_components: std.ArrayList(TypenameComponent) = .empty; defer new_components.deinit(gpa); for (components.list.items) |component| switch (component) { @@ -557,9 +545,7 @@ fn camel_to_snake(arena: Allocator, str: []const u8) ![]const u8 { if (str.len == 0) return str; - var ret = std.ArrayListUnmanaged(u8){}; - errdefer ret.deinit(arena); - + var ret: std.ArrayList(u8) = .empty; if (std.ascii.isUpper(str[0])) { try ret.append(arena, std.ascii.toLower(str[0])); } else { From 64c53ceabd15313a4c4138dbbf863ad1473aeb86 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 27 May 2026 20:33:33 -0700 Subject: [PATCH 14/61] Update CI --- .github/workflows/ci.yml | 4 ++-- .github/workflows/deploy.yml | 2 +- .github/workflows/drivers.yaml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-github-pages.yml | 2 +- .github/workflows/sim-aviron.yml | 2 +- .github/workflows/unused-imports.yml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1549de62..6f68496cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: env: - ZIG_VERSION: 0.15.1 + ZIG_VERSION: 0.16.0 jobs: formatting-check: @@ -246,7 +246,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Build Website run: zig build working-directory: website diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 196df1259..ff6c32d79 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Extract version run: echo "MICROZIG_VERSION=$(zig build package -- get-version)" >> $GITHUB_ENV diff --git a/.github/workflows/drivers.yaml b/.github/workflows/drivers.yaml index 7f510ffd8..b414f77a9 100644 --- a/.github/workflows/drivers.yaml +++ b/.github/workflows/drivers.yaml @@ -20,7 +20,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Run Test Suite working-directory: drivers diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a157f89c3..b5873d59c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 # Build linter from trusted base branch code - name: Build linter diff --git a/.github/workflows/publish-github-pages.yml b/.github/workflows/publish-github-pages.yml index 4becbe241..ed646331f 100644 --- a/.github/workflows/publish-github-pages.yml +++ b/.github/workflows/publish-github-pages.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Download and install GitHub CLI run: | diff --git a/.github/workflows/sim-aviron.yml b/.github/workflows/sim-aviron.yml index ed71a1fa2..053513a34 100644 --- a/.github/workflows/sim-aviron.yml +++ b/.github/workflows/sim-aviron.yml @@ -19,7 +19,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Build working-directory: sim/aviron diff --git a/.github/workflows/unused-imports.yml b/.github/workflows/unused-imports.yml index 029cfa804..cee1d7837 100644 --- a/.github/workflows/unused-imports.yml +++ b/.github/workflows/unused-imports.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Build zigimports run: | From 449cb4936050d86f536f72a8596610b291df2da8 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 27 May 2026 21:02:38 -0700 Subject: [PATCH 15/61] dfu compiles on 0.16.0 --- tools/dfu/src/bin2dfu.zig | 25 ++++++++++--------------- tools/dfu/src/dfuse.zig | 6 +++--- tools/dfu/src/elf2dfuse.zig | 27 ++++++++++++--------------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/tools/dfu/src/bin2dfu.zig b/tools/dfu/src/bin2dfu.zig index fb452c22e..55d1e4f7f 100644 --- a/tools/dfu/src/bin2dfu.zig +++ b/tools/dfu/src/bin2dfu.zig @@ -38,15 +38,11 @@ fn find_arg(args: []const []const u8, key: []const u8) !?[]const u8 { var input_reader_buf: [4096]u8 = undefined; -pub fn main() !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - - const args = try std.process.argsAlloc(gpa.allocator()); - defer std.process.argsFree(gpa.allocator(), args); - +pub fn main(init: std.process.Init) !void { + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); for (args) |arg| if (std.mem.eql(u8, "--help", arg)) { - var writer = std.fs.File.stdout().writer(&.{}); + var writer = std.Io.File.stdout().writer(io, &.{}); try writer.interface.writeAll(usage); return; }; @@ -84,16 +80,15 @@ pub fn main() !void { }; } - const bin_file = try std.fs.cwd().openFile(bin_path, .{}); - defer bin_file.close(); - - var bin_reader = bin_file.reader(&input_reader_buf); + const bin_file = try std.Io.Dir.cwd().openFile(io, bin_path, .{}); + defer bin_file.close(io); - const dest_file = try std.fs.cwd().createFile(output_path, .{}); - defer dest_file.close(); + var bin_reader = bin_file.reader(io, &input_reader_buf); + const dest_file = try std.Io.Dir.cwd().createFile(io, output_path, .{}); + defer dest_file.close(io); // Unbuffered because dfu uses a hashed writer, which suggests // using an unbuffered underlying writer - var writer = dest_file.writer(&.{}); + var writer = dest_file.writer(io, &.{}); try dfu.from_bin(&bin_reader.interface, &writer.interface, opts); } diff --git a/tools/dfu/src/dfuse.zig b/tools/dfu/src/dfuse.zig index 592264746..3ac3fc599 100644 --- a/tools/dfu/src/dfuse.zig +++ b/tools/dfu/src/dfuse.zig @@ -108,7 +108,7 @@ const Segment = struct { /// Convert an ELF file into a single-target DfuSe image. pub fn from_elf( allocator: Allocator, - reader: *std.fs.File.Reader, + reader: *std.Io.File.Reader, writer: *std.Io.Writer, opts: Options, ) !void { @@ -156,7 +156,7 @@ pub fn from_elf( fn collect_segments( allocator: Allocator, - reader: *std.fs.File.Reader, + reader: *std.Io.File.Reader, segments: *std.ArrayList(Segment), ) !void { const header = try std.elf.Header.read(&reader.interface); @@ -208,7 +208,7 @@ fn calculate_target_size(segments: []const Segment) u32 { return size; } -fn write_elements(reader: *std.fs.File.Reader, writer: *std.Io.Writer, segments: []const Segment) !void { +fn write_elements(reader: *std.Io.File.Reader, writer: *std.Io.Writer, segments: []const Segment) !void { var ranges = ElementRangeIterator.init(segments); while (ranges.next()) |range| { const element_size = range.size(); diff --git a/tools/dfu/src/elf2dfuse.zig b/tools/dfu/src/elf2dfuse.zig index b6b3eefb8..a4ac9159c 100644 --- a/tools/dfu/src/elf2dfuse.zig +++ b/tools/dfu/src/elf2dfuse.zig @@ -38,15 +38,12 @@ fn find_arg(args: []const []const u8, key: []const u8) !?[]const u8 { var elf_reader_buf: [4096]u8 = undefined; -pub fn main() !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - - const args = try std.process.argsAlloc(gpa.allocator()); - defer std.process.argsFree(gpa.allocator(), args); - +pub fn main(init: std.process.Init) !void { + const io = init.io; + const gpa = init.gpa; + const args = try init.minimal.args.toSlice(init.arena.allocator()); for (args) |arg| if (std.mem.eql(u8, "--help", arg)) { - var writer = std.fs.File.stdout().writer(&.{}); + var writer = std.Io.File.stdout().writer(io, &.{}); try writer.interface.writeAll(usage); return; }; @@ -84,15 +81,15 @@ pub fn main() !void { }; } - const elf_file = try std.fs.cwd().openFile(elf_path, .{}); - defer elf_file.close(); - var elf_reader = elf_file.reader(&elf_reader_buf); + const elf_file = try std.Io.Dir.cwd().openFile(io, elf_path, .{}); + defer elf_file.close(io); + var elf_reader = elf_file.reader(io, &elf_reader_buf); - const dest_file = try std.fs.cwd().createFile(output_path, .{}); - defer dest_file.close(); + const dest_file = try std.Io.Dir.cwd().createFile(io, output_path, .{}); + defer dest_file.close(io); // Unbuffered because dfu uses a hashed writer, which suggests // using an unbuffered underlying writer - var writer = dest_file.writer(&.{}); - try dfuse.from_elf(gpa.allocator(), &elf_reader, &writer.interface, opts); + var writer = dest_file.writer(io, &.{}); + try dfuse.from_elf(gpa, &elf_reader, &writer.interface, opts); } From 998489af8777401e0dbdd692ee8eb7ffb62f2682 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 27 May 2026 21:06:05 -0700 Subject: [PATCH 16/61] esp-image compile and tests on 0.16.0 --- tools/esp-image/src/elf2image.zig | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/esp-image/src/elf2image.zig b/tools/esp-image/src/elf2image.zig index 2adc77189..cf289277c 100644 --- a/tools/esp-image/src/elf2image.zig +++ b/tools/esp-image/src/elf2image.zig @@ -494,19 +494,20 @@ test "Segment.write_to" { @memset(segment.data, 'a'); - var segment_data: std.ArrayList(u8) = .empty; - defer segment_data.deinit(allocator); - const writer = segment_data.writer(allocator); + var segment_data: std.Io.Writer.Allocating = .init(std.testing.allocator); + defer segment_data.deinit(); + + const writer = &segment_data.writer; var checksum: u8 = esp_image.CHECKSUM_XOR_BYTE; try segment.write_to(allocator, writer, 0x10, &checksum); try segment.write_to(allocator, writer, null, &checksum); - try std.testing.expectEqual(std.mem.readInt(u32, segment_data.items[0..4], .little), 0x42000020); - try std.testing.expectEqual(std.mem.readInt(u32, segment_data.items[4..8], .little), 0x10); - try std.testing.expectEqualStrings(segment_data.items[8..24], &@as([16]u8, @splat('a'))); - try std.testing.expectEqual(std.mem.readInt(u32, segment_data.items[24..28], .little), 0x42000030); - try std.testing.expectEqual(std.mem.readInt(u32, segment_data.items[28..32], .little), 0x10); - try std.testing.expectEqualStrings(segment_data.items[32..48], &@as([16]u8, @splat('a'))); + try std.testing.expectEqual(std.mem.readInt(u32, writer.buffered()[0..4], .little), 0x42000020); + try std.testing.expectEqual(std.mem.readInt(u32, writer.buffered()[4..8], .little), 0x10); + try std.testing.expectEqualStrings(writer.buffered()[8..24], &@as([16]u8, @splat('a'))); + try std.testing.expectEqual(std.mem.readInt(u32, writer.buffered()[24..28], .little), 0x42000030); + try std.testing.expectEqual(std.mem.readInt(u32, writer.buffered()[28..32], .little), 0x10); + try std.testing.expectEqualStrings(writer.buffered()[32..48], &@as([16]u8, @splat('a'))); try std.testing.expectEqual(segment.size, 0); } From aff067714291ac80070c85fd118ceefe5671585b Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Wed, 27 May 2026 21:06:56 -0700 Subject: [PATCH 17/61] Remove package-test --- tools/package-test/build.zig | 45 -------------------------------- tools/package-test/build.zig.zon | 11 -------- tools/package-test/src/empty.zig | 10 ------- 3 files changed, 66 deletions(-) delete mode 100644 tools/package-test/build.zig delete mode 100644 tools/package-test/build.zig.zon delete mode 100644 tools/package-test/src/empty.zig diff --git a/tools/package-test/build.zig b/tools/package-test/build.zig deleted file mode 100644 index 37b1d59a1..000000000 --- a/tools/package-test/build.zig +++ /dev/null @@ -1,45 +0,0 @@ -const std = @import("std"); -const microzig = @import("microzig"); - -const MicroBuild = microzig.MicroBuild(.{ - .rp2xxx = true, - .gd32 = true, - .samd51 = true, - //.atmega = true, - .nrf5x = true, - .lpc = true, - .stm32 = true, -}); - -pub fn build(b: *std.Build) void { - const optimize = b.standardOptimizeOption(.{}); - - const mz_dep = b.dependency("microzig", .{}); - const mb = MicroBuild.init(b, mz_dep) orelse return; - - const examples: []const Example = &.{ - .{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "rp2xxx" }, - .{ .target = mb.ports.gd32.boards.sipeed.longan_nano, .name = "gd32" }, - .{ .target = mb.ports.samd51.chips.atsamd51j19, .name = "atsam" }, - //.{ .target = mb.ports.atmega.boards.arduino.nano, .name = "avr" }, - .{ .target = mb.ports.nrf5x.boards.nordic.nrf52840_dongle, .name = "nrf5x" }, - .{ .target = mb.ports.lpc.boards.mbed.lpc1768, .name = "lpc" }, - .{ .target = mb.ports.stm32.boards.stm32f3discovery, .name = "stm32" }, - }; - - for (examples) |example| { - const firmware = mb.add_firmware(.{ - .name = example.name, - .target = example.target, - .optimize = optimize, - .root_source_file = b.path("src/empty.zig"), - }); - - mb.install_firmware(firmware, .{}); - } -} - -const Example = struct { - target: *const microzig.Target, - name: []const u8, -}; diff --git a/tools/package-test/build.zig.zon b/tools/package-test/build.zig.zon deleted file mode 100644 index 647a6ff49..000000000 --- a/tools/package-test/build.zig.zon +++ /dev/null @@ -1,11 +0,0 @@ -.{ - .name = .mz_package_test, - .fingerprint = 0x67a6623979baa54d, - .version = "0.0.0", - .dependencies = .{}, - .paths = .{ - "build.zig", - "build.zig.zon", - "src", - }, -} diff --git a/tools/package-test/src/empty.zig b/tools/package-test/src/empty.zig deleted file mode 100644 index 6dfe7b420..000000000 --- a/tools/package-test/src/empty.zig +++ /dev/null @@ -1,10 +0,0 @@ -const microzig = @import("microzig"); - -pub const panic = microzig.panic; -pub const std_options = microzig.std_options(.{}); - -comptime { - _ = microzig.export_startup(); -} - -pub fn main() void {} From 5f2e7e41bcff7eb743b6e0aa907e88c6954cefb5 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 11:44:56 -0700 Subject: [PATCH 18/61] printer compiling with 0.16.0 --- examples/raspberrypi/rp2xxx/build.zig | 13 ++-- tools/dfu/src/dfuse.zig | 2 +- tools/generate_linker_script.zig | 2 +- tools/printer/build.zig.zon | 4 +- tools/printer/examples/rp2xxx_runner.zig | 76 +++++++++----------- tools/printer/src/Elf.zig | 2 +- tools/printer/src/main.zig | 55 +++++++------- tools/printer/src/root.zig | 72 +++++++++---------- tools/printer/tests/generate_test_data.zig | 21 +++--- tools/printer/tests/test.zig | 39 +++++----- tools/printer/tests/test_program.dwarf32.zon | 42 +++++------ tools/printer/tests/test_program.dwarf64.zon | 73 +------------------ tools/regz/src/Database.zig | 2 +- tools/regz/src/targetdb.zig | 4 +- 14 files changed, 166 insertions(+), 241 deletions(-) diff --git a/examples/raspberrypi/rp2xxx/build.zig b/examples/raspberrypi/rp2xxx/build.zig index 364ef186d..8072717e5 100644 --- a/examples/raspberrypi/rp2xxx/build.zig +++ b/examples/raspberrypi/rp2xxx/build.zig @@ -101,13 +101,12 @@ pub fn build(b: *std.Build) void { .{ .name = "font8x8", .module = font8x8_dep.module("font8x8") }, } }, .{ .name = "st7789", .file = "src/st7789_lcd.zig" }, - // TODO: foundation libc and 0.16 - //.{ .name = "net-pong", .file = "src/net/pong.zig" }, - //.{ .name = "net-irq", .file = "src/net/irq.zig" }, - //.{ .name = "net-scan", .file = "src/net/scan.zig" }, - //.{ .name = "net-udp", .file = "src/net/udp.zig" }, - //.{ .name = "net-tcp_client", .file = "src/net/tcp_client.zig" }, - //.{ .name = "net-tcp_server", .file = "src/net/tcp_server.zig" }, + .{ .name = "net-pong", .file = "src/net/pong.zig" }, + .{ .name = "net-irq", .file = "src/net/irq.zig" }, + .{ .name = "net-scan", .file = "src/net/scan.zig" }, + .{ .name = "net-udp", .file = "src/net/udp.zig" }, + .{ .name = "net-tcp_client", .file = "src/net/tcp_client.zig" }, + .{ .name = "net-tcp_server", .file = "src/net/tcp_server.zig" }, .{ .name = "board-id", .file = "src/board_id.zig" }, .{ .name = "flash-program", .file = "src/flash_program.zig" }, }; diff --git a/tools/dfu/src/dfuse.zig b/tools/dfu/src/dfuse.zig index 3ac3fc599..858b1f112 100644 --- a/tools/dfu/src/dfuse.zig +++ b/tools/dfu/src/dfuse.zig @@ -208,7 +208,7 @@ fn calculate_target_size(segments: []const Segment) u32 { return size; } -fn write_elements(reader: *std.Io.File.Reader, writer: *std.Io.Writer, segments: []const Segment) !void { +fn write_elements(reader: *std.Io.File.fsReader, writer: *std.Io.Writer, segments: []const Segment) !void { var ranges = ElementRangeIterator.init(segments); while (ranges.next()) |range| { const element_size = range.size(); diff --git a/tools/generate_linker_script.zig b/tools/generate_linker_script.zig index 9702beaac..fb99f4a0b 100644 --- a/tools/generate_linker_script.zig +++ b/tools/generate_linker_script.zig @@ -28,7 +28,7 @@ pub fn main(init: std.process.Init) !void { const parsed_args = try std.json.parseFromSliceLeaky(Args, allocator, json_args, .{}); const maybe_user_linker_script = if (args.len == 4) - try std.Io.Dir.cwd().readFileAlloc(io, args[3], allocator, @enumFromInt(100 * 1024 * 1024)) + try std.Io.Dir.cwd().readFileAlloc(io, args[3], allocator, .limited(100 * 1024 * 1024)) else null; diff --git a/tools/printer/build.zig.zon b/tools/printer/build.zig.zon index f11b4fedb..21864693d 100644 --- a/tools/printer/build.zig.zon +++ b/tools/printer/build.zig.zon @@ -5,8 +5,8 @@ .minimum_zig_version = "0.15.1", .dependencies = .{ .serial = .{ - .url = "git+https://github.com/ZigEmbeddedGroup/serial#fbd7389ff8bbc9fa362aa74081588755b5d028a0", - .hash = "serial-0.0.1-PoeRzF60AAAN8Iu0yXTIX-t3DVzsnmN7vWHKM2HA2Zbq", + .url = "git+https://github.com/ZigEmbeddedGroup/serial#4c4caabad4a78e699034a95ba7145bf07cdd8e78", + .hash = "serial-0.0.1-PoeRzPq5AAAHeo07adkaBjANT4JUaOpNWcnxQGqjxcQY", }, // used to compile the test program // .microzig = .{ .path = "../..", .lazy = true }, diff --git a/tools/printer/examples/rp2xxx_runner.zig b/tools/printer/examples/rp2xxx_runner.zig index 65c1967d3..6a46cf582 100644 --- a/tools/printer/examples/rp2xxx_runner.zig +++ b/tools/printer/examples/rp2xxx_runner.zig @@ -6,64 +6,58 @@ var elf_file_reader_buf: [1024]u8 = undefined; var in_stream_buf: [1024]u8 = undefined; var out_stream_buf: [1024]u8 = undefined; -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - const allocator = debug_allocator.allocator(); - - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); - - if (args.len != 4) return error.UsageError; +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); + if (args.len != 4) + return error.UsageError; const elf_path = args[1]; const serial_device_path = args[2]; const baud_rate = try std.fmt.parseInt(u32, args[3], 10); - const elf_file = try std.fs.cwd().openFile(elf_path, .{}); - defer elf_file.close(); - var elf_file_reader = elf_file.reader(&elf_file_reader_buf); + const elf_file = try std.Io.Dir.cwd().openFile(io, elf_path, .{}); + defer elf_file.close(io); + var elf_file_reader = elf_file.reader(io, &elf_file_reader_buf); - var elf: printer.Elf = try .init(allocator, &elf_file_reader); - defer elf.deinit(allocator); + var elf: printer.Elf = try .init(gpa, &elf_file_reader); + defer elf.deinit(gpa); - var debug_info: printer.DebugInfo = try .init(allocator, elf); - defer debug_info.deinit(allocator); + var debug_info: printer.DebugInfo = try .init(gpa, elf); + defer debug_info.deinit(gpa); - const serial_device = try std.fs.cwd().openFile(serial_device_path, .{}); - defer serial_device.close(); + const serial_device = try std.Io.Dir.cwd().openFile(io, serial_device_path, .{}); + defer serial_device.close(io); try serial.configureSerialPort(serial_device, .{ .baud_rate = baud_rate, }); try serial.flushSerialPort(serial_device, .both); - var in_stream = serial_device.reader(&in_stream_buf); + var reader = serial_device.reader(io, &in_stream_buf); - { - var flash_cmd: std.process.Child = .init(&.{ - "picotool", - "load", - "-u", - "-v", - "-x", - "-t", - "elf", - elf_path, - }, allocator); - const term = try flash_cmd.spawnAndWait(); - switch (term) { - .Exited => |code| if (code != 0) return error.FlashCommandFailed, - else => {}, - } + var flash_cmd = try std.process.spawn(io, .{ + .argv = &.{ "picotool", "load", "-u", "-v", "-x", "-t", "elf", elf_path }, + }); + const term = try flash_cmd.wait(io); + switch (term) { + .exited => |code| if (code != 0) return error.FlashCommandFailed, + else => {}, } - const stdout = std.fs.File.stdout(); - var out_stream = stdout.writer(&out_stream_buf); - const out_tty_config = std.Io.tty.detectConfig(stdout); + const stdout = std.Io.File.stdout(); + var writer = stdout.writer(io, &out_stream_buf); + + const no_color = try init.minimal.environ.containsUnempty(gpa, "NO_COLOR"); + const clicolor_force = try init.minimal.environ.containsUnempty(gpa, "CLICOLOR_FORCE"); + var terminal: std.Io.Terminal = .{ + .writer = &writer.interface, + .mode = try std.Io.Terminal.Mode.detect(io, stdout, no_color, clicolor_force), + }; try printer.annotate( - &in_stream.interface, - &out_stream.interface, - out_tty_config, + io, + &reader.interface, + &terminal, elf, &debug_info, ); diff --git a/tools/printer/src/Elf.zig b/tools/printer/src/Elf.zig index c466aae79..f997df25a 100644 --- a/tools/printer/src/Elf.zig +++ b/tools/printer/src/Elf.zig @@ -35,7 +35,7 @@ pub const Region = struct { }; }; -pub fn init(allocator: std.mem.Allocator, file_reader: *std.fs.File.Reader) !Elf { +pub fn init(allocator: std.mem.Allocator, file_reader: *std.Io.File.Reader) !Elf { var elf_header = try std.elf.Header.read(&file_reader.interface); const format: Format = if (elf_header.is_64) .@"64" else .@"32"; diff --git a/tools/printer/src/main.zig b/tools/printer/src/main.zig index 502327bcb..54ac5459d 100644 --- a/tools/printer/src/main.zig +++ b/tools/printer/src/main.zig @@ -6,44 +6,49 @@ var elf_file_reader_buf: [1024]u8 = undefined; var in_stream_buf: [1024]u8 = undefined; var out_stream_buf: [1024]u8 = undefined; -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - const allocator = debug_allocator.allocator(); - - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len < 2) { - try std.fs.File.stderr().writeAll("usage: ./printer elf_file [input_file]\n"); + var stderr = std.Io.File.stderr().writer(io, &.{}); + try stderr.interface.writeAll("usage: ./printer elf_file [input_file]\n"); std.process.exit(1); } - const elf_file = try std.fs.cwd().openFile(args[1], .{}); - defer elf_file.close(); - var elf_file_reader = elf_file.reader(&elf_file_reader_buf); + const elf_file = try std.Io.Dir.cwd().openFile(io, args[1], .{}); + defer elf_file.close(io); - var elf: printer.Elf = try .init(allocator, &elf_file_reader); - defer elf.deinit(allocator); + var elf_file_reader = elf_file.reader(io, &elf_file_reader_buf); + var elf: printer.Elf = try .init(gpa, &elf_file_reader); + defer elf.deinit(gpa); - var debug_info: printer.DebugInfo = try .init(allocator, elf); - defer debug_info.deinit(allocator); + var debug_info: printer.DebugInfo = try .init(gpa, elf); + defer debug_info.deinit(gpa); const input_file = if (args.len <= 2 or std.mem.eql(u8, args[2], "-")) - std.fs.File.stdin() + std.Io.File.stdin() else - try std.fs.cwd().openFile(args[2], .{}); - defer input_file.close(); - var in_stream = input_file.reader(&in_stream_buf); + try std.Io.Dir.cwd().openFile(io, args[2], .{}); + defer input_file.close(io); + + var reader = input_file.reader(io, &in_stream_buf); + + const stdout = std.Io.File.stdout(); + var writer = stdout.writer(io, &out_stream_buf); - const stdout = std.fs.File.stdout(); - var out_stream = stdout.writer(&out_stream_buf); - const out_tty_config = std.io.tty.detectConfig(stdout); + const no_color = try init.minimal.environ.containsUnempty(gpa, "NO_COLOR"); + const clicolor_force = try init.minimal.environ.containsUnempty(gpa, "CLICOLOR_FORCE"); + var terminal: std.Io.Terminal = .{ + .writer = &writer.interface, + .mode = try std.Io.Terminal.Mode.detect(io, stdout, no_color, clicolor_force), + }; try printer.annotate( - &in_stream.interface, - &out_stream.interface, - out_tty_config, + io, + &reader.interface, + &terminal, elf, &debug_info, ); diff --git a/tools/printer/src/root.zig b/tools/printer/src/root.zig index 6221f9585..553206451 100644 --- a/tools/printer/src/root.zig +++ b/tools/printer/src/root.zig @@ -7,9 +7,9 @@ pub const DebugInfo = @import("DebugInfo.zig"); /// Reads lines one by one from in_stream and outputs them with annotated /// addresses to out_stream. Returns after it reaches the end of the stream. pub fn annotate( + io: Io, in_stream: *Io.Reader, - out_stream: *Io.Writer, - out_tty_config: std.io.tty.Config, + terminal: *Io.Terminal, elf: Elf, debug_info: *DebugInfo, ) !void { @@ -17,26 +17,26 @@ pub fn annotate( const line = in_stream.takeDelimiterInclusive('\n') catch |err| switch (err) { error.ReadFailed => return error.ReadFailed, error.EndOfStream => { - try output_line(in_stream.buffered(), out_stream, out_tty_config, elf, debug_info); - try out_stream.flush(); + try output_line(io, in_stream.buffered(), terminal, elf, debug_info); + try terminal.writer.flush(); return; }, error.StreamTooLong => return error.StreamTooLong, }; - try output_line(line, out_stream, out_tty_config, elf, debug_info); - try out_stream.flush(); + try output_line(io, line, terminal, elf, debug_info); + try terminal.writer.flush(); } } fn output_line( + io: Io, line: []const u8, - out_stream: *Io.Writer, - out_tty_config: std.io.tty.Config, + terminal: *Io.Terminal, elf: Elf, debug_info: *DebugInfo, ) !void { - try out_stream.writeAll(line); + try terminal.writer.writeAll(line); const prefix_index = std.mem.indexOf(u8, line, "0x") orelse return; var after_prefix = line[prefix_index + 2 ..]; @@ -55,56 +55,55 @@ fn output_line( const address = std.fmt.parseInt(u64, after_prefix[0..hex_digit_count], 16) catch unreachable; if (elf.is_address_executable(address)) { const query_result = debug_info.query(address); - try output_location_info(out_stream, out_tty_config, address, query_result); + try output_location_info(terminal, address, query_result); if (query_result.source_location) |src_loc| { - try output_source_line(out_stream, out_tty_config, src_loc); + try output_source_line(io, terminal, src_loc); } } } fn output_location_info( - out_stream: *Io.Writer, - out_tty_config: std.io.tty.Config, + terminal: *Io.Terminal, address: u64, query_result: DebugInfo.QueryResult, ) !void { - try out_tty_config.setColor(out_stream, .bold); + try terminal.setColor(.bold); if (query_result.source_location) |src_loc| { - try out_stream.print("{f}:{}:{}", .{ + try terminal.writer.print("{f}:{}:{}", .{ std.fs.path.fmtJoin(&.{ src_loc.dir_path, src_loc.file_path }), src_loc.line, src_loc.column, }); } else { - try out_stream.writeAll("???:?:?"); + try terminal.writer.writeAll("???:?:?"); } - try out_tty_config.setColor(out_stream, .reset); - try out_stream.writeAll(": "); + try terminal.setColor(.reset); + try terminal.writer.writeAll(": "); - try out_tty_config.setColor(out_stream, .dim); - try out_stream.print("0x{x} in {s} ({s})\n", .{ + try terminal.setColor(.dim); + try terminal.writer.print("0x{x} in {s} ({s})\n", .{ address, query_result.function_name orelse "???", query_result.module_name orelse "???", }); - try out_tty_config.setColor(out_stream, .reset); + try terminal.setColor(.reset); } fn output_source_line( - out_stream: *Io.Writer, - out_tty_config: std.io.tty.Config, + io: Io, + terminal: *Io.Terminal, src_loc: DebugInfo.ResolvedSourceLocation, ) !void { - var dir = std.fs.cwd().openDir(src_loc.dir_path, .{}) catch return; - defer dir.close(); + var dir = std.Io.Dir.cwd().openDir(io, src_loc.dir_path, .{}) catch return; + defer dir.close(io); - const file = dir.openFile(src_loc.file_path, .{}) catch return; - defer file.close(); + const file = dir.openFile(io, src_loc.file_path, .{}) catch return; + defer file.close(io); var r_buf: [512]u8 = undefined; - var file_reader = file.reader(&r_buf); + var file_reader = file.reader(io, &r_buf); var line_count: u32 = 1; var line_buf: [128]u8 = undefined; @@ -135,19 +134,20 @@ fn output_source_line( }; }; - try out_stream.print("{s}", .{src_line.line}); + try terminal.writer.print("{s}", .{src_line.line}); if (src_line.too_long) { - try out_stream.writeAll(" [...]"); + try terminal.writer.writeAll(" [...]"); } - try out_stream.writeAll("\n"); + try terminal.writer.writeAll("\n"); if (src_loc.column > 0) { const space_needed = src_loc.column - 1; - try out_stream.splatByteAll(' ', space_needed); - try out_tty_config.setColor(out_stream, .green); - try out_stream.writeAll("^"); - try out_tty_config.setColor(out_stream, .reset); + try terminal.writer.splatByteAll(' ', space_needed); + try terminal.setColor(.green); + try terminal.writer.writeAll("^"); + try terminal.setColor(.reset); } - try out_stream.writeAll("\n"); + + try terminal.writer.writeAll("\n"); } diff --git a/tools/printer/tests/generate_test_data.zig b/tools/printer/tests/generate_test_data.zig index b662e0d22..6675b94f2 100644 --- a/tools/printer/tests/generate_test_data.zig +++ b/tools/printer/tests/generate_test_data.zig @@ -7,20 +7,19 @@ const common = @import("common"); var test_data_writer_buf: [1024]u8 = undefined; var elf_file_reader_buf: [1024]u8 = undefined; -pub fn main() !void { - var arena_allocator: std.heap.ArenaAllocator = .init(std.heap.page_allocator); - defer arena_allocator.deinit(); - const allocator = arena_allocator.allocator(); +pub fn main(init: std.process.Init) !void { + const io = init.io; + const allocator = init.arena.allocator(); - const args = try std.process.argsAlloc(allocator); + const args = try init.minimal.args.toSlice(allocator); if (args.len != 3) return error.UsageError; const elf_path = args[1]; const test_data_path = args[2]; - const elf_file = try std.fs.cwd().openFile(elf_path, .{}); - defer elf_file.close(); - var elf_file_reader = elf_file.reader(&elf_file_reader_buf); + const elf_file = try std.Io.Dir.cwd().openFile(io, elf_path, .{}); + defer elf_file.close(io); + var elf_file_reader = elf_file.reader(io, &elf_file_reader_buf); const elf = try printer.Elf.init(allocator, &elf_file_reader); var debug_info = try printer.DebugInfo.init(allocator, elf); @@ -44,9 +43,9 @@ pub fn main() !void { }); } - var test_data_file = try std.fs.cwd().createFile(test_data_path, .{}); - defer test_data_file.close(); - var test_data_writer = test_data_file.writer(&.{}); + var test_data_file = try std.Io.Dir.cwd().createFile(io, test_data_path, .{}); + defer test_data_file.close(io); + var test_data_writer = test_data_file.writer(io, &.{}); const data: common.Data = .{ .zig_version = builtin.zig_version_string, diff --git a/tools/printer/tests/test.zig b/tools/printer/tests/test.zig index f80d31295..5f1551168 100644 --- a/tools/printer/tests/test.zig +++ b/tools/printer/tests/test.zig @@ -6,38 +6,37 @@ const common = @import("common"); var buf: [1024]u8 = undefined; -pub fn main() !void { - var debug_allocator: std.heap.DebugAllocator(.{}) = .init; - defer _ = debug_allocator.deinit(); - const allocator = debug_allocator.allocator(); +pub fn main(init: std.process.Init) !void { + const gpa = init.gpa; + const io = init.io; - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); - - if (args.len != 3) return error.UsageError; + const args = try init.minimal.args.toSlice(init.arena.allocator()); + if (args.len != 3) + return error.UsageError; const elf_path = args[1]; const test_data_path = args[2]; const test_name = std.fs.path.stem(test_data_path); - const elf_file = try std.fs.cwd().openFile(elf_path, .{}); - defer elf_file.close(); + const elf_file = try std.Io.Dir.cwd().openFile(io, elf_path, .{}); + defer elf_file.close(io); - var elf_file_reader = elf_file.reader(&buf); + var elf_file_reader = elf_file.reader(io, &buf); - var elf = try printer.Elf.init(allocator, &elf_file_reader); - defer elf.deinit(allocator); + var elf = try printer.Elf.init(gpa, &elf_file_reader); + defer elf.deinit(gpa); - const test_data_raw = try std.fs.cwd().readFileAllocOptions(allocator, test_data_path, 1_000_000, null, .@"1", 0); - defer allocator.free(test_data_raw); + const test_data_raw = try std.Io.Dir.cwd().readFileAllocOptions(io, test_data_path, gpa, .limited(1_000_000), .@"1", 0); + defer gpa.free(test_data_raw); - const test_data = try std.zon.parse.fromSlice(common.Data, allocator, test_data_raw, null, .{}); - defer std.zon.parse.free(allocator, test_data); + const test_data = try std.zon.parse.fromSliceAlloc(common.Data, gpa, test_data_raw, null, .{}); + defer std.zon.parse.free(gpa, test_data); - var debug_info = try printer.DebugInfo.init(allocator, elf); - defer debug_info.deinit(allocator); + var debug_info = try printer.DebugInfo.init(gpa, elf); + defer debug_info.deinit(gpa); - if (!std.mem.eql(u8, test_data.zig_version, builtin.zig_version_string)) return error.ZigVersionMismatch; + if (!std.mem.eql(u8, test_data.zig_version, builtin.zig_version_string)) + return error.ZigVersionMismatch; for (test_data.tests) |t| { const actual = debug_info.query(t.address); diff --git a/tools/printer/tests/test_program.dwarf32.zon b/tools/printer/tests/test_program.dwarf32.zon index 3fc214322..9e4453876 100644 --- a/tools/printer/tests/test_program.dwarf32.zon +++ b/tools/printer/tests/test_program.dwarf32.zon @@ -1,69 +1,69 @@ -.{ .zig_version = "0.15.1", .tests = .{ - .{ .address = 16883712, .expected = .{ - .line = 165, +.{ .zig_version = "0.16.0", .tests = .{ + .{ .address = 16924672, .expected = .{ + .line = 163, .column = 33, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883785, .expected = .{ - .line = 166, + .{ .address = 16924745, .expected = .{ + .line = 164, .column = 13, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883793, .expected = .{ - .line = 166, + .{ .address = 16924753, .expected = .{ + .line = 164, .column = 67, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883808, .expected = .{ - .line = 167, + .{ .address = 16924773, .expected = .{ + .line = 165, .column = 13, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883816, .expected = .{ - .line = 167, + .{ .address = 16924781, .expected = .{ + .line = 165, .column = 67, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883828, .expected = .{ - .line = 168, + .{ .address = 16924801, .expected = .{ + .line = 166, .column = 40, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883828, .expected = .{ - .line = 168, + .{ .address = 16924801, .expected = .{ + .line = 166, .column = 40, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883836, .expected = .{ - .line = 168, + .{ .address = 16924809, .expected = .{ + .line = 166, .column = 52, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883842, .expected = .{ - .line = 168, + .{ .address = 16924815, .expected = .{ + .line = 166, .column = 52, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16883949, .expected = .{ - .line = 169, + .{ .address = 16924918, .expected = .{ + .line = 167, .column = 18, .file_path = "ubsan_rt.zig", .function_name = null, diff --git a/tools/printer/tests/test_program.dwarf64.zon b/tools/printer/tests/test_program.dwarf64.zon index b322f23d0..d5f4ad06c 100644 --- a/tools/printer/tests/test_program.dwarf64.zon +++ b/tools/printer/tests/test_program.dwarf64.zon @@ -1,72 +1 @@ -.{ .zig_version = "0.15.1", .tests = .{ - .{ .address = 16900096, .expected = .{ - .line = 165, - .column = 33, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900169, .expected = .{ - .line = 166, - .column = 13, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900177, .expected = .{ - .line = 166, - .column = 67, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900192, .expected = .{ - .line = 167, - .column = 13, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900200, .expected = .{ - .line = 167, - .column = 67, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900212, .expected = .{ - .line = 168, - .column = 40, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900212, .expected = .{ - .line = 168, - .column = 40, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900220, .expected = .{ - .line = 168, - .column = 52, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900226, .expected = .{ - .line = 168, - .column = 52, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, - .{ .address = 16900333, .expected = .{ - .line = 169, - .column = 18, - .file_path = "ubsan_rt.zig", - .function_name = null, - .module_name = "ubsan_rt.zig", - } }, -} } +.{ .zig_version = "0.16.0", .tests = .{} } diff --git a/tools/regz/src/Database.zig b/tools/regz/src/Database.zig index 19f637fa8..43a72c6f7 100644 --- a/tools/regz/src/Database.zig +++ b/tools/regz/src/Database.zig @@ -637,7 +637,7 @@ pub fn create_from_path(gpa: Allocator, io: std.Io, format: Format, path: []cons break :blk db; }, .svd, .atdf => blk: { - const text = try std.Io.Dir.cwd().readFileAlloc(io, path, gpa, @enumFromInt(file_size_max)); + const text = try std.Io.Dir.cwd().readFileAlloc(io, path, gpa, .limited(file_size_max)); defer gpa.free(text); break :blk create_from_xml(gpa, format, text); diff --git a/tools/regz/src/targetdb.zig b/tools/regz/src/targetdb.zig index ff2bbd804..b5ba477f8 100644 --- a/tools/regz/src/targetdb.zig +++ b/tools/regz/src/targetdb.zig @@ -78,7 +78,7 @@ fn load_device( filename: []const u8, modules: *std.StringHashMap(ModuleEntry), ) !void { - const device_text = try devices_dir.readFileAlloc(io, filename, db.gpa, @enumFromInt(1024 * 1024)); + const device_text = try devices_dir.readFileAlloc(io, filename, db.gpa, .limited(1024 * 1024)); defer db.gpa.free(device_text); var doc = try xml.Doc.from_memory(device_text); @@ -155,7 +155,7 @@ fn load_instance( // Load the module file for the first time log.debug("Loading new peripheral type from module file: {s}", .{href}); - const module_text = try devices_dir.readFileAlloc(io, href, db.gpa, @enumFromInt(1024 * 1024)); + const module_text = try devices_dir.readFileAlloc(io, href, db.gpa, .limited(1024 * 1024)); defer db.gpa.free(module_text); var doc = try xml.Doc.from_memory(module_text); From 6762e129ddd2cda19c778b209921b2ac89a163f5 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 11:54:45 -0700 Subject: [PATCH 19/61] Remove unused imports/decls --- port/gigadevice/gd32/src/hals/GD32VF103/pins.zig | 2 -- port/raspberrypi/rp2xxx/src/hal/pins.zig | 3 --- port/raspberrypi/rp2xxx/src/hal/uart.zig | 2 -- port/stmicro/stm32/src/hals/STM32F103/pins.zig | 3 --- port/stmicro/stm32/src/hals/common/pins_v2.zig | 2 -- port/wch/ch32v/src/hals/ch32v003/pins.zig | 3 --- port/wch/ch32v/src/hals/pins.zig | 3 --- sim/aviron/src/lib/bus.zig | 1 - sim/aviron/src/main.zig | 2 -- tools/linter/src/main.zig | 2 -- tools/regz/build.zig | 3 --- tools/regz/src/atdf.zig | 2 -- tools/regz/src/main.zig | 2 -- tools/regz/src/svd.zig | 7 ------- tools/uf2/src/uf2.zig | 2 -- 15 files changed, 39 deletions(-) diff --git a/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig b/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig index 82d55608c..afcdc50f6 100644 --- a/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig +++ b/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig @@ -1,7 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.Type.StructField; const microzig = @import("microzig"); diff --git a/port/raspberrypi/rp2xxx/src/hal/pins.zig b/port/raspberrypi/rp2xxx/src/hal/pins.zig index 655a56090..3f97b3133 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pins.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pins.zig @@ -1,7 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.Type.StructField; const microzig = @import("microzig"); const SIO = microzig.chip.peripherals.SIO; @@ -10,7 +8,6 @@ const XIP_CTRL = microzig.chip.peripherals.XIP_CTRL; const gpio = @import("gpio.zig"); const pwm = @import("pwm.zig"); const adc = @import("adc.zig"); -const resets = @import("resets.zig"); const compatibility = @import("compatibility.zig"); const chip = compatibility.chip; diff --git a/port/raspberrypi/rp2xxx/src/hal/uart.zig b/port/raspberrypi/rp2xxx/src/hal/uart.zig index a901cc36e..17094e13f 100644 --- a/port/raspberrypi/rp2xxx/src/hal/uart.zig +++ b/port/raspberrypi/rp2xxx/src/hal/uart.zig @@ -7,10 +7,8 @@ const peripherals = microzig.chip.peripherals; const UART0_reg = peripherals.UART0; const UART1_reg = peripherals.UART1; -const gpio = @import("gpio.zig"); const clocks = @import("clocks.zig"); const dma = @import("dma.zig"); -const resets = @import("resets.zig"); const time = @import("time.zig"); const UartRegs = microzig.chip.types.peripherals.UART0; diff --git a/port/stmicro/stm32/src/hals/STM32F103/pins.zig b/port/stmicro/stm32/src/hals/STM32F103/pins.zig index 2d993de05..d106be8fb 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/pins.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/pins.zig @@ -1,10 +1,7 @@ const std = @import("std"); -const assert = std.debug.assert; const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.Type.StructField; const microzig = @import("microzig"); - const RCC = microzig.chip.peripherals.RCC; const gpio = @import("gpio.zig"); diff --git a/port/stmicro/stm32/src/hals/common/pins_v2.zig b/port/stmicro/stm32/src/hals/common/pins_v2.zig index 1aacb9e6a..6627d54b0 100644 --- a/port/stmicro/stm32/src/hals/common/pins_v2.zig +++ b/port/stmicro/stm32/src/hals/common/pins_v2.zig @@ -1,7 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.Type.StructField; const microzig = @import("microzig"); const enums = @import("../common/enums.zig"); diff --git a/port/wch/ch32v/src/hals/ch32v003/pins.zig b/port/wch/ch32v/src/hals/ch32v003/pins.zig index ccf3f2573..6c6a14ecc 100644 --- a/port/wch/ch32v/src/hals/ch32v003/pins.zig +++ b/port/wch/ch32v/src/hals/ch32v003/pins.zig @@ -1,11 +1,8 @@ const std = @import("std"); const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.Type.StructField; const microzig = @import("microzig"); - const RCC = microzig.chip.peripherals.RCC; - const hal = microzig.hal; const gpio = hal.gpio; diff --git a/port/wch/ch32v/src/hals/pins.zig b/port/wch/ch32v/src/hals/pins.zig index d6c3dadd4..8b595e1cd 100644 --- a/port/wch/ch32v/src/hals/pins.zig +++ b/port/wch/ch32v/src/hals/pins.zig @@ -1,11 +1,8 @@ const std = @import("std"); const comptimePrint = std.fmt.comptimePrint; -const StructField = std.builtin.Type.StructField; const microzig = @import("microzig"); - const RCC = microzig.chip.peripherals.RCC; - const hal = microzig.hal; const gpio = hal.gpio; diff --git a/sim/aviron/src/lib/bus.zig b/sim/aviron/src/lib/bus.zig index 70e412d14..dfb2c8097 100644 --- a/sim/aviron/src/lib/bus.zig +++ b/sim/aviron/src/lib/bus.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const isa = @import("decoder.zig"); pub const Flash = struct { pub const Address = u24; diff --git a/sim/aviron/src/main.zig b/sim/aviron/src/main.zig index a06ccaa93..5915e8e73 100644 --- a/sim/aviron/src/main.zig +++ b/sim/aviron/src/main.zig @@ -4,8 +4,6 @@ const aviron = @import("aviron"); const ihex = @import("ihex"); const flags = @import("flags"); -const log = std.log.scoped(.main); - const RunWith_MCU_Options = struct { trace: bool = false, info: bool = false, diff --git a/tools/linter/src/main.zig b/tools/linter/src/main.zig index 70fc16a2b..f90ccae1b 100644 --- a/tools/linter/src/main.zig +++ b/tools/linter/src/main.zig @@ -1,7 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; const Allocator = std.mem.Allocator; - const Token = std.zig.Token; const TokenIndex = std.zig.Ast.TokenIndex; diff --git a/tools/regz/build.zig b/tools/regz/build.zig index ce6146130..0b5a9c08d 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -1,8 +1,5 @@ const std = @import("std"); const Build = std.Build; -const Compile = Build.Compile; -const Step = Build.Step; -const GeneratedFile = Build.GeneratedFile; pub const patch = @import("src/patch.zig"); diff --git a/tools/regz/src/atdf.zig b/tools/regz/src/atdf.zig index 70f8497db..d4b5649af 100644 --- a/tools/regz/src/atdf.zig +++ b/tools/regz/src/atdf.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const ArenaAllocator = std.heap.ArenaAllocator; const Allocator = std.mem.Allocator; const assert = std.debug.assert; @@ -1094,7 +1093,6 @@ fn validate_attrs(node: xml.Node, attrs: []const []const u8) void { } } -const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectEqualStrings = std.testing.expectEqualStrings; diff --git a/tools/regz/src/main.zig b/tools/regz/src/main.zig index 53e945631..c658bfb71 100644 --- a/tools/regz/src/main.zig +++ b/tools/regz/src/main.zig @@ -5,9 +5,7 @@ const Database = regz.Database; const xml = @import("xml"); -const ArenaAllocator = std.heap.ArenaAllocator; const Allocator = std.mem.Allocator; -const assert = std.debug.assert; pub const std_options = std.Options{ .log_level = .warn, diff --git a/tools/regz/src/svd.zig b/tools/regz/src/svd.zig index 983325164..69f29d9fc 100644 --- a/tools/regz/src/svd.zig +++ b/tools/regz/src/svd.zig @@ -1,7 +1,6 @@ const std = @import("std"); const ArenaAllocator = std.heap.ArenaAllocator; const Allocator = std.mem.Allocator; -const assert = std.debug.assert; const xml = @import("xml"); const Arch = @import("arch.zig").Arch; @@ -10,7 +9,6 @@ const Database = @import("Database.zig"); const Access = Database.Access; const StructID = Database.StructID; const DeviceID = Database.DeviceID; -const PeripheralID = Database.PeripheralID; const RegisterID = Database.RegisterID; const EnumID = Database.EnumID; @@ -680,11 +678,6 @@ pub const DimableIdentifier = struct { /// pattern: [0-9]+\-[0-9]+|[A-Z]-[A-Z]|[_0-9a-zA-Z]+(,\s*[_0-9a-zA-Z]+)+ pub const DimIndex = struct {}; -const DimType = enum { - array, - list, -}; - const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectError = std.testing.expectError; diff --git a/tools/uf2/src/uf2.zig b/tools/uf2/src/uf2.zig index 214403139..9f2924f93 100644 --- a/tools/uf2/src/uf2.zig +++ b/tools/uf2/src/uf2.zig @@ -1,12 +1,10 @@ const std = @import("std"); -const testing = std.testing; const assert = std.debug.assert; const Allocator = std.mem.Allocator; pub const FamilyId = @import("family_id.zig").FamilyId; const prog_page_size = 256; -const uf2_alignment = 4; pub const Archive = struct { allocator: Allocator, From 53c4bfe72c8ace8b6aa66a36caa0aeaa566ffec1 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 13:25:48 -0700 Subject: [PATCH 20/61] Reorganize drivers --- drivers/README.md | 110 +++++++++--------- drivers/build.zig | 2 +- .../base/BlockMemory.zig} | 20 ++-- .../base/ClockDevice.zig} | 48 ++++---- .../base/DatagramDevice.zig} | 62 +++++----- drivers/{ => src}/base/DateTime.zig | 2 +- drivers/{ => src}/base/Digital_IO.zig | 28 ++--- drivers/{ => src}/base/I2C_Device.zig | 34 +++--- .../base/StreamDevice.zig} | 93 +++++++-------- drivers/{ => src}/display/colors.zig | 0 drivers/{ => src}/display/common.zig | 0 drivers/{ => src}/display/hd44780.zig | 16 +-- drivers/{ => src}/display/sh1106.zig | 26 ++--- .../{ => src}/display/sharp_memory_lcd.zig | 20 ++-- drivers/{ => src}/display/ssd1306.zig | 34 +++--- drivers/{ => src}/display/st77xx.zig | 20 ++-- .../input/debounced_button.zig} | 16 +-- .../input/keyboard_matrix.zig} | 22 ++-- .../input/rotary_encoder.zig} | 14 +-- drivers/{ => src}/io_expander/pca9685.zig | 12 +- drivers/{ => src}/io_expander/pcf8574.zig | 18 +-- drivers/{ => src}/led/ws2812.zig | 14 +-- drivers/{framework.zig => src/root.zig} | 42 +++---- drivers/{ => src}/sensor/AHT30.zig | 2 +- drivers/{ => src}/sensor/AS5600.zig | 2 +- drivers/{ => src}/sensor/DS18B20.zig | 6 +- drivers/{ => src}/sensor/HTS221.zig | 2 +- .../sensor/ICM_20948.zig} | 66 +++++------ drivers/{ => src}/sensor/MLX90640.zig | 52 ++++----- .../MPU-6050.zig => src/sensor/MPU_6050.zig} | 14 +-- drivers/{ => src}/sensor/TLV493D.zig | 8 +- drivers/{ => src}/sensor/TMP117.zig | 2 +- drivers/{ => src}/stepper/ULN2003.zig | 30 ++--- drivers/{ => src}/stepper/common.zig | 2 +- drivers/{ => src}/stepper/stepper.zig | 64 +++++----- drivers/{ => src}/wireless/cyw43/bus.zig | 34 +++--- drivers/{ => src}/wireless/cyw43/consts.zig | 0 drivers/{ => src}/wireless/cyw43/cyw43.zig | 0 .../cyw43/firmware/43439A0_7_95_61.bin | Bin .../cyw43/firmware/43439A0_7_95_88.bin | Bin .../wireless/cyw43/firmware/43439A0_btfw.bin | Bin .../wireless/cyw43/firmware/43439A0_clm.bin | Bin .../LICENSE-permissive-binary-license-1.0.txt | 0 .../wireless/cyw43/firmware/README.md | 0 drivers/{ => src}/wireless/cyw43/nvram.zig | 0 drivers/{ => src}/wireless/cyw43/runner.zig | 2 +- drivers/{ => src}/wireless/cyw43/sdpcm.zig | 0 drivers/{ => src}/wireless/cyw43/wifi.zig | 0 drivers/{ => src}/wireless/cyw43439.zig | 0 drivers/{ => src}/wireless/cyw43439/bus.zig | 12 +- drivers/{ => src}/wireless/cyw43439/ioctl.zig | 66 +++++------ drivers/{ => src}/wireless/cyw43439/nvram.zig | 0 drivers/{ => src}/wireless/cyw43439/wifi.zig | 6 +- .../espressif/esp/src/i2c_display_sh1106.zig | 6 +- examples/espressif/esp/src/ws2812_blinky.zig | 2 +- .../rp2xxx/src/mlx90640_hottest_point.zig | 2 +- .../raspberrypi/rp2xxx/src/mlx90640_image.zig | 2 +- .../raspberrypi/rp2xxx/src/ssd1306_oled.zig | 2 +- .../stmicro/stm32/src/stm32f1xx/ssd1306.zig | 4 +- examples/wch/ch32v/src/sharp_niceview.zig | 2 +- port/espressif/esp/src/hal/drivers.zig | 50 ++++---- port/nordic/nrf5x/src/hal/drivers.zig | 59 +++++----- port/raspberrypi/rp2xxx/src/hal/drivers.zig | 56 ++++----- .../stm32/src/hals/STM32F103/drivers.zig | 28 ++--- .../stm32/src/hals/common/systick_timer.zig | 6 +- port/wch/ch32v/src/hals/drivers.zig | 54 ++++----- port/wch/ch32v/src/hals/spi.zig | 4 +- 67 files changed, 644 insertions(+), 656 deletions(-) rename drivers/{base/Block_Memory.zig => src/base/BlockMemory.zig} (88%) rename drivers/{base/Clock_Device.zig => src/base/ClockDevice.zig} (70%) rename drivers/{base/Datagram_Device.zig => src/base/DatagramDevice.zig} (85%) rename drivers/{ => src}/base/DateTime.zig (99%) rename drivers/{ => src}/base/Digital_IO.zig (85%) rename drivers/{ => src}/base/I2C_Device.zig (93%) rename drivers/{base/Stream_Device.zig => src/base/StreamDevice.zig} (81%) rename drivers/{ => src}/display/colors.zig (100%) rename drivers/{ => src}/display/common.zig (100%) rename drivers/{ => src}/display/hd44780.zig (97%) rename drivers/{ => src}/display/sh1106.zig (95%) rename drivers/{ => src}/display/sharp_memory_lcd.zig (96%) rename drivers/{ => src}/display/ssd1306.zig (97%) rename drivers/{ => src}/display/st77xx.zig (96%) rename drivers/{input/debounced-button.zig => src/input/debounced_button.zig} (96%) rename drivers/{input/keyboard-matrix.zig => src/input/keyboard_matrix.zig} (92%) rename drivers/{input/rotary-encoder.zig => src/input/rotary_encoder.zig} (91%) rename drivers/{ => src}/io_expander/pca9685.zig (92%) rename drivers/{ => src}/io_expander/pcf8574.zig (86%) rename drivers/{ => src}/led/ws2812.zig (85%) rename drivers/{framework.zig => src/root.zig} (86%) rename drivers/{ => src}/sensor/AHT30.zig (99%) rename drivers/{ => src}/sensor/AS5600.zig (99%) rename drivers/{ => src}/sensor/DS18B20.zig (99%) rename drivers/{ => src}/sensor/HTS221.zig (99%) rename drivers/{sensor/ICM-20948.zig => src/sensor/ICM_20948.zig} (95%) rename drivers/{ => src}/sensor/MLX90640.zig (97%) rename drivers/{sensor/MPU-6050.zig => src/sensor/MPU_6050.zig} (97%) rename drivers/{ => src}/sensor/TLV493D.zig (98%) rename drivers/{ => src}/sensor/TMP117.zig (99%) rename drivers/{ => src}/stepper/ULN2003.zig (94%) rename drivers/{ => src}/stepper/common.zig (97%) rename drivers/{ => src}/stepper/stepper.zig (92%) rename drivers/{ => src}/wireless/cyw43/bus.zig (92%) rename drivers/{ => src}/wireless/cyw43/consts.zig (100%) rename drivers/{ => src}/wireless/cyw43/cyw43.zig (100%) rename drivers/{ => src}/wireless/cyw43/firmware/43439A0_7_95_61.bin (100%) rename drivers/{ => src}/wireless/cyw43/firmware/43439A0_7_95_88.bin (100%) rename drivers/{ => src}/wireless/cyw43/firmware/43439A0_btfw.bin (100%) rename drivers/{ => src}/wireless/cyw43/firmware/43439A0_clm.bin (100%) rename drivers/{ => src}/wireless/cyw43/firmware/LICENSE-permissive-binary-license-1.0.txt (100%) rename drivers/{ => src}/wireless/cyw43/firmware/README.md (100%) rename drivers/{ => src}/wireless/cyw43/nvram.zig (100%) rename drivers/{ => src}/wireless/cyw43/runner.zig (99%) rename drivers/{ => src}/wireless/cyw43/sdpcm.zig (100%) rename drivers/{ => src}/wireless/cyw43/wifi.zig (100%) rename drivers/{ => src}/wireless/cyw43439.zig (100%) rename drivers/{ => src}/wireless/cyw43439/bus.zig (98%) rename drivers/{ => src}/wireless/cyw43439/ioctl.zig (95%) rename drivers/{ => src}/wireless/cyw43439/nvram.zig (100%) rename drivers/{ => src}/wireless/cyw43439/wifi.zig (99%) diff --git a/drivers/README.md b/drivers/README.md index fc533b3fb..3ecadd659 100644 --- a/drivers/README.md +++ b/drivers/README.md @@ -7,12 +7,12 @@ A collection of device drivers and driver abstractions for embedded systems usin - [Introduction](#introduction) - [Available Drivers](#available-drivers) - [Base Interfaces](#base-interfaces) - - [Datagram_Device](#datagram_device) - - [Stream_Device](#stream_device) + - [DatagramDevice](#datagram_device) + - [StreamDevice](#stream_device) - [Digital_IO](#digital_io) - [I2C_Device](#i2c_device) - - [Clock_Device](#clock_device) - - [Block_Memory](#block_memory) + - [ClockDevice](#clock_device) + - [BlockMemory](#block_memory) - [Writing a Simple Driver](#writing-a-simple-driver) - [Zero-Cost Abstraction Pattern](#zero-cost-abstraction-pattern) - [The Problem](#the-problem) @@ -90,7 +90,7 @@ Drivers with a checkmark are already implemented, drivers without are missing: All base interfaces are located in `drivers/base/` and are re-exported through `microzig.drivers.base.*`. -### Datagram_Device +### DatagramDevice **Purpose**: Abstract packet-oriented communication devices where data is transferred in fixed-size packets with known boundaries. @@ -99,7 +99,7 @@ packets with known boundaries. **Structure**: ```zig -pub const Datagram_Device = struct { +pub const DatagramDevice = struct { ptr: *anyopaque, vtable: *const VTable, @@ -146,7 +146,7 @@ try spi_dd.write_then_read(cmd, &data); --- -### Stream_Device +### StreamDevice **Purpose**: Abstract stream-oriented communication devices with continuous data flow and no packet boundaries. @@ -155,7 +155,7 @@ boundaries. **Structure**: ```zig -pub const Stream_Device = struct { +pub const StreamDevice = struct { ptr: *anyopaque, vtable: *const VTable, @@ -330,7 +330,7 @@ const temp_celsius = @as(f32, @intCast(temp_raw)) * 0.0625; --- -### Clock_Device +### ClockDevice **Purpose**: Provide time tracking and sleep functionality for drivers that need timing. @@ -367,7 +367,7 @@ pub const Deadline = struct { **Structure**: ```zig -pub const Clock_Device = struct { +pub const ClockDevice = struct { ptr: *anyopaque, vtable: *const VTable, @@ -405,7 +405,7 @@ clock.sleep_ms(10); --- -### Block_Memory +### BlockMemory **Purpose**: Abstract flash/block memory operations with sector-based erase and write. @@ -420,7 +420,7 @@ pub const ReadError = BaseError || error{ReadDisabled}; **Structure**: ```zig -pub const Block_Memory = struct { +pub const BlockMemory = struct { ptr: *anyopaque, vtable: *const VTable, @@ -593,7 +593,7 @@ concrete struct type. ```zig pub const Driver_Options = struct { // Defaults to vtable interface - Device_Interface: type = mdf.base.Datagram_Device, + Device_Interface: type = mdf.base.DatagramDevice, // Other configuration... }; @@ -635,7 +635,7 @@ const mdf = @import("microzig").drivers; pub const Display_Options = struct { width: comptime_int, height: comptime_int, - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, }; /// Helper init function that infers type from argument @@ -646,13 +646,13 @@ pub fn init( ) !Display(.{ .width = width, .height = height, - .Datagram_Device = @TypeOf(datagram_device), // Infer concrete type + .DatagramDevice = @TypeOf(datagram_device), // Infer concrete type }) { // Create specialized type const Type = Display(.{ .width = width, .height = height, - .Datagram_Device = @TypeOf(datagram_device), + .DatagramDevice = @TypeOf(datagram_device), }); // Forward to actual init @@ -663,9 +663,9 @@ pub fn init( pub fn Display(comptime options: Display_Options) type { return struct { const Self = @This(); - dd: options.Datagram_Device, + dd: options.DatagramDevice, - pub fn init(dd: options.Datagram_Device) !Self { + pub fn init(dd: options.DatagramDevice) !Self { return .{ .dd = dd }; } @@ -680,7 +680,7 @@ pub fn Display(comptime options: Display_Options) type { const hal = microzig.hal; // Create concrete SPI device -var spi_dev = hal.drivers.SPI_Datagram_Device(...).init(...); +var spi_dev = hal.drivers.SPI_DatagramDevice(...).init(...); // Type is inferred from spi_dev - no need to specify! var display = try init(160, 68, spi_dev); @@ -691,7 +691,7 @@ var display = try init(160, 68, spi_dev); // var display = Display(.{ // .width = 160, // .height = 68, -// .Datagram_Device = @TypeOf(spi_dev), +// .DatagramDevice = @TypeOf(spi_dev), // }).init(spi_dev); ``` @@ -707,7 +707,7 @@ pub const Display_Config = struct { width: comptime_int, height: comptime_int, vcom_mode: enum { none, software }, // VCOM toggling mode - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, Digital_IO: ?type = null, // Optional display enable pin }; @@ -715,7 +715,7 @@ pub fn Display(comptime config: Display_Config) type { return struct { const Self = @This(); - dd: config.Datagram_Device, + dd: config.DatagramDevice, // Pin field only exists if Digital_IO is provided disp_pin: if (config.Digital_IO) |T| T else void, @@ -724,7 +724,7 @@ pub fn Display(comptime config: Display_Config) type { vcom_state: if (config.vcom_mode == .software) bool else void, pub fn init( - dd: config.Datagram_Device, + dd: config.DatagramDevice, disp_pin: if (config.Digital_IO) |T| T else void, ) !Self { var self = Self{ @@ -796,15 +796,15 @@ pub const Config = struct { width: comptime_int, height: comptime_int, vcom_mode: VCOM_Mode = .none, - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, Digital_IO: ?type = null, }; -pub fn Sharp_Memory_LCD(comptime config: Config) type { +pub fn SharpMemory_LCD(comptime config: Config) type { return struct { const Self = @This(); - dd: config.Datagram_Device, + dd: config.DatagramDevice, // Pin only exists if Digital_IO is provided disp_pin: if (config.Digital_IO) |T| T else void, @@ -831,11 +831,11 @@ pub fn Sharp_Memory_LCD(comptime config: Config) type { ```zig // nice!view display - no VCOM needed -const Display = mdf.display.Sharp_Memory_LCD(.{ +const Display = mdf.display.SharpMemory_LCD(.{ .width = 160, .height = 68, .vcom_mode = .none, // Feature disabled at compile time - .Datagram_Device = @TypeOf(spi_dev), // Zero-cost concrete type + .DatagramDevice = @TypeOf(spi_dev), // Zero-cost concrete type }); ``` @@ -848,18 +848,18 @@ This driver accepts multiple interface types: ```zig pub fn WS2812(options: struct { max_led_count: usize = 1, - Datagram_Device: type = mdf.base.Datagram_Device, - Clock_Device: type = mdf.base.Clock_Device, + DatagramDevice: type = mdf.base.DatagramDevice, + ClockDevice: type = mdf.base.Clock_Device, }) type { return struct { const Self = @This(); - dev: options.Datagram_Device, - clock_dev: options.Clock_Device, + dev: options.DatagramDevice, + clock_dev: options.ClockDevice, pub fn init( - dev: options.Datagram_Device, - clock_dev: options.Clock_Device, + dev: options.DatagramDevice, + clock_dev: options.ClockDevice, ) Self { return .{ .dev = dev, @@ -895,8 +895,8 @@ pub fn WS2812(options: struct { // Create with concrete types for maximum performance var ws2812: WS2812(.{ .max_led_count = 1, - .Datagram_Device = hal.drivers.SPI_Device, - .Clock_Device = hal.drivers.Clock, + .DatagramDevice = hal.drivers.SPI_Device, + .ClockDevice = hal.drivers.Clock, }) = .init(spi_dev, clock); const red: Color = .{ .r = 255, .g = 0, .b = 0 }; @@ -911,7 +911,7 @@ This driver provides a helper init function that infers the type: ```zig pub const PCA9685_Config = struct { - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, oscillator_frequency: u32 = 25_000_000, }; @@ -919,9 +919,9 @@ pub const PCA9685_Config = struct { pub fn init( datagram_device: anytype, frequency: u32, -) !PCA9685(.{ .Datagram_Device = @TypeOf(datagram_device) }) { +) !PCA9685(.{ .DatagramDevice = @TypeOf(datagram_device) }) { const Type = PCA9685(.{ - .Datagram_Device = @TypeOf(datagram_device), + .DatagramDevice = @TypeOf(datagram_device), // ^^^^^^ Type inference! }); @@ -932,9 +932,9 @@ pub fn init( pub fn PCA9685(comptime config: PCA9685_Config) type { return struct { const Self = @This(); - dd: config.Datagram_Device, + dd: config.DatagramDevice, - fn init(dd: config.Datagram_Device, frequency: u32) !Self { + fn init(dd: config.DatagramDevice, frequency: u32) !Self { var self = Self{ .dd = dd }; try self.reset(); try self.set_pwm_freq(frequency); @@ -954,7 +954,7 @@ var pwm = try pca9685.init(i2c_dev, 50); // 50 Hz for servos // Equivalent to manually specifying: // var pwm = pca9685.PCA9685(.{ -// .Datagram_Device = @TypeOf(i2c_dev), +// .DatagramDevice = @TypeOf(i2c_dev), // }).init(i2c_dev, 50); ``` @@ -969,14 +969,14 @@ pub const Driver_Mode = enum { i2c, spi_3wire, spi_4wire, dynamic }; pub const SSD1306_Options = struct { mode: Driver_Mode, - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, Digital_IO: type = mdf.base.Digital_IO, }; pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { return struct { const Self = @This(); - const Datagram_Device = options.Datagram_Device; + const DatagramDevice = options.DatagramDevice; // Digital_IO only exists for 4-wire SPI mode const Digital_IO = switch (options.mode) { @@ -984,18 +984,18 @@ pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { .i2c, .spi_3wire => void, // Not used - no overhead }; - dd: Datagram_Device, + dd: DatagramDevice, dev_pin: Digital_IO, // Will be 'void' for I2C/3-wire SPI // Init varies by mode - pub fn init_without_io(dd: Datagram_Device) !Self { + pub fn init_without_io(dd: DatagramDevice) !Self { return .{ .dd = dd, .dev_pin = {}, // void for I2C/3-wire modes }; } - pub fn init_with_io(dd: Datagram_Device, pin: Digital_IO) !Self { + pub fn init_with_io(dd: DatagramDevice, pin: Digital_IO) !Self { return .{ .dd = dd, .dev_pin = pin, @@ -1078,7 +1078,7 @@ This section shows how to create HAL wrappers that implement the base interfaces ### Creating a Concrete Implementation -Here's how the CH32V port implements `SPI_Datagram_Device`: +Here's how the CH32V port implements `SPI_DatagramDevice`: **File**: `port/wch/ch32v/src/hals/drivers.zig` @@ -1089,7 +1089,7 @@ const mdf = microzig.drivers; /// SPI Datagram Device implementation /// Generic over SPI configuration to enable compile-time DMA optimization -pub fn SPI_Datagram_Device(comptime config: spi.Config) type { +pub fn SPI_DatagramDevice(comptime config: spi.Config) type { return struct { const Self = @This(); // ... Add required fields @@ -1099,7 +1099,7 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { } /// Create vtable interface from this concrete type - pub fn datagram_device(dev: *Self) Datagram_Device { + pub fn datagram_device(dev: *Self) DatagramDevice { return .{ .ptr = dev, .vtable = &datagram_vtable, @@ -1133,7 +1133,7 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { // Vtable implementation (for runtime polymorphism mode) - const datagram_vtable = Datagram_Device.VTable{ + const datagram_vtable = DatagramDevice.VTable{ .connect_fn = connect_fn, .disconnect_fn = disconnect_fn, .writev_fn = writev_fn, @@ -1184,15 +1184,15 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { var spi_dev = SPI_DD.init(spi1, cs_pin, false, timeout); var datagram_if = spi_dev.datagram_device(); // Get vtable interface -const Display = Sharp_Memory_LCD(.{}); // Uses default vtable type +const Display = SharpMemory_LCD(.{}); // Uses default vtable type var display = Display.init(datagram_if, {}); // Pattern 2: Use concrete type directly (zero-cost) -const SPI_DD = hal.drivers.SPI_Datagram_Device(spi_config); +const SPI_DD = hal.drivers.SPI_DatagramDevice(spi_config); var spi_dev = SPI_DD.init(spi1, cs_pin, false, timeout); -const Display = Sharp_Memory_LCD(.{ - .Datagram_Device = SPI_DD, // Concrete type +const Display = SharpMemory_LCD(.{ + .DatagramDevice = SPI_DD, // Concrete type }); var display = Display.init(spi_dev, {}); diff --git a/drivers/build.zig b/drivers/build.zig index 658b93e5b..66ebde85f 100644 --- a/drivers/build.zig +++ b/drivers/build.zig @@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const drivers_mod = b.addModule("drivers", .{ - .root_source_file = b.path("framework.zig"), + .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, .imports = &.{.{ diff --git a/drivers/base/Block_Memory.zig b/drivers/src/base/BlockMemory.zig similarity index 88% rename from drivers/base/Block_Memory.zig rename to drivers/src/base/BlockMemory.zig index b04b90599..3af3e2ceb 100644 --- a/drivers/base/Block_Memory.zig +++ b/drivers/src/base/BlockMemory.zig @@ -16,39 +16,39 @@ pub const VTable = struct { sector_size_fn: ?*const fn (*anyopaque, sector: u32) BaseError!u32, }; -pub const Block_Memory = @This(); +pub const BlockMemory = @This(); ptr: *anyopaque, vtable: VTable, -pub fn enable_write(mem: Block_Memory) BaseError!void { +pub fn enable_write(mem: BlockMemory) BaseError!void { if (mem.vtable.enable_write_fn) |enable_write_fn| { return try enable_write_fn(mem.ptr); } } -pub fn disable_write(mem: Block_Memory) BaseError!void { +pub fn disable_write(mem: BlockMemory) BaseError!void { if (mem.vtable.disable_write_fn) |disable_write_fn| { return try disable_write_fn(mem.ptr); } } -pub fn erase_sector(mem: Block_Memory, sector: u32) WriteError!void { +pub fn erase_sector(mem: BlockMemory, sector: u32) WriteError!void { const erase_fn = mem.vtable.erase_fn orelse return error.Unsupported; return erase_fn(mem.ptr, sector); } -pub fn write(mem: Block_Memory, sector: u32, data: []u8) WriteError!void { +pub fn write(mem: BlockMemory, sector: u32, data: []u8) WriteError!void { const sector_capacity = try mem.sector_size(sector); if (data.len > sector_capacity) return error.SectorOverrun; try mem.erase_sector(sector); const write_fn = mem.vtable.write_fn orelse return error.Unsupported; return write_fn(mem.ptr, sector, data); } -pub fn read(mem: Block_Memory, offset: u32, data: []u8) ReadError!usize { +pub fn read(mem: BlockMemory, offset: u32, data: []u8) ReadError!usize { const read_fn = mem.vtable.read_fn orelse return error.Unsupported; return read_fn(mem.ptr, offset, data); } -// pub fn findSector(flash: Block_Memory, offset: u32) BaseError!u8 { +// pub fn findSector(flash: BlockMemory, offset: u32) BaseError!u8 { // } -pub fn sector_size(mem: Block_Memory, sector: u32) BaseError!u32 { +pub fn sector_size(mem: BlockMemory, sector: u32) BaseError!u32 { const sector_size_fn = mem.vtable.sector_size_fn orelse return error.Unsupported; return sector_size_fn(mem.ptr, sector); } @@ -60,8 +60,8 @@ pub const TestDevice = struct { sector_capacity: u32 = 16384, num_sectors: u8 = 4, - pub fn block_memory(td: *TestDevice) Block_Memory { - return Block_Memory{ .vtable = vtable, .ptr = td }; + pub fn block_memory(td: *TestDevice) BlockMemory { + return BlockMemory{ .vtable = vtable, .ptr = td }; } pub fn enable_write(ctx: *anyopaque) BaseError!void { const td: *TestDevice = @ptrCast(@alignCast(ctx)); diff --git a/drivers/base/Clock_Device.zig b/drivers/src/base/ClockDevice.zig similarity index 70% rename from drivers/base/Clock_Device.zig rename to drivers/src/base/ClockDevice.zig index 480f7aa56..569b9f2c2 100644 --- a/drivers/base/Clock_Device.zig +++ b/drivers/src/base/ClockDevice.zig @@ -1,13 +1,13 @@ //! //! An abstract clock device //! -//! Clock_Devices can be used to track time & sleep +//! ClockDevices can be used to track time & sleep //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); -const Clock_Device = @This(); +const ClockDevice = @This(); /// Pointer to the object implementing the driver. /// @@ -21,7 +21,7 @@ vtable: *const VTable, /// Object created by make_timeout to perform to hold /// a duration. pub const Timeout = struct { - clock: Clock_Device, + clock: ClockDevice, time: mdf.time.Absolute, pub fn is_reached(self: @This()) bool { @@ -33,23 +33,23 @@ pub const Timeout = struct { } }; -pub fn is_reached(td: Clock_Device, time: mdf.time.Absolute) bool { +pub fn is_reached(td: ClockDevice, time: mdf.time.Absolute) bool { const now = td.get_time_since_boot(); return time.is_reached_by(now); } -pub fn make_timeout(td: Clock_Device, timeout: mdf.time.Duration) Timeout { +pub fn make_timeout(td: ClockDevice, timeout: mdf.time.Duration) Timeout { return .{ .clock = td, .time = td.get_time_since_boot().add_duration(timeout), }; } -pub fn sleep_ms(td: Clock_Device, time_ms: u32) void { +pub fn sleep_ms(td: ClockDevice, time_ms: u32) void { td.sleep_us(time_ms * 1000); } -pub fn sleep_us(td: Clock_Device, time_us: u64) void { +pub fn sleep_us(td: ClockDevice, time_us: u64) void { // If the device provides a custom sleep implementation, use it if (td.vtable.sleep) |sleep_fn| { sleep_fn(td.ptr, time_us); @@ -62,7 +62,7 @@ pub fn sleep_us(td: Clock_Device, time_us: u64) void { } /// VTable methods -pub fn get_time_since_boot(td: Clock_Device) mdf.time.Absolute { +pub fn get_time_since_boot(td: ClockDevice) mdf.time.Absolute { return td.vtable.get_time_since_boot(td.ptr); } @@ -71,56 +71,56 @@ pub const VTable = struct { sleep: ?*const fn (*anyopaque, u64) void = null, }; -pub const Test_Device = struct { +pub const TestDevice = struct { time: u64 = 0, total_sleep_time: u64 = 0, - pub fn init() Test_Device { - return Test_Device{}; + pub fn init() TestDevice { + return TestDevice{}; } - pub fn elapse_time(dev: *Test_Device, time_us: u64) void { + pub fn elapse_time(dev: *TestDevice, time_us: u64) void { dev.time += time_us; } - pub fn set_time(dev: *Test_Device, time_us: u64) void { + pub fn set_time(dev: *TestDevice, time_us: u64) void { dev.time = time_us; } - pub fn get_total_sleep_time(dev: *Test_Device) u64 { + pub fn get_total_sleep_time(dev: *TestDevice) u64 { return dev.total_sleep_time; } - pub fn reset_sleep_time(dev: *Test_Device) void { + pub fn reset_sleep_time(dev: *TestDevice) void { dev.total_sleep_time = 0; } - pub fn clock_device(dev: *Test_Device) Clock_Device { - return Clock_Device{ + pub fn clock_device(dev: *TestDevice) ClockDevice { + return ClockDevice{ .ptr = dev, .vtable = &vtable, }; } pub fn get_time_since_boot_fn(ctx: *anyopaque) mdf.time.Absolute { - const dev: *Test_Device = @ptrCast(@alignCast(ctx)); + const dev: *TestDevice = @ptrCast(@alignCast(ctx)); return @enumFromInt(dev.time); } pub fn sleep_fn(ctx: *anyopaque, time_us: u64) void { - const dev: *Test_Device = @ptrCast(@alignCast(ctx)); + const dev: *TestDevice = @ptrCast(@alignCast(ctx)); dev.total_sleep_time += time_us; dev.time += time_us; } const vtable = VTable{ - .get_time_since_boot = Test_Device.get_time_since_boot_fn, - .sleep = Test_Device.sleep_fn, + .get_time_since_boot = TestDevice.get_time_since_boot_fn, + .sleep = TestDevice.sleep_fn, }; }; -test Test_Device { - var ttd = Test_Device.init(); +test TestDevice { + var ttd = TestDevice.init(); const td = ttd.clock_device(); diff --git a/drivers/base/Datagram_Device.zig b/drivers/src/base/DatagramDevice.zig similarity index 85% rename from drivers/base/Datagram_Device.zig rename to drivers/src/base/DatagramDevice.zig index 209f7c915..a75724335 100644 --- a/drivers/base/Datagram_Device.zig +++ b/drivers/src/base/DatagramDevice.zig @@ -8,7 +8,7 @@ const std = @import("std"); -const Datagram_Device = @This(); +const DatagramDevice = @This(); /// Pointer to the object implementing the driver. /// @@ -27,33 +27,33 @@ pub const AnyError = ConnectError || WriteError || ReadError; /// Establishes a connection to the device (like activating a chip-select lane or similar). /// NOTE: Call `.disconnect()` when the usage of the device is done to release it. -pub fn connect(dd: Datagram_Device) ConnectError!void { +pub fn connect(dd: DatagramDevice) ConnectError!void { if (dd.vtable.connect_fn) |connectFn| { return connectFn(dd.ptr); } } /// Releases a device from the connection. -pub fn disconnect(dd: Datagram_Device) void { +pub fn disconnect(dd: DatagramDevice) void { if (dd.vtable.disconnect_fn) |disconnectFn| { return disconnectFn(dd.ptr); } } /// Writes a single `datagram` to the device. -pub fn write(dd: Datagram_Device, datagram: []const u8) WriteError!void { +pub fn write(dd: DatagramDevice, datagram: []const u8) WriteError!void { return try dd.writev(&.{datagram}); } /// Writes multiple `datagrams` to the device. -pub fn writev(dd: Datagram_Device, datagrams: []const []const u8) WriteError!void { +pub fn writev(dd: DatagramDevice, datagrams: []const []const u8) WriteError!void { const writev_fn = dd.vtable.writev_fn orelse return error.Unsupported; return writev_fn(dd.ptr, datagrams); } /// Writes then reads a single `datagram` to the device. pub fn write_then_read( - dd: Datagram_Device, + dd: DatagramDevice, src: []const u8, dst: []u8, ) (WriteError || ReadError)!void { @@ -62,7 +62,7 @@ pub fn write_then_read( /// Writes a slice of datagrams to the device, then reads back into another slice of datagrams pub fn writev_then_readv( - dd: Datagram_Device, + dd: DatagramDevice, write_chunks: []const []const u8, read_chunks: []const []u8, ) (WriteError || ReadError)!void { @@ -75,7 +75,7 @@ pub fn writev_then_readv( /// /// If `error.BufferOverrun` is returned, the `datagram` will still be fully filled with the data /// that was received up till the overrun. The rest of the datagram will be discarded. -pub fn read(dd: Datagram_Device, datagram: []u8) ReadError!usize { +pub fn read(dd: DatagramDevice, datagram: []u8) ReadError!usize { return try dd.readv(&.{datagram}); } @@ -84,7 +84,7 @@ pub fn read(dd: Datagram_Device, datagram: []u8) ReadError!usize { /// /// If `error.BufferOverrun` is returned, the `datagrams` will still be fully filled with the data /// that was received up till the overrun. The rest of the datagram will be discarded. -pub fn readv(dd: Datagram_Device, datagrams: []const []u8) ReadError!usize { +pub fn readv(dd: DatagramDevice, datagrams: []const []u8) ReadError!usize { const readv_fn = dd.vtable.readv_fn orelse return error.Unsupported; return readv_fn(dd.ptr, datagrams); } @@ -102,7 +102,7 @@ pub const VTable = struct { }; /// A device implementation that can be used to write unit tests for datagram devices. -pub const Test_Device = struct { +pub const TestDevice = struct { arena: std.heap.ArenaAllocator, packets: std.array_list.Managed([]u8), @@ -115,16 +115,16 @@ pub const Test_Device = struct { connected: bool, - pub fn init_receiver_only() Test_Device { + pub fn init_receiver_only() TestDevice { return init(null, true); } - pub fn init_sender_only(input: []const []const u8) Test_Device { + pub fn init_sender_only(input: []const []const u8) TestDevice { return init(input, false); } - pub fn init(input: ?[]const []const u8, write_enabled: bool) Test_Device { - return Test_Device{ + pub fn init(input: ?[]const []const u8, write_enabled: bool) TestDevice { + return TestDevice{ .arena = std.heap.ArenaAllocator.init(std.testing.allocator), .packets = std.array_list.Managed([]u8).init(std.testing.allocator), @@ -137,13 +137,13 @@ pub const Test_Device = struct { }; } - pub fn deinit(td: *Test_Device) void { + pub fn deinit(td: *TestDevice) void { td.arena.deinit(); td.packets.deinit(); td.* = undefined; } - pub fn expect_sent(td: Test_Device, expected_datagrams: []const []const u8) !void { + pub fn expect_sent(td: TestDevice, expected_datagrams: []const []const u8) !void { const actual_datagrams = td.packets.items; try std.testing.expectEqual(expected_datagrams.len, actual_datagrams.len); @@ -152,22 +152,22 @@ pub const Test_Device = struct { } } - pub fn datagram_device(td: *Test_Device) Datagram_Device { - return Datagram_Device{ + pub fn datagram_device(td: *TestDevice) DatagramDevice { + return DatagramDevice{ .ptr = td, .vtable = &vtable, }; } fn connect(ctx: *anyopaque) ConnectError!void { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (td.connected) return error.DeviceBusy; td.connected = true; } fn disconnect(ctx: *anyopaque) void { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (!td.connected) { std.log.err("disconnect when test device was not connected!", .{}); } @@ -175,7 +175,7 @@ pub const Test_Device = struct { } fn writev(ctx: *anyopaque, datagrams: []const []const u8) WriteError!void { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (!td.connected) { return error.NotConnected; @@ -209,7 +209,7 @@ pub const Test_Device = struct { } fn readv(ctx: *anyopaque, datagrams: []const []u8) ReadError!usize { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (!td.connected) { return error.NotConnected; @@ -253,21 +253,21 @@ pub const Test_Device = struct { } fn writev_then_readv(ctx: *anyopaque, write_chunks: []const []const u8, read_chunks: []const []u8) (WriteError || ReadError)!void { - try Test_Device.writev(ctx, write_chunks); - _ = try Test_Device.readv(ctx, read_chunks); + try TestDevice.writev(ctx, write_chunks); + _ = try TestDevice.readv(ctx, read_chunks); } const vtable = VTable{ - .connect_fn = Test_Device.connect, - .disconnect_fn = Test_Device.disconnect, - .writev_fn = Test_Device.writev, - .readv_fn = Test_Device.readv, - .writev_then_readv_fn = Test_Device.writev_then_readv, + .connect_fn = TestDevice.connect, + .disconnect_fn = TestDevice.disconnect, + .writev_fn = TestDevice.writev, + .readv_fn = TestDevice.readv, + .writev_then_readv_fn = TestDevice.writev_then_readv, }; }; -test Test_Device { - var td = Test_Device.init(&.{ +test TestDevice { + var td = TestDevice.init(&.{ "first datagram", "second datagram", "the very third datagram which overruns the buffer", diff --git a/drivers/base/DateTime.zig b/drivers/src/base/DateTime.zig similarity index 99% rename from drivers/base/DateTime.zig rename to drivers/src/base/DateTime.zig index e8aea784d..9ae7f0374 100644 --- a/drivers/base/DateTime.zig +++ b/drivers/src/base/DateTime.zig @@ -6,7 +6,7 @@ //! - No support for BCE dates. pub const std = @import("std"); -pub const time = @import("../framework.zig").time; +pub const time = @import("../root.zig").time; const DateTime = @This(); diff --git a/drivers/base/Digital_IO.zig b/drivers/src/base/Digital_IO.zig similarity index 85% rename from drivers/base/Digital_IO.zig rename to drivers/src/base/Digital_IO.zig index 0f4193622..3c2af379c 100644 --- a/drivers/base/Digital_IO.zig +++ b/drivers/src/base/Digital_IO.zig @@ -66,18 +66,18 @@ pub const VTable = struct { read_fn: *const fn (*anyopaque) ReadError!State, }; -pub const Test_Device = struct { +pub const TestDevice = struct { state: State, dir: Direction, - pub fn init(initial_dir: Direction, initial_state: State) Test_Device { - return Test_Device{ + pub fn init(initial_dir: Direction, initial_state: State) TestDevice { + return TestDevice{ .dir = initial_dir, .state = initial_state, }; } - pub fn digital_io(dev: *Test_Device) Digital_IO { + pub fn digital_io(dev: *TestDevice) Digital_IO { return Digital_IO{ .ptr = dev, .vtable = &vtable, @@ -85,38 +85,38 @@ pub const Test_Device = struct { } fn set_direction(ctx: *anyopaque, dir: Direction) SetDirError!void { - const dev: *Test_Device = @ptrCast(@alignCast(ctx)); + const dev: *TestDevice = @ptrCast(@alignCast(ctx)); dev.dir = dir; } fn set_bias(ctx: *anyopaque, bias: ?State) SetBiasError!void { - const dev: *Test_Device = @ptrCast(@alignCast(ctx)); + const dev: *TestDevice = @ptrCast(@alignCast(ctx)); _ = dev; _ = bias; } fn write(ctx: *anyopaque, state: State) WriteError!void { - const dev: *Test_Device = @ptrCast(@alignCast(ctx)); + const dev: *TestDevice = @ptrCast(@alignCast(ctx)); if (dev.dir != .output) return error.Unsupported; dev.state = state; } fn read(ctx: *anyopaque) ReadError!State { - const dev: *Test_Device = @ptrCast(@alignCast(ctx)); + const dev: *TestDevice = @ptrCast(@alignCast(ctx)); return dev.state; } const vtable = VTable{ - .set_direction_fn = Test_Device.set_direction, - .set_bias_fn = Test_Device.set_bias, - .write_fn = Test_Device.write, - .read_fn = Test_Device.read, + .set_direction_fn = TestDevice.set_direction, + .set_bias_fn = TestDevice.set_bias, + .write_fn = TestDevice.write, + .read_fn = TestDevice.read, }; }; -test Test_Device { - var td = Test_Device.init(.input, .high); +test TestDevice { + var td = TestDevice.init(.input, .high); const io = td.digital_io(); diff --git a/drivers/base/I2C_Device.zig b/drivers/src/base/I2C_Device.zig similarity index 93% rename from drivers/base/I2C_Device.zig rename to drivers/src/base/I2C_Device.zig index 2a26f1d29..ddaf60434 100644 --- a/drivers/base/I2C_Device.zig +++ b/drivers/src/base/I2C_Device.zig @@ -129,7 +129,7 @@ pub const VTable = struct { }; /// A device implementation that can be used to write unit tests for datagram devices. -pub const Test_Device = struct { +pub const TestDevice = struct { arena: std.heap.ArenaAllocator, packets: std.array_list.Managed([]u8), @@ -141,16 +141,16 @@ pub const Test_Device = struct { addr: Address, write_enabled: bool, - pub fn init_receiver_only() Test_Device { + pub fn init_receiver_only() TestDevice { return init(null, true); } - pub fn init_sender_only(input: []const []const u8) Test_Device { + pub fn init_sender_only(input: []const []const u8) TestDevice { return init(input, false); } - pub fn init(input: ?[]const []const u8, write_enabled: bool) Test_Device { - return Test_Device{ + pub fn init(input: ?[]const []const u8, write_enabled: bool) TestDevice { + return TestDevice{ .arena = std.heap.ArenaAllocator.init(std.testing.allocator), .packets = std.array_list.Managed([]u8).init(std.testing.allocator), @@ -163,13 +163,13 @@ pub const Test_Device = struct { }; } - pub fn deinit(td: *Test_Device) void { + pub fn deinit(td: *TestDevice) void { td.arena.deinit(); td.packets.deinit(); td.* = undefined; } - pub fn expect_sent(td: Test_Device, expected_datagrams: []const []const u8) !void { + pub fn expect_sent(td: TestDevice, expected_datagrams: []const []const u8) !void { const actual_datagrams = td.packets.items; try std.testing.expectEqual(expected_datagrams.len, actual_datagrams.len); @@ -178,7 +178,7 @@ pub const Test_Device = struct { } } - pub fn i2c_device(td: *Test_Device) I2C_Device { + pub fn i2c_device(td: *TestDevice) I2C_Device { return I2C_Device{ .ptr = td, .vtable = &vtable, @@ -186,7 +186,7 @@ pub const Test_Device = struct { } fn writev(ctx: *anyopaque, address: Address, datagrams: []const []const u8) InterfaceError!void { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); _ = address; if (!td.write_enabled) { @@ -217,7 +217,7 @@ pub const Test_Device = struct { } fn readv(ctx: *anyopaque, address: Address, datagrams: []const []u8) InterfaceError!usize { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); _ = address; const inputs = td.input_sequence orelse return error.Unsupported; @@ -258,14 +258,14 @@ pub const Test_Device = struct { } fn writev_then_readv(ctx: *anyopaque, address: Address, write_chunks: []const []const u8, read_chunks: []const []u8) InterfaceError!void { - try Test_Device.writev(ctx, address, write_chunks); - _ = try Test_Device.readv(ctx, address, read_chunks); + try TestDevice.writev(ctx, address, write_chunks); + _ = try TestDevice.readv(ctx, address, read_chunks); } const vtable = I2C_Device.VTable{ - .writev_fn = Test_Device.writev, - .readv_fn = Test_Device.readv, - .writev_then_readv_fn = Test_Device.writev_then_readv, + .writev_fn = TestDevice.writev, + .readv_fn = TestDevice.readv, + .writev_then_readv_fn = TestDevice.writev_then_readv, }; }; @@ -314,8 +314,8 @@ test "Address.check_reserved returns correct error types" { } } -test Test_Device { - var td = Test_Device.init(&.{ +test TestDevice { + var td = TestDevice.init(&.{ "first datagram", "second datagram", "the very third datagram which overruns the buffer", diff --git a/drivers/base/Stream_Device.zig b/drivers/src/base/StreamDevice.zig similarity index 81% rename from drivers/base/Stream_Device.zig rename to drivers/src/base/StreamDevice.zig index a54df6f82..40ea66a32 100644 --- a/drivers/base/Stream_Device.zig +++ b/drivers/src/base/StreamDevice.zig @@ -7,7 +7,7 @@ const std = @import("std"); -const Stream_Device = @This(); +const StreamDevice = @This(); /// Pointer to the object implementing the driver. /// @@ -26,44 +26,45 @@ pub const ReadError = BaseError || error{ Unsupported, NotConnected }; /// Establishes a connection to the device (like activating a chip-select lane or similar). /// NOTE: Call `.disconnect()` when the usage of the device is done to release it. -pub fn connect(sd: Stream_Device) ConnectError!void { +pub fn connect(sd: StreamDevice) ConnectError!void { const connect_fn = sd.vtable.connect_fn orelse return; return connect_fn(sd.ptr); } /// Releases a device from the connection. -pub fn disconnect(sd: Stream_Device) void { +pub fn disconnect(sd: StreamDevice) void { const disconnect_fn = sd.vtable.disconnect_fn orelse return; return disconnect_fn(sd.ptr); } /// Writes some `bytes` to the device and returns the number of bytes written. -pub fn write(sd: Stream_Device, bytes: []const u8) WriteError!usize { +pub fn write(sd: StreamDevice, bytes: []const u8) WriteError!usize { return sd.writev(&.{bytes}); } /// Writes some `bytes` to the device and returns the number of bytes written. -pub fn writev(sd: Stream_Device, bytes_vec: []const []const u8) WriteError!usize { +pub fn writev(sd: StreamDevice, bytes_vec: []const []const u8) WriteError!usize { const writev_fn = sd.vtable.writev_fn orelse return error.Unsupported; return writev_fn(sd.ptr, bytes_vec); } /// Reads some `bytes` to the device and returns the number of bytes read. -pub fn read(sd: Stream_Device, bytes: []u8) ReadError!usize { - return sd.readv(&.{bytes}); +pub fn read(sd: StreamDevice, bytes: []u8) ReadError!usize { + var vec: [1][]u8 = .{bytes}; + return sd.readv(&vec); } /// Reads some `bytes` to the device and returns the number of bytes read. -pub fn readv(sd: Stream_Device, bytes_vec: []const []u8) ReadError!usize { +pub fn readv(sd: StreamDevice, bytes_vec: [][]u8) ReadError!usize { const readv_fn = sd.vtable.readv_fn orelse return error.Unsupported; return readv_fn(sd.ptr, bytes_vec); } -pub fn writer(self: Stream_Device, buf: []u8) Writer { +pub fn writer(self: StreamDevice, buf: []u8) Writer { return .init(self, buf); } -pub fn reader(self: Stream_Device, buf: []u8) Reader { +pub fn reader(self: StreamDevice, buf: []u8) Reader { return .init(self, buf); } @@ -71,7 +72,7 @@ pub const VTable = struct { connect_fn: ?*const fn (*anyopaque) ConnectError!void, disconnect_fn: ?*const fn (*anyopaque) void, writev_fn: ?*const fn (*anyopaque, datagram: []const []const u8) WriteError!usize, - readv_fn: ?*const fn (*anyopaque, datagram: []const []u8) ReadError!usize, + readv_fn: ?*const fn (*anyopaque, datagram: [][]u8) ReadError!usize, }; /// microzig already has this function in SliceVector, but no other base driver include microzig as a dependency @@ -85,7 +86,7 @@ fn byte_sum(data: []const []const u8) usize { } pub const Writer = struct { - dev: Stream_Device, + dev: StreamDevice, interface: std.Io.Writer, err: ?WriteError = null, @@ -124,7 +125,7 @@ pub const Writer = struct { return ret; } - pub fn init(dev: Stream_Device, buf: []u8) Writer { + pub fn init(dev: StreamDevice, buf: []u8) Writer { return Writer{ .dev = dev, .interface = .{ @@ -138,7 +139,7 @@ pub const Writer = struct { }; pub const Reader = struct { - dev: Stream_Device, + dev: StreamDevice, interface: std.Io.Reader, err: ?ReadError = null, @@ -158,7 +159,7 @@ pub const Reader = struct { return n; } - pub fn init(dev: Stream_Device, buf: []u8) Reader { + pub fn init(dev: StreamDevice, buf: []u8) Reader { return Reader{ .dev = dev, .interface = .{ @@ -174,23 +175,19 @@ pub const Reader = struct { }; /// A device implementation that can be used to write unit tests for datagram devices. -pub const Test_Device = struct { - input: ?std.io.FixedBufferStream([]const u8), +pub const TestDevice = struct { + input: ?std.Io.Reader, output: ?std.array_list.Managed(u8), connected: bool, // Public API - pub fn init(input: ?[]const u8, write_enabled: bool) Test_Device { - return Test_Device{ + pub fn init(input: ?[]const u8, write_enabled: bool) TestDevice { + return TestDevice{ .connected = false, - .input = if (input) |bytes| - std.io.FixedBufferStream([]const u8){ .buffer = bytes, .pos = 0 } - else - null, - + .input = if (input) |bytes| .fixed(bytes) else null, .output = if (write_enabled) std.array_list.Managed(u8).init(std.testing.allocator) else @@ -198,15 +195,15 @@ pub const Test_Device = struct { }; } - pub fn deinit(td: *Test_Device) void { + pub fn deinit(td: *TestDevice) void { if (td.output) |*list| { list.deinit(); } td.* = undefined; } - pub fn stream_device(td: *Test_Device) Stream_Device { - return Stream_Device{ + pub fn stream_device(td: *TestDevice) StreamDevice { + return StreamDevice{ .ptr = td, .vtable = &vtable, }; @@ -215,15 +212,15 @@ pub const Test_Device = struct { // Testing interface: /// Checks if all of the provided input was consumed. - pub fn expect_all_input_consumed(td: Test_Device) !void { + pub fn expect_all_input_consumed(td: TestDevice) !void { // No input is totally fine and counts as "all input consumed" const input = td.input orelse return; - try std.testing.expectEqualSlices(u8, "", input.buffer[input.pos..]); + try std.testing.expectEqualSlices(u8, "", input.buffer[input.seek..]); } /// Expects that all sent data is `expected`. - pub fn expect_sent(td: Test_Device, expected: []const u8) !void { + pub fn expect_sent(td: TestDevice, expected: []const u8) !void { if (td.output) |output| { try std.testing.expectEqualSlices(u8, expected, output.items); } @@ -232,21 +229,21 @@ pub const Test_Device = struct { // Interface implementation const vtable = VTable{ - .connect_fn = Test_Device.connect, - .disconnect_fn = Test_Device.disconnect, - .writev_fn = Test_Device.writev, - .readv_fn = Test_Device.readv, + .connect_fn = TestDevice.connect, + .disconnect_fn = TestDevice.disconnect, + .writev_fn = TestDevice.writev, + .readv_fn = TestDevice.readv, }; fn connect(ctx: *anyopaque) ConnectError!void { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (td.connected) return error.DeviceBusy; td.connected = true; } fn disconnect(ctx: *anyopaque) void { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (!td.connected) { std.log.err("disconnect when test device was not connected!", .{}); } @@ -254,7 +251,7 @@ pub const Test_Device = struct { } fn writev(ctx: *anyopaque, bytes_vec: []const []const u8) WriteError!usize { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (!td.connected) { return error.NotConnected; } @@ -269,28 +266,18 @@ pub const Test_Device = struct { return total_len; } - fn readv(ctx: *anyopaque, bytes_vec: []const []u8) ReadError!usize { - const td: *Test_Device = @ptrCast(@alignCast(ctx)); + fn readv(ctx: *anyopaque, bytes_vec: [][]u8) ReadError!usize { + const td: *TestDevice = @ptrCast(@alignCast(ctx)); if (!td.connected) { return error.NotConnected; } - const data_reader = if (td.input) |*stream| stream.reader() else return error.Unsupported; - - var total_length: usize = 0; - - for (bytes_vec) |bytes| { - const len = data_reader.read(bytes) catch comptime unreachable; - total_length += len; - if (len < bytes.len) - return total_length; - } - - return total_length; + const data_reader = if (td.input) |*r| r else return error.Unsupported; + return data_reader.readVec(bytes_vec) catch error.IoError; } }; -test Test_Device { +test TestDevice { const input_text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque pen" ++ "atibus et magnis dis parturient montes, nascetur ridiculus mus. " ++ @@ -302,7 +289,7 @@ test Test_Device { "eifend tellus. Aenean leo ligula, porttitor eu, consequat vitae," ++ " eleifend ac, enim."; - var td = Test_Device.init(input_text, true); + var td = TestDevice.init(input_text, true); defer td.deinit(); var buffer: [128]u8 = undefined; diff --git a/drivers/display/colors.zig b/drivers/src/display/colors.zig similarity index 100% rename from drivers/display/colors.zig rename to drivers/src/display/colors.zig diff --git a/drivers/display/common.zig b/drivers/src/display/common.zig similarity index 100% rename from drivers/display/common.zig rename to drivers/src/display/common.zig diff --git a/drivers/display/hd44780.zig b/drivers/src/display/hd44780.zig similarity index 97% rename from drivers/display/hd44780.zig rename to drivers/src/display/hd44780.zig index af0f0a929..130fc34d1 100644 --- a/drivers/display/hd44780.zig +++ b/drivers/src/display/hd44780.zig @@ -1,5 +1,5 @@ -const mdf = @import("../framework.zig"); -const DigitalIO = mdf.base.Digital_IO; +const mdf = @import("../root.zig"); +const Digital_IO = mdf.base.Digital_IO; pub const delayus_callback = fn (delay: u32) void; pub const LCD_Commands = enum(u8) { @@ -54,12 +54,12 @@ pub const DeviceConfig = struct { }; pub const HD44780_Config = struct { - high_pins: type = DigitalIO, - lower_pins: type = DigitalIO, - RS: type = DigitalIO, - EN1: type = DigitalIO, - EN2: type = DigitalIO, - BK: type = DigitalIO, + high_pins: type = Digital_IO, + lower_pins: type = Digital_IO, + RS: type = Digital_IO, + EN1: type = Digital_IO, + EN2: type = Digital_IO, + BK: type = Digital_IO, }; pub const EnableSet = enum { diff --git a/drivers/display/sh1106.zig b/drivers/src/display/sh1106.zig similarity index 95% rename from drivers/display/sh1106.zig rename to drivers/src/display/sh1106.zig index 10353b244..34307b5c5 100644 --- a/drivers/display/sh1106.zig +++ b/drivers/src/display/sh1106.zig @@ -9,12 +9,12 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const common = @import("common.zig"); const I2C_ControlByte = common.I2C_ControlByte; -pub const Driver_Mode = enum { +pub const DriverMode = enum { /// The driver operates in I²C mode, which requires a 8 bit datagram device. /// Each datagram is prefixed with the corresponding command/data byte. i2c, @@ -33,10 +33,10 @@ pub const Driver_Mode = enum { pub const Options = struct { /// Defines the operation of the SH1106 driver. - mode: Driver_Mode, + mode: DriverMode, /// Which datagram device interface should be used. - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, /// Which digital i/o interface should be used. Digital_IO: type = mdf.base.Digital_IO, @@ -60,7 +60,7 @@ pub fn SH1106(comptime options: Options) type { return struct { const Self = @This(); - const Datagram_Device = options.Datagram_Device; + const DatagramDevice = options.DatagramDevice; const Digital_IO = switch (options.mode) { // 4-wire SPI mode uses a dedicated command/data control pin: .spi_4wire, .dynamic => options.Digital_IO, @@ -70,23 +70,23 @@ pub fn SH1106(comptime options: Options) type { .i2c, .spi_3wire => void, }; - pub const Driver_Init_Mode = union(enum) { + pub const DriverInitMode = union(enum) { i2c: struct { - device: Datagram_Device, + device: DatagramDevice, }, spi_3wire: noreturn, spi_4wire: struct { - device: Datagram_Device, + device: DatagramDevice, dc_pin: Digital_IO, }, }; const Mode = switch (options.mode) { - .dynamic => Driver_Mode, + .dynamic => DriverMode, else => void, }; - dd: Datagram_Device, + dd: DatagramDevice, mode: Mode, dc_pin: Digital_IO, @@ -99,7 +99,7 @@ pub fn SH1106(comptime options: Options) type { /// Creates an instance with only a datagram device. /// `init` will be an alias to this if the init requires no D/C pin. - fn init_without_io(dev: Datagram_Device) !Self { + fn init_without_io(dev: DatagramDevice) !Self { var self = Self{ .dd = dev, .dc_pin = {}, @@ -111,7 +111,7 @@ pub fn SH1106(comptime options: Options) type { /// Creates an instance with a datagram device and the D/C pin. /// `init` will be an alias to this if the init requires a D/C pin. - fn init_with_io(dev: Datagram_Device, data_cmd_pin: Digital_IO) !Self { + fn init_with_io(dev: DatagramDevice, data_cmd_pin: Digital_IO) !Self { var self = Self{ .dd = dev, .dc_pin = data_cmd_pin, @@ -125,7 +125,7 @@ pub fn SH1106(comptime options: Options) type { return self; } - fn init_with_mode(mode: Driver_Init_Mode) !Self { + fn init_with_mode(mode: DriverInitMode) !Self { var self = Self{ .dd = switch (mode) { .i2c => |opt| opt.device, diff --git a/drivers/display/sharp_memory_lcd.zig b/drivers/src/display/sharp_memory_lcd.zig similarity index 96% rename from drivers/display/sharp_memory_lcd.zig rename to drivers/src/display/sharp_memory_lcd.zig index dca4e15f1..ba259e3ad 100644 --- a/drivers/display/sharp_memory_lcd.zig +++ b/drivers/src/display/sharp_memory_lcd.zig @@ -32,7 +32,7 @@ //! ``` const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); /// VCOM (Voltage Compensation) mode for Sharp Memory LCDs /// WARNING: This can be required for actual sharp LCD panels to avoid damaging the LCD. @@ -51,8 +51,8 @@ pub const Config = struct { height: comptime_int, /// VCOM mode (none for nice!view, software for older displays) vcom_mode: VCOM_Mode = .none, - /// Datagram device type (typically SPI_Datagram_Device) - Datagram_Device: type = mdf.base.Datagram_Device, + /// Datagram device type (typically SPI_DatagramDevice) + DatagramDevice: type = mdf.base.DatagramDevice, /// Optional digital I/O type for DISP enable pin Digital_IO: ?type = null, }; @@ -91,7 +91,7 @@ pub fn SharpMemory_LCD(comptime config: Config) type { const Self = @This(); /// Datagram device for SPI communication - dd: config.Datagram_Device, + dd: config.DatagramDevice, /// Optional display enable pin disp_pin: if (config.Digital_IO) |T| T else void, /// VCOM state (compile-time conditional, zero cost when disabled) @@ -101,11 +101,11 @@ pub fn SharpMemory_LCD(comptime config: Config) type { /// Total display size in bytes pub const display_size_bytes = bytes_per_line * config.height; /// Framebuffer type for this display - pub const Framebuffer = Framebuffer_Type(config.width, config.height); + pub const Framebuffer = FramebufferGeneric(config.width, config.height); /// Initialize the Sharp Memory LCD driver pub fn init( - dd: config.Datagram_Device, + dd: config.DatagramDevice, disp_pin: if (config.Digital_IO) |T| T else void, ) !Self { var self = Self{ @@ -241,7 +241,7 @@ pub fn SharpMemory_LCD(comptime config: Config) type { } /// Generate a framebuffer type for the specified dimensions -fn Framebuffer_Type(width: comptime_int, height: comptime_int) type { +fn FramebufferGeneric(width: comptime_int, height: comptime_int) type { return struct { const Self = @This(); @@ -356,7 +356,7 @@ fn Framebuffer_Type(width: comptime_int, height: comptime_int) type { // Tests for framebuffer pixel ordering test "framebuffer LSB-first pixel ordering" { - const Fb = Framebuffer_Type(8, 1); + const Fb = FramebufferGeneric(8, 1); var fb = Fb.init(.white); // Set pixel 0 (leftmost bit) - should set bit 0 @@ -377,7 +377,7 @@ test "framebuffer LSB-first pixel ordering" { } test "framebuffer line-major layout" { - const Fb = Framebuffer_Type(16, 2); + const Fb = FramebufferGeneric(16, 2); var fb = Fb.init(.white); // Set pixel at (0, 0) - first byte @@ -391,7 +391,7 @@ test "framebuffer line-major layout" { } test "framebuffer get_line" { - const Fb = Framebuffer_Type(16, 2); + const Fb = FramebufferGeneric(16, 2); var fb = Fb.init(.white); // Fill first line diff --git a/drivers/display/ssd1306.zig b/drivers/src/display/ssd1306.zig similarity index 97% rename from drivers/display/ssd1306.zig rename to drivers/src/display/ssd1306.zig index a0707af9a..f574bac23 100644 --- a/drivers/display/ssd1306.zig +++ b/drivers/src/display/ssd1306.zig @@ -9,7 +9,7 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const common = @import("common.zig"); const I2C_ControlByte = common.I2C_ControlByte; @@ -19,7 +19,7 @@ pub const SSD1306_I2C = SSD1306_Generic(.{ .mode = .i2c, }); -pub const Driver_Mode = enum { +pub const DriverMode = enum { /// The driver operates in I²C mode, which requires a 8 bit datagram device. /// Each datagram is prefixed with the corresponding command/data byte. i2c, @@ -38,23 +38,23 @@ pub const Driver_Mode = enum { pub const SSD1306_Options = struct { /// Defines the operation of the SSD1306 driver. - mode: Driver_Mode, + mode: DriverMode, /// Which datagram device interface should be used. - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, /// Which digital i/o interface should be used. Digital_IO: type = mdf.base.Digital_IO, }; -pub fn init(comptime mode: Driver_Mode, device: anytype, digital_io: anytype) !SSD1306_Generic(.{ +pub fn init(comptime mode: DriverMode, device: anytype, digital_io: anytype) !SSD1306_Generic(.{ .mode = mode, - .Datagram_Device = @TypeOf(device), + .DatagramDevice = @TypeOf(device), .Digital_IO = @TypeOf(digital_io), }) { const Type = SSD1306_Generic(.{ .mode = mode, - .Datagram_Device = @TypeOf(device), + .DatagramDevice = @TypeOf(device), .Digital_IO = @TypeOf(digital_io), }); @@ -76,7 +76,7 @@ pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { return struct { const Self = @This(); - const Datagram_Device = options.Datagram_Device; + const DatagramDevice = options.DatagramDevice; const Digital_IO = switch (options.mode) { // 4-wire SPI mode uses a dedicated command/data control pin: .spi_4wire, .dynamic => options.Digital_IO, @@ -86,23 +86,23 @@ pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { .i2c, .spi_3wire => void, }; - pub const Driver_Init_Mode = union(enum) { + pub const DriverInitMode = union(enum) { i2c: struct { - device: Datagram_Device, + device: DatagramDevice, }, spi_3wire: noreturn, spi_4wire: struct { - device: Datagram_Device, + device: DatagramDevice, dc_pin: Digital_IO, }, }; const Mode = switch (options.mode) { - .dynamic => Driver_Mode, + .dynamic => DriverMode, else => void, }; - dd: Datagram_Device, + dd: DatagramDevice, mode: Mode, dc_pin: Digital_IO, @@ -115,7 +115,7 @@ pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { /// Creates an instance with only a datagram device. /// `init` will be an alias to this if the init requires no D/C pin. - fn init_without_io(dev: Datagram_Device) !Self { + fn init_without_io(dev: DatagramDevice) !Self { var self = Self{ .dd = dev, .dc_pin = {}, @@ -127,7 +127,7 @@ pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { /// Creates an instance with a datagram device and the D/C pin. /// `init` will be an alias to this if the init requires a D/C pin. - fn init_with_io(dev: Datagram_Device, data_cmd_pin: Digital_IO) !Self { + fn init_with_io(dev: DatagramDevice, data_cmd_pin: Digital_IO) !Self { var self = Self{ .dd = dev, .dc_pin = data_cmd_pin, @@ -142,7 +142,7 @@ pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { return self; } - fn init_with_mode(mode: Driver_Init_Mode) !Self { + fn init_with_mode(mode: DriverInitMode) !Self { var self = Self{ .dd = switch (mode) { .i2c => |opt| opt.device, @@ -443,7 +443,7 @@ pub fn SSD1306_Generic(comptime options: SSD1306_Options) type { // Tests - const TestDevice = mdf.base.Datagram_Device.Test_Device; + const TestDevice = mdf.base.DatagramDevice.TestDevice; // This is the command sequence created by SSD1306_I2C.init() // to set up the display. diff --git a/drivers/display/st77xx.zig b/drivers/src/display/st77xx.zig similarity index 96% rename from drivers/display/st77xx.zig rename to drivers/src/display/st77xx.zig index 47edde558..27d94dfc4 100644 --- a/drivers/display/st77xx.zig +++ b/drivers/src/display/st77xx.zig @@ -8,15 +8,15 @@ //! - https://www.waveshare.com/w/upload/a/ae/ST7789_Datasheet.pdf //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); -pub fn ST7735(display_cfg: Display_Config) type { +pub fn ST7735(display_cfg: DisplayConfig) type { return ST77xx_Generic(.{ .device = .st7735, }, display_cfg); } -pub fn ST7789(display_cfg: Display_Config) type { +pub fn ST7789(display_cfg: DisplayConfig) type { return ST77xx_Generic(.{ .device = .st7789, }, display_cfg); @@ -44,12 +44,12 @@ const Rotation = enum(u2) { deg270, }; -pub const Driver_Config = struct { +pub const DriverConfig = struct { /// Which SST77xx device does the driver target? device: Device, /// Which datagram device interface should be used. - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, /// Which digital i/o interface should be used. Digital_IO: type = mdf.base.Digital_IO, @@ -58,7 +58,7 @@ pub const Driver_Config = struct { Color: type = mdf.display.colors.RGB565_Generic(.big), }; -pub const Display_Config = struct { +pub const DisplayConfig = struct { const Self = @This(); /// Native panel resolution in pixels. resolution: Resolution, @@ -111,14 +111,14 @@ pub const Display_Config = struct { }; }; -pub fn ST77xx_Generic(driver_cfg: Driver_Config, display_cfg: Display_Config) type { +pub fn ST77xx_Generic(driver_cfg: DriverConfig, display_cfg: DisplayConfig) type { return struct { const Self = @This(); - const Datagram_Device = driver_cfg.Datagram_Device; + const DatagramDevice = driver_cfg.DatagramDevice; const Digital_IO = driver_cfg.Digital_IO; pub const Color = driver_cfg.Color; - dd: Datagram_Device, + dd: DatagramDevice, dev_rst: Digital_IO, dev_datcmd: Digital_IO, madctl: MemoryDataAccessControl, @@ -128,7 +128,7 @@ pub fn ST77xx_Generic(driver_cfg: Driver_Config, display_cfg: Display_Config) ty y_offset: u16 = display_cfg.y_offset, pub fn init( - channel: Datagram_Device, + channel: DatagramDevice, rst: Digital_IO, data_cmd: Digital_IO, delay_ms: *const fn (ms: u32) void, diff --git a/drivers/input/debounced-button.zig b/drivers/src/input/debounced_button.zig similarity index 96% rename from drivers/input/debounced-button.zig rename to drivers/src/input/debounced_button.zig index 93f7e51f5..ef8c932b5 100644 --- a/drivers/input/debounced-button.zig +++ b/drivers/src/input/debounced_button.zig @@ -3,9 +3,9 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); -pub const Debounced_Button_Options = struct { +pub const Options = struct { /// The active state for the button. Use `.high` for active-high, `.low` for active-low. active_state: mdf.base.Digital_IO.State, @@ -28,13 +28,13 @@ pub const Debounced_Button_Options = struct { /// Each poll, the filter integer is shifted by one bit and the new state is inserted. This /// way, a simple "was it pressed in the last N polls" function is implemented. /// -pub fn Debounced_Button(comptime options: Debounced_Button_Options) type { +pub fn DebouncedButton(comptime options: Options) type { return struct { const Button = @This(); - const Filter_Int = std.meta.Int(.unsigned, options.filter_depth orelse 16); + const FilterInt = std.meta.Int(.unsigned, options.filter_depth orelse 16); io: options.Digital_IO, - filter_buffer: Filter_Int, + filter_buffer: FilterInt, pub fn init(io: options.Digital_IO) !Button { try io.set_bias(options.active_state.invert()); @@ -87,13 +87,13 @@ pub const Event = enum { released, }; -test Debounced_Button { - const Button = Debounced_Button(.{ +test DebouncedButton { + const Button = DebouncedButton(.{ .active_state = .low, .filter_depth = 4, }); - var button_input = mdf.base.Digital_IO.Test_Device.init(.input, .high); + var button_input = mdf.base.Digital_IO.TestDevice.init(.input, .high); var button = try Button.init(button_input.digital_io()); diff --git a/drivers/input/keyboard-matrix.zig b/drivers/src/input/keyboard_matrix.zig similarity index 92% rename from drivers/input/keyboard-matrix.zig rename to drivers/src/input/keyboard_matrix.zig index d2edc1f9f..1814b189e 100644 --- a/drivers/input/keyboard-matrix.zig +++ b/drivers/src/input/keyboard_matrix.zig @@ -3,9 +3,9 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); -pub const Keyboard_Matrix_Options = struct { +pub const Options = struct { /// How many rows does the keyboard matrix have? rows: usize, @@ -19,7 +19,7 @@ pub const Keyboard_Matrix_Options = struct { /// Keyboard matrix implementation via GPIOs that scans columns and checks rows. /// /// Will use the columns as matrix drivers (outputs) and the rows as matrix readers (inputs). -pub fn Keyboard_Matrix(comptime options: Keyboard_Matrix_Options) type { +pub fn KeyboardMatrix(comptime options: Options) type { if (options.columns > 256 or options.rows > 256) @compileError("cannot encode more than 256 rows or columns!"); return struct { @@ -164,7 +164,7 @@ inline fn busyloop(comptime N: comptime_int) void { } } -test Keyboard_Matrix { +test KeyboardMatrix { const key_tl = Key.new(0, 0); const key_tr = Key.new(0, 1); const key_bl = Key.new(1, 0); @@ -172,16 +172,16 @@ test Keyboard_Matrix { // Those are "drivers", so we initialize them inverse // to what we'd expect them to be - var col_pins = [_]mdf.base.Digital_IO.Test_Device{ - mdf.base.Digital_IO.Test_Device.init(.input, .low), - mdf.base.Digital_IO.Test_Device.init(.input, .low), + var col_pins = [_]mdf.base.Digital_IO.TestDevice{ + mdf.base.Digital_IO.TestDevice.init(.input, .low), + mdf.base.Digital_IO.TestDevice.init(.input, .low), }; // Those are "inputs", so we have to check the // direction init, but not the state change: - var row_pins = [_]mdf.base.Digital_IO.Test_Device{ - mdf.base.Digital_IO.Test_Device.init(.output, .high), - mdf.base.Digital_IO.Test_Device.init(.output, .high), + var row_pins = [_]mdf.base.Digital_IO.TestDevice{ + mdf.base.Digital_IO.TestDevice.init(.output, .high), + mdf.base.Digital_IO.TestDevice.init(.output, .high), }; const row_drivers = [_]mdf.base.Digital_IO{ @@ -194,7 +194,7 @@ test Keyboard_Matrix { col_pins[1].digital_io(), }; - const Matrix = Keyboard_Matrix(.{ + const Matrix = KeyboardMatrix(.{ .rows = 2, .columns = 2, }); diff --git a/drivers/input/rotary-encoder.zig b/drivers/src/input/rotary_encoder.zig similarity index 91% rename from drivers/input/rotary-encoder.zig rename to drivers/src/input/rotary_encoder.zig index f2ba66220..291e00843 100644 --- a/drivers/input/rotary-encoder.zig +++ b/drivers/src/input/rotary_encoder.zig @@ -3,14 +3,14 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); -pub const Rotary_Encoder_Options = struct { +pub const Options = struct { /// Which digital i/o interface should be used. Digital_IO: type = mdf.base.Digital_IO, }; -pub fn Rotary_Encoder(comptime options: Rotary_Encoder_Options) type { +pub fn RotaryEncoder(comptime options: Options) type { return struct { const Encoder = @This(); @@ -72,11 +72,11 @@ pub const Event = enum(i2) { @"error" = -2, }; -test Rotary_Encoder { - var a = mdf.base.Digital_IO.Test_Device.init(.output, .high); - var b = mdf.base.Digital_IO.Test_Device.init(.output, .high); +test RotaryEncoder { + var a = mdf.base.Digital_IO.TestDevice.init(.output, .high); + var b = mdf.base.Digital_IO.TestDevice.init(.output, .high); - var encoder = try Rotary_Encoder(.{}).init( + var encoder = try RotaryEncoder(.{}).init( a.digital_io(), b.digital_io(), .high, diff --git a/drivers/io_expander/pca9685.zig b/drivers/src/io_expander/pca9685.zig similarity index 92% rename from drivers/io_expander/pca9685.zig rename to drivers/src/io_expander/pca9685.zig index 75ede6bbd..dff75f721 100644 --- a/drivers/io_expander/pca9685.zig +++ b/drivers/src/io_expander/pca9685.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const Digital_IO = mdf.base.Digital_IO; const default_oscillator_frequency = 25_000_000; @@ -23,13 +23,13 @@ pub const Register = enum(u8) { }; pub const PCA9685_Config = struct { - Datagram_Device: type = mdf.base.Datagram_Device, + DatagramDevice: type = mdf.base.DatagramDevice, oscillator_frequency: u32 = default_oscillator_frequency, }; -pub fn init(datagram_device: anytype, frequency: u32) !PCA9685(.{ .Datagram_Device = @TypeOf(datagram_device) }) { +pub fn init(datagram_device: anytype, frequency: u32) !PCA9685(.{ .DatagramDevice = @TypeOf(datagram_device) }) { const Type = PCA9685(.{ - .Datagram_Device = @TypeOf(datagram_device), + .DatagramDevice = @TypeOf(datagram_device), }); return Type.init(datagram_device, frequency); @@ -38,9 +38,9 @@ pub fn init(datagram_device: anytype, frequency: u32) !PCA9685(.{ .Datagram_Devi pub fn PCA9685(comptime config: PCA9685_Config) type { return struct { const Self = @This(); - dd: config.Datagram_Device, + dd: config.DatagramDevice, - fn init(datagram_device: config.Datagram_Device, frequency: u32) !Self { + fn init(datagram_device: config.DatagramDevice, frequency: u32) !Self { const self = Self{ .dd = datagram_device, }; diff --git a/drivers/io_expander/pcf8574.zig b/drivers/src/io_expander/pcf8574.zig similarity index 86% rename from drivers/io_expander/pcf8574.zig rename to drivers/src/io_expander/pcf8574.zig index b234d3cde..8e6fb9443 100644 --- a/drivers/io_expander/pcf8574.zig +++ b/drivers/src/io_expander/pcf8574.zig @@ -1,4 +1,4 @@ -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const Digital_IO = mdf.base.Digital_IO; const State = Digital_IO.State; const Vtable = Digital_IO.VTable; @@ -7,13 +7,13 @@ const SetBiasError = Digital_IO.SetBiasError; const SetDirError = Digital_IO.SetDirError; const WriteError = Digital_IO.WriteError; -const I2CAddress = mdf.base.I2C_Device.Address; +const I2C_Address = mdf.base.I2C_Device.Address; -pub const PCF8574_Config = struct { +pub const Config = struct { I2C_Device: type = mdf.base.I2C_Device, }; -pub fn PCF8574(comptime config: PCF8574_Config) type { +pub fn PCF8574(comptime config: Config) type { return struct { const Self = @This(); interface: config.I2C_Device, @@ -49,7 +49,7 @@ pub fn PCF8574(comptime config: PCF8574_Config) type { return if (read_value & mask != 0) State.high else State.low; } - pub fn init(datagram: config.I2C_Device, address: I2CAddress) Self { + pub fn init(datagram: config.I2C_Device, address: I2C_Address) Self { var obj = Self{ .interface = datagram, .address = address }; for (0..obj.pin_arr.len) |index| { obj.pin_arr[index] = @intCast(index); @@ -68,8 +68,8 @@ pub fn PCF8574(comptime config: PCF8574_Config) type { const pin_ref: *u8 = @ptrCast(@alignCast(ctx)); const index = pin_ref.*; const pin_base: *[8]u8 = @ptrFromInt(@intFromPtr(pin_ref) - index); //just 1 byte - var PCF_base: *Self = @alignCast(@fieldParentPtr("pin_arr", pin_base)); - const state = PCF_base.read(@intCast(index)) catch return ReadError.IoError; + var pcf_base: *Self = @alignCast(@fieldParentPtr("pin_arr", pin_base)); + const state = pcf_base.read(@intCast(index)) catch return ReadError.IoError; return state; } @@ -77,8 +77,8 @@ pub fn PCF8574(comptime config: PCF8574_Config) type { const pin_ref: *u8 = @ptrCast(@alignCast(ctx)); const index = pin_ref.*; const pin_base: *[8]u8 = @ptrFromInt(@intFromPtr(pin_ref) - index); //just 1 byte - var PCF_base: *Self = @alignCast(@fieldParentPtr("pin_arr", pin_base)); - PCF_base.put(@intCast(index), state) catch return WriteError.IoError; + var pcf_base: *Self = @alignCast(@fieldParentPtr("pin_arr", pin_base)); + pcf_base.put(@intCast(index), state) catch return WriteError.IoError; } fn set_bias_fn(_: *anyopaque, _: ?State) SetBiasError!void { diff --git a/drivers/led/ws2812.zig b/drivers/src/led/ws2812.zig similarity index 85% rename from drivers/led/ws2812.zig rename to drivers/src/led/ws2812.zig index 531849737..1ec267f59 100644 --- a/drivers/led/ws2812.zig +++ b/drivers/src/led/ws2812.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); // inspired by https://github.com/smart-leds-rs/ws2812-spi-rs/blob/68d98bf9c7f10bc852bace0f3fd5af2a1cef51a7/src/lib.rs @@ -7,8 +7,8 @@ const mdf = @import("../framework.zig"); /// bytes are written the output pin **must** be low. pub fn WS2812(options: struct { max_led_count: usize = 1, - Datagram_Device: type = mdf.base.Datagram_Device, - Clock_Device: type = mdf.base.Clock_Device, + DatagramDevice: type = mdf.base.DatagramDevice, + ClockDevice: type = mdf.base.Clock_Device, }) type { return struct { const Self = @This(); @@ -16,13 +16,13 @@ pub fn WS2812(options: struct { // we can fit 2 bits (out of 24 bits per color) into 1 byte const buffer_size = options.max_led_count * 24 / 2; - dev: options.Datagram_Device, - clock_dev: options.Clock_Device, - next_write_time: ?mdf.base.Clock_Device.Timeout = null, + dev: options.DatagramDevice, + clock_dev: options.ClockDevice, + next_write_time: ?mdf.base.ClockDevice.Timeout = null, buffer: [buffer_size]u8 = undefined, /// Initializes the driver. - pub fn init(dev: options.Datagram_Device, clock_dev: options.Clock_Device) Self { + pub fn init(dev: options.DatagramDevice, clock_dev: options.ClockDevice) Self { return .{ .dev = dev, .clock_dev = clock_dev, diff --git a/drivers/framework.zig b/drivers/src/root.zig similarity index 86% rename from drivers/framework.zig rename to drivers/src/root.zig index 7fc00c3e9..baa8a7eac 100644 --- a/drivers/framework.zig +++ b/drivers/src/root.zig @@ -23,15 +23,15 @@ pub const display = struct { }; pub const input = struct { - pub const rotary_encoder = @import("input/rotary-encoder.zig"); - pub const keyboard_matrix = @import("input/keyboard-matrix.zig"); - pub const debounced_button = @import("input/debounced-button.zig"); + pub const rotary_encoder = @import("input/rotary_encoder.zig"); + pub const keyboard_matrix = @import("input/keyboard_matrix.zig"); + pub const debounced_button = @import("input/debounced_button.zig"); // Export generic drivers: pub const Key = keyboard_matrix.Key; - pub const Keyboard_Matrix = keyboard_matrix.Keyboard_Matrix; - pub const Debounced_Button = debounced_button.Debounced_Button; - pub const Rotary_Encoder = rotary_encoder.Rotary_Encoder; + pub const KeyboardMatrix = keyboard_matrix.KeyboardMatrix; + pub const DebouncedButton = debounced_button.DebouncedButton; + pub const RotaryEncoder = rotary_encoder.RotaryEncoder; pub const touch = struct { // const xpt2046 = @import("input/touch/xpt2046.zig"); @@ -48,9 +48,9 @@ pub const sensor = struct { pub const AS5600 = @import("sensor/AS5600.zig").AS5600; pub const HTS221 = @import("sensor/HTS221.zig").HTS221; pub const DS18B20 = @import("sensor/DS18B20.zig").DS18B20; - pub const ICM_20948 = @import("sensor/ICM-20948.zig").ICM_20948; + pub const ICM_20948 = @import("sensor/ICM_20948.zig").ICM_20948; pub const MLX90640 = @import("sensor/MLX90640.zig").MLX90640; - pub const MPU_6050 = @import("sensor/MPU-6050.zig").MPU_6050; + pub const MPU_6050 = @import("sensor/MPU_6050.zig").MPU_6050; pub const TLV493D = @import("sensor/TLV493D.zig").TLV493D; pub const TMP117 = @import("sensor/TMP117.zig").TMP117; pub const AHT30 = @import("sensor/AHT30.zig").AHT30; @@ -63,7 +63,7 @@ pub const stepper = struct { pub const ULN2003 = @import("stepper/ULN2003.zig").ULN2003; }; -pub const IO_expander = struct { +pub const io_expander = struct { pub const pcf8574 = @import("io_expander/pcf8574.zig"); pub const PCF8574 = pcf8574.PCF8574; @@ -75,9 +75,9 @@ pub const wireless = struct { pub const cyw43 = @import("wireless/cyw43/cyw43.zig"); pub const cyw43_bus = @import("wireless/cyw43/bus.zig"); pub const cyw43_runner = @import("wireless/cyw43/runner.zig"); - pub const Cyw43_Spi = cyw43_bus.Cyw43_Spi; - pub const Cyw43_Bus = cyw43_bus.Cyw43_Bus; - pub const Cyw43_Runner = cyw43_runner.Cyw43_Runner; + pub const CYW43_SPI = cyw43_bus.CYW43_SPI; + pub const CYW43_Bus = cyw43_bus.CYW43_Bus; + pub const CYW43_Runner = cyw43_runner.CYW43_Runner; // pub const sx1278 = @import("wireless/sx1278.zig"); pub const Cyw43439 = @import("wireless/cyw43439.zig"); @@ -209,11 +209,11 @@ pub const time = struct { pub const DateTime = @import("base/DateTime.zig"); pub const base = struct { - pub const Datagram_Device = @import("base/Datagram_Device.zig"); - pub const Stream_Device = @import("base/Stream_Device.zig"); + pub const DatagramDevice = @import("base/DatagramDevice.zig"); + pub const StreamDevice = @import("base/StreamDevice.zig"); pub const Digital_IO = @import("base/Digital_IO.zig"); - pub const Clock_Device = @import("base/Clock_Device.zig"); - pub const Block_Memory = @import("base/Block_Memory.zig"); + pub const ClockDevice = @import("base/ClockDevice.zig"); + pub const BlockMemory = @import("base/BlockMemory.zig"); pub const I2C_Device = @import("base/I2C_Device.zig"); }; @@ -240,15 +240,15 @@ test { _ = stepper.DRV8825; _ = stepper.ULN2003; - _ = IO_expander.pcf8574; + _ = io_expander.pcf8574; _ = time; _ = DateTime; - _ = base.Datagram_Device; - _ = base.Stream_Device; + _ = base.DatagramDevice; + _ = base.StreamDevice; _ = base.Digital_IO; - _ = base.Block_Memory; - _ = base.Clock_Device; + _ = base.BlockMemory; + _ = base.ClockDevice; _ = base.I2C_Device; } diff --git a/drivers/sensor/AHT30.zig b/drivers/src/sensor/AHT30.zig similarity index 99% rename from drivers/sensor/AHT30.zig rename to drivers/src/sensor/AHT30.zig index 756717458..7aacb0c64 100644 --- a/drivers/sensor/AHT30.zig +++ b/drivers/src/sensor/AHT30.zig @@ -5,7 +5,7 @@ //! * AHT30: https://eleparts.co.kr/data/goods_attach/202306/good-pdf-12751003-1.pdf //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); pub const AHT30 = struct { dev: mdf.base.I2C_Device, diff --git a/drivers/sensor/AS5600.zig b/drivers/src/sensor/AS5600.zig similarity index 99% rename from drivers/sensor/AS5600.zig rename to drivers/src/sensor/AS5600.zig index 0f533b529..01ea984d0 100644 --- a/drivers/sensor/AS5600.zig +++ b/drivers/src/sensor/AS5600.zig @@ -5,7 +5,7 @@ //! * https://www.mouser.com/datasheet/2/588/AS5600_DS000365_5-00-1877365.pdf //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); pub const AS5600 = struct { const Self = @This(); diff --git a/drivers/sensor/DS18B20.zig b/drivers/src/sensor/DS18B20.zig similarity index 99% rename from drivers/sensor/DS18B20.zig rename to drivers/src/sensor/DS18B20.zig index 4d17fcf13..b57941f9c 100644 --- a/drivers/sensor/DS18B20.zig +++ b/drivers/src/sensor/DS18B20.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); /// Driver for the DS18B20 1-Wire temperature sensor. /// @@ -19,7 +19,7 @@ pub const DS18B20 = struct { const Self = @This(); pin: mdf.base.Digital_IO, - clock_dev: mdf.base.Clock_Device, + clock_dev: mdf.base.ClockDevice, // timing constants in microseconds const T_RESET_US = 480; @@ -89,7 +89,7 @@ pub const DS18B20 = struct { resolution: Resolution, }; - pub fn init(pin: mdf.base.Digital_IO, clock_dev: mdf.base.Clock_Device) !Self { + pub fn init(pin: mdf.base.Digital_IO, clock_dev: mdf.base.ClockDevice) !Self { try pin.set_direction(.input); return .{ .pin = pin, .clock_dev = clock_dev }; } diff --git a/drivers/sensor/HTS221.zig b/drivers/src/sensor/HTS221.zig similarity index 99% rename from drivers/sensor/HTS221.zig rename to drivers/src/sensor/HTS221.zig index 2132f56aa..974ea1bad 100644 --- a/drivers/sensor/HTS221.zig +++ b/drivers/src/sensor/HTS221.zig @@ -6,7 +6,7 @@ //! * HTS221: https://www.st.com/resource/en/datasheet/hts221.pdf //! const std = @import("std"); -const mdf_base = @import("../framework.zig").base; +const mdf_base = @import("../root.zig").base; const InterfaceError = mdf_base.I2C_Device.InterfaceError; const assert = std.debug.assert; diff --git a/drivers/sensor/ICM-20948.zig b/drivers/src/sensor/ICM_20948.zig similarity index 95% rename from drivers/sensor/ICM-20948.zig rename to drivers/src/sensor/ICM_20948.zig index dd3f885a0..e97195b14 100644 --- a/drivers/sensor/ICM-20948.zig +++ b/drivers/src/sensor/ICM_20948.zig @@ -33,7 +33,7 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const log = struct { const builtin = @import("builtin"); @@ -65,7 +65,7 @@ pub const ICM_20948 = struct { dev: mdf.base.I2C_Device, address: mdf.base.I2C_Device.Address, - clock: mdf.base.Clock_Device, + clock: mdf.base.ClockDevice, config: Config, current_bank: ?u2 = null, slave_address: u8 = 0, @@ -325,7 +325,7 @@ pub const ICM_20948 = struct { pub fn init( dev: mdf.base.I2C_Device, address: mdf.base.I2C_Device.Address, - clock: mdf.base.Clock_Device, + clock: mdf.base.ClockDevice, config: Config, ) Error!Self { return Self{ .dev = dev, .address = address, .clock = clock, .config = config }; @@ -545,14 +545,14 @@ pub const ICM_20948 = struct { }); } - const Accel_data_unscaled = packed struct { + const AccelDataUnscaled = packed struct { x: i16 = 0, y: i16 = 0, z: i16 = 0, }; - pub fn get_accel_data_unscaled(self: *Self) Error!Accel_data_unscaled { - var raw_data: Accel_data_unscaled = .{}; + pub fn get_accel_data_unscaled(self: *Self) Error!AccelDataUnscaled { + var raw_data: AccelDataUnscaled = .{}; self.read_reg(.{ .bank0 = .accel_xout_h }, std.mem.asBytes(&raw_data)) catch |err| { log.err("Failed to read accelerometer data: {}", .{err}); @@ -566,13 +566,13 @@ pub const ICM_20948 = struct { }; } - const Accel_data = struct { + const AccelData = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0, }; - pub fn get_accel_data(self: *Self) Error!Accel_data { + pub fn get_accel_data(self: *Self) Error!AccelData { const unscaled_data = try self.get_accel_data_unscaled(); const scalar_val = self.accel_scalar(); @@ -609,14 +609,14 @@ pub const ICM_20948 = struct { }); } - const Gyro_data_unscaled = packed struct { + const GyroDataUnscaled = packed struct { x: i16 = 0, y: i16 = 0, z: i16 = 0, }; - pub fn get_gyro_data_unscaled(self: *Self) Error!Gyro_data_unscaled { - var raw_data: Gyro_data_unscaled = .{}; + pub fn get_gyro_data_unscaled(self: *Self) Error!GyroDataUnscaled { + var raw_data: GyroDataUnscaled = .{}; self.read_reg(.{ .bank0 = .gyro_xout_h }, std.mem.asBytes(&raw_data)) catch |err| { log.err("Failed to read gyroscope data: {}", .{err}); @@ -630,13 +630,13 @@ pub const ICM_20948 = struct { }; } - const Gyro_data = struct { + const GyroData = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0, }; - pub fn get_gyro_data(self: *Self) Error!Gyro_data { + pub fn get_gyro_data(self: *Self) Error!GyroData { const unscaled_data = try self.get_gyro_data_unscaled(); const scalar_val = self.gyro_scalar(); @@ -652,15 +652,15 @@ pub const ICM_20948 = struct { } const SixDofData = struct { - accel: Accel_data, - gyro: Gyro_data, + accel: AccelData, + gyro: GyroData, temp: f32, }; pub fn get_accel_gyro_data(self: *Self) Error!SixDofData { var raw_data = packed struct { - accel: Accel_data_unscaled = .{}, - gyro: Gyro_data_unscaled = .{}, + accel: AccelDataUnscaled = .{}, + gyro: GyroDataUnscaled = .{}, temp: i16 = 0, }{}; @@ -687,15 +687,15 @@ pub const ICM_20948 = struct { }; } - const NineDofData = struct { accel: Accel_data, gyro: Gyro_data, temp: f32, mag: Mag_data }; + const NineDofData = struct { accel: AccelData, gyro: GyroData, temp: f32, mag: MagData }; pub fn get_accel_gyro_mag_data(self: *Self) Error!NineDofData { try self.mag_set_sensor_read(); var raw_data = packed struct { - accel: Accel_data_unscaled = .{}, - gyro: Gyro_data_unscaled = .{}, + accel: AccelDataUnscaled = .{}, + gyro: GyroDataUnscaled = .{}, temp: i16 = 0, - mag: Mag_data_unscaled = .{}, + mag: MagDataUnscaled = .{}, }{}; self.read_reg(.{ .bank0 = .accel_xout_h }, std.mem.asBytes(&raw_data)) catch |err| { @@ -837,7 +837,7 @@ pub const ICM_20948 = struct { try self.modify_reg(.{ .bank0 = .user_ctrl }, user_ctrl, .{ .I2C_MST_RST = 1 }); } - const Mag_data_unscaled = packed struct { + const MagDataUnscaled = packed struct { status1: u8 = 0, x: i16 = 0, y: i16 = 0, @@ -860,9 +860,9 @@ pub const ICM_20948 = struct { self.clock.sleep_us(MAG_READ_DELAY_US); } - pub fn get_mag_data_unscaled(self: *Self) Error!Mag_data_unscaled { + pub fn get_mag_data_unscaled(self: *Self) Error!MagDataUnscaled { try self.mag_set_sensor_read(); - var raw_data: Mag_data_unscaled = .{}; + var raw_data: MagDataUnscaled = .{}; self.read_reg(.{ .bank0 = .ext_slv_sens_data_00 }, std.mem.asBytes(&raw_data)) catch |err| { log.err("Failed to read magnetometer data: {}", .{err}); @@ -878,13 +878,13 @@ pub const ICM_20948 = struct { } // Unit: µT - const Mag_data = struct { + const MagData = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0, }; - pub fn get_mag_data(self: *Self) Error!Mag_data { + pub fn get_mag_data(self: *Self) Error!MagData { const unscaled_data = try self.get_mag_data_unscaled(); return .{ @@ -896,12 +896,12 @@ pub const ICM_20948 = struct { }; // Testing -const TestI2CDevice = mdf.base.I2C_Device.Test_Device; -const TestTime = mdf.base.Clock_Device.Test_Device; +const Test_I2C_Device = mdf.base.I2C_Device.TestDevice; +const TestTime = mdf.base.ClockDevice.TestDevice; test "set_bank" { var ttd = TestTime.init(); - var d = TestI2CDevice.init(null, true); + var d = Test_I2C_Device.init(null, true); defer d.deinit(); const id = d.i2c_device(); @@ -929,7 +929,7 @@ test "set_bank" { test "reset" { var ttd = TestTime.init(); - var d = TestI2CDevice.init(null, true); + var d = Test_I2C_Device.init(null, true); defer d.deinit(); const id = d.i2c_device(); @@ -947,7 +947,7 @@ test "reset" { test "read_byte" { var ttd = TestTime.init(); - var d = TestI2CDevice.init(null, true); + var d = Test_I2C_Device.init(null, true); defer d.deinit(); const id = d.i2c_device(); @@ -964,7 +964,7 @@ test "read_byte" { test "error handling in setup" { var ttd = TestTime.init(); - var d = TestI2CDevice.init(null, true); + var d = Test_I2C_Device.init(null, true); defer d.deinit(); const id = d.i2c_device(); @@ -978,7 +978,7 @@ test "error handling in setup" { test "device responsiveness check" { var ttd = TestTime.init(); - var d = TestI2CDevice.init(null, true); + var d = Test_I2C_Device.init(null, true); defer d.deinit(); const id = d.i2c_device(); diff --git a/drivers/sensor/MLX90640.zig b/drivers/src/sensor/MLX90640.zig similarity index 97% rename from drivers/sensor/MLX90640.zig rename to drivers/src/sensor/MLX90640.zig index a05b406b7..35958fb5d 100644 --- a/drivers/sensor/MLX90640.zig +++ b/drivers/src/sensor/MLX90640.zig @@ -9,9 +9,9 @@ //! The calculations were copied from https://github.com/netzbasteln/MLX90640-Thermocam //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); -const Mlx90649Error = error{ +pub const Error = error{ BadPixels, TooManyBrokenPixels, TooManyOutlierPixels, @@ -19,10 +19,10 @@ const Mlx90649Error = error{ LargeAdjacentPixelDifference, }; -pub const MLX90640_Config = struct { +pub const Config = struct { i2c: mdf.base.I2C_Device, address: mdf.base.I2C_Device.Address, - clock: mdf.base.Clock_Device, + clock: mdf.base.ClockDevice, open_air_shift: f32 = 8, emissivity: f32 = 0.95, }; @@ -92,12 +92,12 @@ pub const MLX90640 = struct { scratch_data: [768]f32 = undefined, i2c: mdf.base.I2C_Device, address: mdf.base.I2C_Device.Address, - clock_device: mdf.base.Clock_Device, + clock_device: mdf.base.ClockDevice, params: parameters, emissivity: f32, open_air_shift: f32, - pub fn init(cfg: MLX90640_Config) !Self { + pub fn init(cfg: Config) !Self { return .{ .i2c = cfg.i2c, .address = cfg.address, @@ -782,30 +782,30 @@ pub const MLX90640 = struct { } fn extract_ky_pixel(self: *Self) void { - var KvT: [4]u8 = undefined; + var kvt: [4]u8 = undefined; var KvRoCo: i8 = @intCast((self.eeprom[52] & 0xF000) >> 12); if (KvRoCo > 7) { KvRoCo = KvRoCo - 16; } - KvT[0] = @intCast(KvRoCo); + kvt[0] = @intCast(KvRoCo); var KvReCo: i8 = @intCast((self.eeprom[52] & 0x0F00) >> 8); if (KvReCo > 7) { KvReCo = KvReCo - 16; } - KvT[2] = @intCast(KvReCo); + kvt[2] = @intCast(KvReCo); var KvRoCe: i8 = @intCast((self.eeprom[52] & 0x00F0) >> 4); if (KvRoCe > 7) { KvRoCe = KvRoCe - 16; } - KvT[1] = @intCast(KvRoCe); + kvt[1] = @intCast(KvRoCe); var KvReCe: i8 = @intCast(self.eeprom[52] & 0x000F); if (KvReCe > 7) { KvReCe = KvReCe - 16; } - KvT[3] = @intCast(KvReCe); + kvt[3] = @intCast(KvReCe); var kvScale: u8 = @intCast((self.eeprom[56] & 0x0F00) >> 8); @@ -813,7 +813,7 @@ pub const MLX90640 = struct { for (0..columns) |j| { const p = 32 * i + j; const split = 2 * (p / 32 - (p / 64) * 2) + p % 2; - self.scratch_data[p] = @floatFromInt(KvT[split]); + self.scratch_data[p] = @floatFromInt(kvt[split]); self.scratch_data[p] = self.scratch_data[p] / std.math.pow(f32, 2, @floatFromInt(kvScale)); } } @@ -891,7 +891,7 @@ pub const MLX90640 = struct { self.params.cpOffset[1] = offsetSP[1]; } - fn extract_deviating_pixels(self: *Self) !void { + fn extract_deviating_pixels(self: *Self) Error!void { var pixCnt: u32 = 0; for (0..5) |i| { pixCnt = @intCast(i); @@ -915,11 +915,11 @@ pub const MLX90640 = struct { } if (brokenPixCnt > 4) { - return Mlx90649Error.TooManyBrokenPixels; + return error.TooManyBrokenPixels; } else if (outlierPixCnt > 4) { - return Mlx90649Error.TooManyOutlierPixels; + return error.TooManyOutlierPixels; } else if ((brokenPixCnt + outlierPixCnt) > 4) { - return Mlx90649Error.TooManyOutlierAndBrokenPixels; + return error.TooManyOutlierAndBrokenPixels; } else { for (0..brokenPixCnt) |x| { pixCnt = @intCast(x); @@ -944,25 +944,25 @@ pub const MLX90640 = struct { } } - fn check_adjacent_pixels(_: *Self, pix1: u16, pix2: u16) !void { + fn check_adjacent_pixels(_: *Self, pix1: u16, pix2: u16) Error!void { var pixPosDif: i32 = 0; pixPosDif = pix1 - pix2; if (pixPosDif > -34 and pixPosDif < -30) { - return Mlx90649Error.LargeAdjacentPixelDifference; + return error.LargeAdjacentPixelDifference; } if (pixPosDif > -2 and pixPosDif < 2) { - return Mlx90649Error.LargeAdjacentPixelDifference; + return error.LargeAdjacentPixelDifference; } if (pixPosDif > 30 and pixPosDif < 34) { - return Mlx90649Error.LargeAdjacentPixelDifference; + return error.LargeAdjacentPixelDifference; } } }; test "control_register_values" { - const Test_I2C_Device = mdf.base.I2C_Device.Test_Device; - const Test_Clock = mdf.base.Clock_Device.Test_Device; + const Test_I2C_Device = mdf.base.I2C_Device.TestDevice; + const TestClock = mdf.base.ClockDevice.TestDevice; const control_register_data = [_][]const u8{ &.{ 0b00000010, 0b10000000 }, //refresh rate data &.{ 0b00000010, 0b10000000 }, //refresh rate data that is fetched before set_refresh_rate @@ -972,7 +972,7 @@ test "control_register_values" { var td = Test_I2C_Device.init(&control_register_data, true); defer td.deinit(); - var tc = Test_Clock.init(); + var tc = TestClock.init(); var camera = try MLX90640.init(.{ .i2c = td.i2c_device(), .address = @enumFromInt(0x7f), .clock = tc.clock_device() }); @@ -992,8 +992,8 @@ test "control_register_values" { } test "temperature" { - const Test_I2C_Device = mdf.base.I2C_Device.Test_Device; - const Test_Clock = mdf.base.Clock_Device.Test_Device; + const Test_I2C_Device = mdf.base.I2C_Device.TestDevice; + const TestClock = mdf.base.ClockDevice.TestDevice; const temperature = [_]u8{ 0xff, 0xde, 0xff, 0xd8, 0xff, 0xdb, 0xff, 0xcf, 0xff, 0xd8, 0xff, 0xcf, 0xff, 0xd8, 0xff, 0xcb, 0xff, 0xd7, 0xff, 0xcc, 0xff, 0xd6, 0xff, 0xc7, 0xff, 0xd5, 0xff, 0xcc, 0xff, 0xd6, 0xff, 0xc6, 0xff, 0xd6, 0xff, 0xc8, 0xff, 0xd6, 0xff, 0xc4, 0xff, 0xda, 0xff, 0xc8, 0xff, 0xd7, 0xff, 0xc1, 0xff, 0xd9, 0xff, 0xc7, 0xff, 0xd4, 0xff, 0xc0, 0xff, 0xd4, 0xff, 0xc5, 0xff, 0xd8, 0xff, 0xba, 0xff, 0xd6, 0xff, 0xd2, 0xff, 0xc9, 0xff, 0xcf, 0xff, 0xd0, 0xff, 0xcb, 0xff, 0xc8, 0xff, 0xcc, 0xff, 0xcc, 0xff, 0xc9, 0xff, 0xc7, 0xff, 0xca, 0xff, 0xcf, 0xff, 0xc6, 0xff, 0xc6, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xc2, 0xff, 0xc6, 0xff, 0xc5, 0xff, 0xcf, 0xff, 0xc2, 0xff, 0xc3, 0xff, 0xc1, 0xff, 0xd0, 0xff, 0xc2, 0xff, 0xc3, 0xff, 0xc2, 0xff, 0xcd, 0xff, 0xbe, 0xff, 0xc6, 0xff, 0xbb, 0xff, 0xdd, 0xff, 0xd5, 0xff, 0xda, 0xff, 0xce, 0xff, 0xd9, 0xff, 0xd1, 0xff, 0xd8, 0xff, 0xc9, 0xff, 0xd7, 0xff, 0xce, 0xff, 0xd6, 0xff, 0xc4, 0xff, 0xd4, 0xff, 0xc8, 0xff, 0xd3, 0xff, 0xc4, 0xff, 0xd8, 0xff, 0xcb, 0xff, 0xd5, 0xff, 0xc1, 0xff, 0xd6, 0xff, 0xc4, 0xff, 0xd3, 0xff, 0xc0, 0xff, 0xd2, 0xff, 0xc4, 0xff, 0xd5, 0xff, 0xbf, 0xff, 0xd5, 0xff, 0xc5, 0xff, 0xd9, 0xff, 0xb7, 0xff, 0xd1, 0xff, 0xcf, 0xff, 0xca, 0xff, 0xcf, 0xff, 0xce, 0xff, 0xcb, 0xff, 0xc7, 0xff, 0xc8, 0xff, 0xcf, 0xff, 0xc5, 0xff, 0xc4, 0xff, 0xc6, 0xff, 0xcc, 0xff, 0xc4, 0xff, 0xc2, 0xff, 0xc5, 0xff, 0xcc, 0xff, 0xc3, 0xff, 0xc4, 0xff, 0xc3, 0xff, 0xcb, 0xff, 0xc1, 0xff, 0xc4, 0xff, 0xc3, 0xff, 0xcd, 0xff, 0xbf, 0xff, 0xc5, 0xff, 0xc0, 0xff, 0xcc, 0xff, 0xc0, 0xff, 0xc5, 0xff, 0xbd, 0xff, 0xdd, 0xff, 0xd4, 0xff, 0xda, 0xff, 0xcf, 0xff, 0xdc, 0xff, 0xd0, 0xff, 0xd7, 0xff, 0xc8, 0xff, 0xd6, 0xff, 0xc7, 0xff, 0xd2, 0xff, 0xc5, 0xff, 0xd4, 0xff, 0xc7, 0xff, 0xd3, 0xff, 0xc0, 0xff, 0xd7, 0xff, 0xc6, 0xff, 0xd3, 0xff, 0xc2, 0xff, 0xd5, 0xff, 0xc4, 0xff, 0xd2, 0xff, 0xc2, 0xff, 0xd6, 0xff, 0xc2, 0xff, 0xd5, 0xff, 0xbd, 0xff, 0xd2, 0xff, 0xc4, 0xff, 0xd7, 0xff, 0xb9, 0xff, 0xd4, 0xff, 0xcd, 0xff, 0xc6, 0xff, 0xce, 0xff, 0xcd, 0xff, 0xc8, 0xff, 0xc5, 0xff, 0xc9, 0xff, 0xca, 0xff, 0xc4, 0xff, 0xc4, 0xff, 0xc2, 0xff, 0xc9, 0xff, 0xc2, 0xff, 0xc0, 0xff, 0xc2, 0xff, 0xcd, 0xff, 0xc0, 0xff, 0xc2, 0xff, 0xbf, 0xff, 0xca, 0xff, 0xbd, 0xff, 0xc3, 0xff, 0xc0, 0xff, 0xd1, 0xff, 0xbe, 0xff, 0xc4, 0xff, 0xbf, 0xff, 0xc9, 0xff, 0xb9, 0xff, 0xc8, 0xff, 0xb9, 0xff, 0xdd, 0xff, 0xd3, 0xff, 0xd9, 0xff, 0xce, 0xff, 0xd8, 0xff, 0xce, 0xff, 0xd7, 0xff, 0xc8, 0xff, 0xd4, 0xff, 0xc9, 0xff, 0xd1, 0xff, 0xc4, 0xff, 0xd3, 0xff, 0xc5, 0xff, 0xd0, 0xff, 0xbf, 0xff, 0xd1, 0xff, 0xc5, 0xff, 0xd1, 0xff, 0xbe, 0xff, 0xd3, 0xff, 0xc5, 0xff, 0xd2, 0xff, 0xc1, 0xff, 0xd6, 0xff, 0xc5, 0xff, 0xd3, 0xff, 0xbf, 0xff, 0xd4, 0xff, 0xc3, 0xff, 0xd7, 0xff, 0xb8, 0xff, 0xd1, 0xff, 0xcb, 0xff, 0xc5, 0xff, 0xcb, 0xff, 0xcc, 0xff, 0xc5, 0xff, 0xc4, 0xff, 0xc5, 0xff, 0xc8, 0xff, 0xc3, 0xff, 0xc1, 0xff, 0xc0, 0xff, 0xc5, 0xff, 0xbf, 0xff, 0xbe, 0xff, 0xc2, 0xff, 0xc7, 0xff, 0xbd, 0xff, 0xc1, 0xff, 0xbd, 0xff, 0xc8, 0xff, 0xbc, 0xff, 0xc2, 0xff, 0xc0, 0xff, 0xcd, 0xff, 0xbd, 0xff, 0xc5, 0xff, 0xbf, 0xff, 0xc8, 0xff, 0xbf, 0xff, 0xc5, 0xff, 0xba, 0xff, 0xda, 0xff, 0xd3, 0xff, 0xda, 0xff, 0xcb, 0xff, 0xd8, 0xff, 0xcf, 0xff, 0xd6, 0xff, 0xc8, 0xff, 0xd6, 0xff, 0xcc, 0xff, 0xd2, 0xff, 0xc4, 0xff, 0xd4, 0xff, 0xc6, 0xff, 0xd2, 0xff, 0xc2, 0xff, 0xd4, 0xff, 0xc5, 0xff, 0xd0, 0xff, 0xbf, 0xff, 0xd3, 0xff, 0xc6, 0xff, 0xd2, 0xff, 0xc1, 0xff, 0xd3, 0xff, 0xc4, 0xff, 0xd1, 0xff, 0xbf, 0xff, 0xd3, 0xff, 0xc4, 0xff, 0xd7, 0xff, 0xb8, 0xff, 0xcf, 0xff, 0xc9, 0xff, 0xc7, 0xff, 0xc8, 0xff, 0xcd, 0xff, 0xc5, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xc9, 0xff, 0xc1, 0xff, 0xbb, 0xff, 0xc2, 0xff, 0xc8, 0xff, 0xbe, 0xff, 0xbe, 0xff, 0xbf, 0xff, 0xc8, 0xff, 0xbf, 0xff, 0xbc, 0xff, 0xbf, 0xff, 0xc9, 0xff, 0xbb, 0xff, 0xbf, 0xff, 0xbd, 0xff, 0xcb, 0xff, 0xbf, 0xff, 0xc1, 0xff, 0xba, 0xff, 0xca, 0xff, 0xbc, 0xff, 0xc6, 0xff, 0xb9, 0xff, 0xdd, 0xff, 0xd3, 0xff, 0xd9, 0xff, 0xcd, 0xff, 0xd9, 0xff, 0xcc, 0xff, 0xd5, 0xff, 0xc8, 0xff, 0xd3, 0xff, 0xc9, 0xff, 0xcf, 0xff, 0xc2, 0xff, 0xd4, 0xff, 0xc8, 0xff, 0xcf, 0xff, 0xc1, 0xff, 0xd4, 0xff, 0xc7, 0xff, 0xd0, 0xff, 0xc0, 0xff, 0xd4, 0xff, 0xc7, 0xff, 0xd1, 0xff, 0xc0, 0xff, 0xd6, 0xff, 0xc5, 0xff, 0xd1, 0xff, 0xbf, 0xff, 0xd3, 0xff, 0xc4, 0xff, 0xd2, 0xff, 0xb7, 0xff, 0xd1, 0xff, 0xc8, 0xff, 0xc5, 0xff, 0xc9, 0xff, 0xcb, 0xff, 0xc4, 0xff, 0xc0, 0xff, 0xc5, 0xff, 0xc9, 0xff, 0xc1, 0xff, 0xbc, 0xff, 0xc0, 0xff, 0xc7, 0xff, 0xc0, 0xff, 0xbd, 0xff, 0xbe, 0xff, 0xc7, 0xff, 0xbc, 0xff, 0xbe, 0xff, 0xbe, 0xff, 0xca, 0xff, 0xbc, 0xff, 0xbe, 0xff, 0xbd, 0xff, 0xc7, 0xff, 0xbd, 0xff, 0xbf, 0xff, 0xbb, 0xff, 0xcb, 0xff, 0xb9, 0xff, 0xc2, 0xff, 0xb8, 0xff, 0xd9, 0xff, 0xd6, 0xff, 0xd8, 0xff, 0xce, 0xff, 0xd5, 0xff, 0xd1, 0xff, 0xd4, 0xff, 0xc7, 0xff, 0xd4, 0xff, 0xcc, 0xff, 0xd5, 0xff, 0xc1, 0xff, 0xd1, 0xff, 0xc7, 0xff, 0xd1, 0xff, 0xbf, 0xff, 0xd2, 0xff, 0xc4, 0xff, 0xd1, 0xff, 0xbe, 0xff, 0xd2, 0xff, 0xc5, 0xff, 0xd1, 0xff, 0xbe, 0xff, 0xd7, 0xff, 0xc3, 0xff, 0xd2, 0xff, 0xc0, 0xff, 0xd0, 0xff, 0xc3, 0xff, 0xd1, 0xff, 0xb8, 0xff, 0xcf, 0xff, 0xc7, 0xff, 0xc6, 0xff, 0xcc, 0xff, 0xca, 0xff, 0xc8, 0xff, 0xc5, 0xff, 0xc3, 0xff, 0xca, 0xff, 0xc1, 0xff, 0xbe, 0xff, 0xc2, 0xff, 0xca, 0xff, 0xc1, 0xff, 0xbc, 0xff, 0xbe, 0xff, 0xc6, 0xff, 0xbb, 0xff, 0xbc, 0xff, 0xbd, 0xff, 0xc7, 0xff, 0xbd, 0xff, 0xbc, 0xff, 0xbd, 0xff, 0xca, 0xff, 0xba, 0xff, 0xbe, 0xff, 0xbb, 0xff, 0xc5, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0xb5, 0xff, 0xdb, 0xff, 0xd8, 0xff, 0xe0, 0xff, 0xda, 0xff, 0xe8, 0xff, 0xe1, 0xff, 0xeb, 0xff, 0xe2, 0xff, 0xf1, 0xff, 0xe8, 0xff, 0xef, 0xff, 0xdc, 0xff, 0xe6, 0xff, 0xd8, 0xff, 0xd4, 0xff, 0xc1, 0xff, 0xd4, 0xff, 0xc7, 0xff, 0xcf, 0xff, 0xc1, 0xff, 0xd2, 0xff, 0xc4, 0xff, 0xd0, 0xff, 0xbe, 0xff, 0xd3, 0xff, 0xc2, 0xff, 0xd1, 0xff, 0xbe, 0xff, 0xd3, 0xff, 0xc3, 0xff, 0xd2, 0xff, 0xb9, 0xff, 0xd1, 0xff, 0xd2, 0xff, 0xd6, 0xff, 0xdd, 0xff, 0xe7, 0xff, 0xe9, 0xff, 0xea, 0xff, 0xef, 0xff, 0xf3, 0xff, 0xeb, 0xff, 0xe1, 0xff, 0xde, 0xff, 0xdb, 0xff, 0xcd, 0xff, 0xbb, 0xff, 0xbb, 0xff, 0xc5, 0xff, 0xbb, 0xff, 0xbb, 0xff, 0xbb, 0xff, 0xc5, 0xff, 0xb8, 0xff, 0xbe, 0xff, 0xba, 0xff, 0xc6, 0xff, 0xba, 0xff, 0xc0, 0xff, 0xba, 0xff, 0xc7, 0xff, 0xb8, 0xff, 0xbf, 0xff, 0xb6, 0xff, 0xe6, 0xff, 0xe8, 0xff, 0xfa, 0xff, 0xf5, 0x0, 0x4, 0x0, 0x3, 0x0, 0xa, 0xff, 0xfe, 0x0, 0x5, 0xff, 0xf7, 0xff, 0xf2, 0xff, 0xe2, 0xff, 0xe5, 0xff, 0xd2, 0xff, 0xcf, 0xff, 0xc1, 0xff, 0xd3, 0xff, 0xc2, 0xff, 0xcd, 0xff, 0xc0, 0xff, 0xd4, 0xff, 0xc3, 0xff, 0xd2, 0xff, 0xbf, 0xff, 0xd3, 0xff, 0xc3, 0xff, 0xcc, 0xff, 0xbe, 0xff, 0xcf, 0xff, 0xc2, 0xff, 0xd1, 0xff, 0xb9, 0xff, 0xd5, 0xff, 0xd9, 0xff, 0xe7, 0xff, 0xf3, 0xff, 0xf4, 0xff, 0xf0, 0xff, 0xf0, 0xff, 0xf3, 0xff, 0xf3, 0xff, 0xe6, 0xff, 0xdd, 0xff, 0xd9, 0xff, 0xd3, 0xff, 0xc4, 0xff, 0xb9, 0xff, 0xb9, 0xff, 0xc4, 0xff, 0xb5, 0xff, 0xb9, 0xff, 0xba, 0xff, 0xc3, 0xff, 0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xff, 0xc6, 0xff, 0xb7, 0xff, 0xba, 0xff, 0xb9, 0xff, 0xc2, 0xff, 0xb6, 0xff, 0xbf, 0xff, 0xb1, 0xff, 0xe7, 0xff, 0xe7, 0x0, 0x0, 0xff, 0xfa, 0x0, 0x1, 0xff, 0xf7, 0x0, 0x1, 0xff, 0xf6, 0xff, 0xfc, 0xff, 0xf0, 0xff, 0xf4, 0xff, 0xe1, 0xff, 0xdf, 0xff, 0xcf, 0xff, 0xcf, 0xff, 0xc2, 0xff, 0xd2, 0xff, 0xc7, 0xff, 0xcd, 0xff, 0xc0, 0xff, 0xd1, 0xff, 0xc2, 0xff, 0xcf, 0xff, 0xbd, 0xff, 0xd2, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xbe, 0xff, 0xd4, 0xff, 0xc2, 0xff, 0xce, 0xff, 0xb9, 0xff, 0xd2, 0xff, 0xd7, 0xff, 0xe3, 0xff, 0xef, 0xff, 0xf0, 0xff, 0xe6, 0xff, 0xe9, 0xff, 0xeb, 0xff, 0xeb, 0xff, 0xe2, 0xff, 0xda, 0xff, 0xd9, 0xff, 0xcd, 0xff, 0xbf, 0xff, 0xba, 0xff, 0xb9, 0xff, 0xc2, 0xff, 0xb7, 0xff, 0xb8, 0xff, 0xb7, 0xff, 0xc2, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xba, 0xff, 0xc2, 0xff, 0xb6, 0xff, 0xb9, 0xff, 0xb7, 0xff, 0xc0, 0xff, 0xb6, 0xff, 0xbb, 0xff, 0xb4, 0xff, 0xe2, 0xff, 0xe3, 0xff, 0xf6, 0xff, 0xf3, 0xff, 0xfe, 0xff, 0xf4, 0xff, 0xf6, 0xff, 0xf1, 0xff, 0xf8, 0xff, 0xee, 0xff, 0xec, 0xff, 0xd8, 0xff, 0xd9, 0xff, 0xcb, 0xff, 0xcf, 0xff, 0xc0, 0xff, 0xcf, 0xff, 0xc5, 0xff, 0xcc, 0xff, 0xbe, 0xff, 0xce, 0xff, 0xc1, 0xff, 0xcf, 0xff, 0xbe, 0xff, 0xcf, 0xff, 0xc2, 0xff, 0xce, 0xff, 0xbd, 0xff, 0xce, 0xff, 0xc2, 0xff, 0xd0, 0xff, 0xbb, 0xff, 0xcc, 0xff, 0xd1, 0xff, 0xd9, 0xff, 0xe5, 0xff, 0xea, 0xff, 0xe3, 0xff, 0xdb, 0xff, 0xe3, 0xff, 0xe0, 0xff, 0xd6, 0xff, 0xcf, 0xff, 0xcf, 0xff, 0xc3, 0xff, 0xbb, 0xff, 0xb4, 0xff, 0xb7, 0xff, 0xbe, 0xff, 0xb5, 0xff, 0xb2, 0xff, 0xb4, 0xff, 0xbd, 0xff, 0xb4, 0xff, 0xb7, 0xff, 0xb5, 0xff, 0xc0, 0xff, 0xb5, 0xff, 0xb6, 0xff, 0xb3, 0xff, 0xbd, 0xff, 0xb2, 0xff, 0xb9, 0xff, 0xb4, 0xff, 0xe2, 0xff, 0xe0, 0xff, 0xea, 0xff, 0xe5, 0xff, 0xf4, 0xff, 0xec, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xf0, 0xff, 0xe5, 0xff, 0xe8, 0xff, 0xd7, 0xff, 0xd5, 0xff, 0xca, 0xff, 0xcc, 0xff, 0xc1, 0xff, 0xd0, 0xff, 0xc3, 0xff, 0xcd, 0xff, 0xbd, 0xff, 0xce, 0xff, 0xc3, 0xff, 0xcd, 0xff, 0xbd, 0xff, 0xcd, 0xff, 0xc1, 0xff, 0xca, 0xff, 0xbd, 0xff, 0xc9, 0xff, 0xc3, 0xff, 0xca, 0xff, 0xb7, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc2, 0xff, 0xcd, 0xff, 0xd6, 0xff, 0xd3, 0xff, 0xc8, 0xff, 0xcb, 0xff, 0xd4, 0xff, 0xcb, 0xff, 0xc3, 0xff, 0xc1, 0xff, 0xb5, 0xff, 0xad, 0xff, 0xa8, 0xff, 0xa9, 0xff, 0xb2, 0xff, 0xa5, 0xff, 0xa6, 0xff, 0xa7, 0xff, 0xb2, 0xff, 0xa8, 0xff, 0xa9, 0xff, 0xa9, 0xff, 0xb3, 0xff, 0xa6, 0xff, 0xac, 0xff, 0xa6, 0xff, 0xb1, 0xff, 0xaa, 0xff, 0xae, 0xff, 0xa2, 0x4d, 0xf4, 0x18, 0xd9, 0x7f, 0xff, 0x18, 0xd9, 0x7f, 0xff, 0x18, 0xd8, 0x7f, 0xff, 0x18, 0xd8, 0xff, 0xc9, 0xd1, 0x6e, 0x17, 0xe4, 0xd7, 0x18, 0xff, 0xfe, 0x0, 0xb, 0x0, 0x4, 0xff, 0xfe, 0x17, 0xe3, 0x3, 0xcc, 0x2, 0x36, 0x7f, 0xff, 0x17, 0xe3, 0x3, 0xcd, 0x2, 0x36, 0x7f, 0xff, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x6, 0x36, 0x7f, 0xff, 0x18, 0xd9, 0x7f, 0xff, 0x18, 0xd9, 0x7f, 0xff, 0x18, 0xd8, 0x7f, 0xff, 0xff, 0xce, 0xf5, 0x87, 0xd2, 0x8c, 0xd7, 0x62, 0x0, 0xa, 0x0, 0x0, 0xff, 0xff, 0x0, 0x5, 0x0, 0xf1, 0x0, 0x3e, 0x25, 0x17, 0x0, 0x39, 0x0, 0xf1, 0x0, 0x3f, 0x25, 0x17, 0x0, 0x39, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0x3 }; @@ -1014,7 +1014,7 @@ test "temperature" { var td = Test_I2C_Device.init(&test_data, true); defer td.deinit(); - var tc = Test_Clock.init(); + var tc = TestClock.init(); var camera = try MLX90640.init(.{ .i2c = td.i2c_device(), .address = @enumFromInt(0x7f), .clock = tc.clock_device() }); diff --git a/drivers/sensor/MPU-6050.zig b/drivers/src/sensor/MPU_6050.zig similarity index 97% rename from drivers/sensor/MPU-6050.zig rename to drivers/src/sensor/MPU_6050.zig index b300da22e..0e95df94f 100644 --- a/drivers/sensor/MPU-6050.zig +++ b/drivers/src/sensor/MPU_6050.zig @@ -22,13 +22,13 @@ //! * DMP support const std = @import("std"); -const mdf = @import("../framework.zig"); -const Datagram_Device = mdf.base.Datagram_Device; -const Clock_Device = mdf.base.Clock_Device; +const mdf = @import("../root.zig"); +const DatagramDevice = mdf.base.DatagramDevice; +const ClockDevice = mdf.base.Clock_Device; pub const MPU_6050 = struct { - dev: Datagram_Device, - clock: Clock_Device, + dev: DatagramDevice, + clock: ClockDevice, accel_range: AccelRange, gyro_range: GyroRange, @@ -37,11 +37,11 @@ pub const MPU_6050 = struct { pub const TEMP_OFFSET: f32 = 36.53; pub const TEMP_SCALE: f32 = 1.0 / TEMP_SENSITIVITY; - pub const Error = Datagram_Device.AnyError; + pub const Error = DatagramDevice.AnyError; pub const VerifyError = error{ DeviceNotResponding, UnexpectedDeviceId }; pub const InitError = Error || VerifyError; - pub fn init(dev: Datagram_Device, clock: Clock_Device) InitError!MPU_6050 { + pub fn init(dev: DatagramDevice, clock: ClockDevice) InitError!MPU_6050 { var self: MPU_6050 = .{ .dev = dev, .clock = clock, diff --git a/drivers/sensor/TLV493D.zig b/drivers/src/sensor/TLV493D.zig similarity index 98% rename from drivers/sensor/TLV493D.zig rename to drivers/src/sensor/TLV493D.zig index 1a45ce5c3..aa2ad9892 100644 --- a/drivers/sensor/TLV493D.zig +++ b/drivers/src/sensor/TLV493D.zig @@ -6,9 +6,9 @@ //! * https://www.mouser.com/pdfDocs/Infineon-TLV493D-A1B6_3DMagnetic-UserManual-v01_03-EN.pdf //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const I2C_Device = mdf.base.I2C_Device; -const Clock_Device = mdf.base.Clock_Device; +const ClockDevice = mdf.base.Clock_Device; /// TLV493D I2C addresses pub const ADDRESS0: I2C_Device.Address = @enumFromInt(0x1F); @@ -146,7 +146,7 @@ pub const TLV493D = struct { dev: I2C_Device, address: I2C_Device.Address, - clock: Clock_Device, + clock: ClockDevice, read_data: ReadRegister, write_data: WriteRegister, x_data: i12 = 0, @@ -157,7 +157,7 @@ pub const TLV493D = struct { expected_frame_count: u2 = 0, /// Create a new TLV493D instance - pub fn init(dev: I2C_Device, address: I2C_Device.Address, clock: Clock_Device, config: Config) Error!Self { + pub fn init(dev: I2C_Device, address: I2C_Device.Address, clock: ClockDevice, config: Config) Error!Self { var self = Self{ .dev = dev, .address = address, diff --git a/drivers/sensor/TMP117.zig b/drivers/src/sensor/TMP117.zig similarity index 99% rename from drivers/sensor/TMP117.zig rename to drivers/src/sensor/TMP117.zig index e6932ed4d..b44317a45 100644 --- a/drivers/sensor/TMP117.zig +++ b/drivers/src/sensor/TMP117.zig @@ -6,7 +6,7 @@ //! * TMP117: https://www.ti.com/lit/ds/symlink/tmp117.pdf //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); pub const TMP117 = struct { const Self = @This(); diff --git a/drivers/stepper/ULN2003.zig b/drivers/src/stepper/ULN2003.zig similarity index 94% rename from drivers/stepper/ULN2003.zig rename to drivers/src/stepper/ULN2003.zig index 004261d86..5a9c5aebb 100644 --- a/drivers/stepper/ULN2003.zig +++ b/drivers/src/stepper/ULN2003.zig @@ -7,15 +7,15 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const common = @import("common.zig"); -pub const Stepper_Options = struct { +pub const Options = struct { in1_pin: mdf.base.Digital_IO, in2_pin: mdf.base.Digital_IO, in3_pin: mdf.base.Digital_IO, in4_pin: mdf.base.Digital_IO, - clock_device: mdf.base.Clock_Device, + clock_device: mdf.base.ClockDevice, motor_steps: u16 = 512, max_rpm: f64 = 30, }; @@ -29,7 +29,7 @@ pub const ULN2003 = struct { const STEP_TABLE_HALF = [_]u4{ 0b1000, 0b1100, 0b0100, 0b0110, 0b0010, 0b0011, 0b0001, 0b1001 }; in: [4]mdf.base.Digital_IO, - clock: mdf.base.Clock_Device, + clock: mdf.base.ClockDevice, rpm: f64 = 0, max_rpm: f64, step_table: []const u4 = STEP_TABLE_FULL[0..], @@ -46,7 +46,7 @@ pub const ULN2003 = struct { direction: Direction = .forward, motor_steps: u16, - pub fn init(opts: Stepper_Options) Self { + pub fn init(opts: Options) Self { return Self{ .clock = opts.clock_device, .in = .{ opts.in1_pin, opts.in2_pin, opts.in3_pin, opts.in4_pin }, @@ -192,21 +192,21 @@ pub const ULN2003 = struct { }; // Testing -const TestGPIO = mdf.base.Digital_IO.Test_Device; -const TestTime = mdf.base.Clock_Device.Test_Device; +const Test_GPIO = mdf.base.Digital_IO.TestDevice; +const TestTime = mdf.base.ClockDevice.TestDevice; const TestDevice = struct { - in1: TestGPIO, - in2: TestGPIO, - in3: TestGPIO, - in4: TestGPIO, + in1: Test_GPIO, + in2: Test_GPIO, + in3: Test_GPIO, + in4: Test_GPIO, clock: TestTime, }; fn create_test_device() TestDevice { return .{ - .in1 = TestGPIO.init(.output, .high), - .in2 = TestGPIO.init(.output, .high), - .in3 = TestGPIO.init(.output, .high), - .in4 = TestGPIO.init(.output, .high), + .in1 = Test_GPIO.init(.output, .high), + .in2 = Test_GPIO.init(.output, .high), + .in3 = Test_GPIO.init(.output, .high), + .in4 = Test_GPIO.init(.output, .high), .clock = TestTime.init(), }; } diff --git a/drivers/stepper/common.zig b/drivers/src/stepper/common.zig similarity index 97% rename from drivers/stepper/common.zig rename to drivers/src/stepper/common.zig index ebc51e91e..05acd00c4 100644 --- a/drivers/stepper/common.zig +++ b/drivers/src/stepper/common.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); /// Calculate the duration of a step pulse for a stepper with `steps` steps, `microsteps` /// microsteps, at `rpm` rpm. diff --git a/drivers/stepper/stepper.zig b/drivers/src/stepper/stepper.zig similarity index 92% rename from drivers/stepper/stepper.zig rename to drivers/src/stepper/stepper.zig index 96fd808f3..ae3a4c687 100644 --- a/drivers/stepper/stepper.zig +++ b/drivers/src/stepper/stepper.zig @@ -7,21 +7,23 @@ //! const std = @import("std"); -const mdf = @import("../framework.zig"); +const mdf = @import("../root.zig"); const common = @import("common.zig"); -pub const Stepper_Options = struct { +pub const Options = struct { ms1_pin: ?mdf.base.Digital_IO = undefined, ms2_pin: ?mdf.base.Digital_IO = undefined, ms3_pin: ?mdf.base.Digital_IO = undefined, dir_pin: mdf.base.Digital_IO, step_pin: mdf.base.Digital_IO, enable_pin: ?mdf.base.Digital_IO = undefined, - clock_device: mdf.base.Clock_Device, + clock_device: mdf.base.ClockDevice, motor_steps: u16 = 200, }; -pub const MSPinsError = error.MSPinsError; +pub const Error = error{ + Pins, +}; pub const State = enum { stopped, @@ -49,7 +51,7 @@ pub const DRV8825 = struct { pub fn Stepper(comptime Driver: type) type { return struct { const Self = @This(); - pub const Speed_Profile = union(enum) { + pub const SpeedProfile = union(enum) { constant_speed, linear_speed: struct { accel: u16 = 1000, @@ -66,11 +68,11 @@ pub fn Stepper(comptime Driver: type) type { step_pin: mdf.base.Digital_IO, enable_pin: ?mdf.base.Digital_IO, enable_active_state: mdf.base.Digital_IO.State = .low, - clock: mdf.base.Clock_Device, + clock: mdf.base.ClockDevice, rpm: f64 = 0, // Movement state - profile: Speed_Profile = .constant_speed, + profile: SpeedProfile = .constant_speed, // Steps remaining in accel steps_to_cruise: u32 = 0, // Steps remaining in current move @@ -86,7 +88,7 @@ pub fn Stepper(comptime Driver: type) type { dir_state: mdf.base.Digital_IO.State = .low, motor_steps: u16, - pub fn init(opts: Stepper_Options) Self { + pub fn init(opts: Options) Self { return Self{ .clock = opts.clock_device, .ms1_pin = opts.ms1_pin, @@ -159,7 +161,7 @@ pub fn Stepper(comptime Driver: type) type { // If any MS pins are not defined, return an error and don't change anything for ([_]?mdf.base.Digital_IO{ self.ms1_pin, self.ms2_pin, self.ms3_pin }) |maybe_pin| { if (maybe_pin) |_| {} else { - return MSPinsError; + return error.Pins; } } @@ -176,7 +178,7 @@ pub fn Stepper(comptime Driver: type) type { return self.microsteps; } - pub fn set_speed_profile(self: *Self, profile: Speed_Profile) void { + pub fn set_speed_profile(self: *Self, profile: SpeedProfile) void { self.profile = profile; } @@ -361,12 +363,12 @@ pub fn Stepper(comptime Driver: type) type { } // Testing -const TestGPIO = mdf.base.Digital_IO.Test_Device; -const TestTime = mdf.base.Clock_Device.Test_Device; +const Test_GPIO = mdf.base.Digital_IO.TestDevice; +const TestTime = mdf.base.ClockDevice.TestDevice; test "begin" { - var dp = TestGPIO.init(.output, .high); - var sp = TestGPIO.init(.output, .high); + var dp = Test_GPIO.init(.output, .high); + var sp = Test_GPIO.init(.output, .high); var ttd = TestTime.init(); var stepper = Stepper(A4988).init(.{ .dir_pin = dp.digital_io(), @@ -380,11 +382,11 @@ test "begin" { } test "A4988: set microstep with ms pins set" { - var dp = TestGPIO.init(.output, .high); - var sp = TestGPIO.init(.output, .high); - var ms1 = TestGPIO.init(.output, .high); - var ms2 = TestGPIO.init(.output, .high); - var ms3 = TestGPIO.init(.output, .high); + var dp = Test_GPIO.init(.output, .high); + var sp = Test_GPIO.init(.output, .high); + var ms1 = Test_GPIO.init(.output, .high); + var ms2 = Test_GPIO.init(.output, .high); + var ms3 = Test_GPIO.init(.output, .high); var ttd = TestTime.init(); var stepper = Stepper(A4988).init(.{ .dir_pin = dp.digital_io(), @@ -416,8 +418,8 @@ test "A4988: set microstep with ms pins set" { } test "A4988: set microstep without ms pins set" { - var dp = TestGPIO.init(.output, .high); - var sp = TestGPIO.init(.output, .high); + var dp = Test_GPIO.init(.output, .high); + var sp = Test_GPIO.init(.output, .high); var ttd = TestTime.init(); var stepper = Stepper(A4988).init(.{ .dir_pin = dp.digital_io(), @@ -425,7 +427,7 @@ test "A4988: set microstep without ms pins set" { .clock_device = ttd.clock_device(), }); const rv = stepper.set_microstep(1); - try std.testing.expectError(MSPinsError, rv); + try std.testing.expectError(error.Pins, rv); const tcs = .{ // arg vs. clamped result .{ 1, 1 }, @@ -442,15 +444,15 @@ test "A4988: set microstep without ms pins set" { const m = stepper.init_microstep(tc[0]); try std.testing.expectEqual(tc[1], m); } - try std.testing.expectError(MSPinsError, stepper.set_microstep(1)); + try std.testing.expectError(error.Pins, stepper.set_microstep(1)); } test "DRV8825: set microstep with ms pins set" { - var dp = TestGPIO.init(.output, .high); - var sp = TestGPIO.init(.output, .high); - var ms1 = TestGPIO.init(.output, .high); - var ms2 = TestGPIO.init(.output, .high); - var ms3 = TestGPIO.init(.output, .high); + var dp = Test_GPIO.init(.output, .high); + var sp = Test_GPIO.init(.output, .high); + var ms1 = Test_GPIO.init(.output, .high); + var ms2 = Test_GPIO.init(.output, .high); + var ms3 = Test_GPIO.init(.output, .high); var ttd = TestTime.init(); var stepper = Stepper(DRV8825).init(.{ .dir_pin = dp.digital_io(), @@ -482,8 +484,8 @@ test "DRV8825: set microstep with ms pins set" { } test "DRV8825: set microstep without ms pins set" { - var dp = TestGPIO.init(.output, .high); - var sp = TestGPIO.init(.output, .high); + var dp = Test_GPIO.init(.output, .high); + var sp = Test_GPIO.init(.output, .high); var ttd = TestTime.init(); var stepper = Stepper(DRV8825).init(.{ .dir_pin = dp.digital_io(), @@ -491,7 +493,7 @@ test "DRV8825: set microstep without ms pins set" { .clock_device = ttd.clock_device(), }); const rv = stepper.set_microstep(1); - try std.testing.expectError(MSPinsError, rv); + try std.testing.expectError(error.Pins, rv); const tcs = .{ // arg vs. clamped result .{ 1, 1 }, diff --git a/drivers/wireless/cyw43/bus.zig b/drivers/src/wireless/cyw43/bus.zig similarity index 92% rename from drivers/wireless/cyw43/bus.zig rename to drivers/src/wireless/cyw43/bus.zig index 79142eb9c..ef5768723 100644 --- a/drivers/wireless/cyw43/bus.zig +++ b/drivers/src/wireless/cyw43/bus.zig @@ -1,13 +1,13 @@ const std = @import("std"); -const mdf = @import("../../framework.zig"); +const mdf = @import("../../root.zig"); const consts = @import("consts.zig"); -const DigitalIO = mdf.base.Digital_IO; +const Digital_IO = mdf.base.Digital_IO; /// Callback for microsecond delays pub const delayus_callback = fn (delay: u32) void; /// SPI interface for CYW43 -pub const Cyw43_Spi = struct { +pub const CYW43_SPI = struct { const Self = @This(); ptr: *anyopaque, vtable: *const VTable, @@ -29,13 +29,13 @@ pub const Cyw43_Spi = struct { }; /// CYW43 bus controller (SPI + power management) -pub const Cyw43_Bus = struct { +pub const CYW43_Bus = struct { const Self = @This(); const log = std.log.scoped(.cyw43_bus); const TestPattern = 0x12345678; - pwr_pin: DigitalIO, - spi: *Cyw43_Spi, + pwr_pin: Digital_IO, + spi: *CYW43_SPI, internal_delay_ms: *const delayus_callback, backplane_window: u32 = 0xAAAA_AAAA, @@ -69,7 +69,7 @@ pub const Cyw43_Bus = struct { log.debug("0b{b}", .{@as(u8, @truncate(ctrl_reg_val))}); // Set 32-bit word length and keep default endianness: little endian - const setup_regs = Cyw43FirstFourRegs{ + const setup_regs = FirstFourRegs{ .ctrl = .{ .word_length = .word_32, .endianness = .little_endian, @@ -138,7 +138,7 @@ pub const Cyw43_Bus = struct { } fn readn(self: *Self, func: FuncType, addr: u17, len: u11) u32 { - const cmd = Cyw43Cmd{ .cmd = .read, .incr = .incremental, .func = func, .addr = addr, .len = len }; + const cmd = Cmd{ .cmd = .read, .incr = .incremental, .func = func, .addr = addr, .len = len }; var buff = [_]u32{0} ** 2; // if we are reading from the backplane, we need an extra word for the response delay const buff_len: usize = if (func == .backplane) 2 else 1; @@ -161,7 +161,7 @@ pub const Cyw43_Bus = struct { } fn writen(self: *Self, func: FuncType, addr: u17, value: u32, len: u11) void { - const cmd = Cyw43Cmd{ .cmd = .write, .incr = .incremental, .func = func, .addr = addr, .len = len }; + const cmd = Cmd{ .cmd = .write, .incr = .incremental, .func = func, .addr = addr, .len = len }; _ = self.spi.spi_write_blocking(&[_]u32{ @bitCast(cmd), value }); } @@ -188,7 +188,7 @@ pub const Cyw43_Bus = struct { self.backplane_set_window(current_addr); - const cmd = Cyw43Cmd{ .cmd = .read, .incr = .incremental, .func = .backplane, .addr = @truncate(window_offs), .len = @truncate(len) }; + const cmd = Cmd{ .cmd = .read, .incr = .incremental, .func = .backplane, .addr = @truncate(window_offs), .len = @truncate(len) }; // round `buf` to word boundary, add one extra word for the response delay const words_to_send = (len + 3) / 4 + 1; @@ -260,7 +260,7 @@ pub const Cyw43_Bus = struct { self.backplane_set_window(current_addr); - const cmd = Cyw43Cmd{ .cmd = .write, .incr = .incremental, .func = .backplane, .addr = @truncate(window_offs), .len = @truncate(len) }; + const cmd = Cmd{ .cmd = .write, .incr = .incremental, .func = .backplane, .addr = @truncate(window_offs), .len = @truncate(len) }; buf[0] = @bitCast(cmd); const words_to_send = (len + 3) / 4 + 1; @@ -313,7 +313,7 @@ pub const Cyw43_Bus = struct { } fn read32_swapped(self: *Self, func: FuncType, addr: u17) u32 { - const cmd = Cyw43Cmd{ .cmd = .read, .incr = .incremental, .func = func, .addr = addr, .len = 4 }; + const cmd = Cmd{ .cmd = .read, .incr = .incremental, .func = func, .addr = addr, .len = 4 }; const cmd_swapped = swap16(@bitCast(cmd)); var buff = [1]u32{0}; @@ -323,7 +323,7 @@ pub const Cyw43_Bus = struct { } fn write32_swapped(self: *Self, func: FuncType, addr: u17, value: u32) void { - const cmd = Cyw43Cmd{ .cmd = .write, .incr = .incremental, .func = func, .addr = addr, .len = 4 }; + const cmd = Cmd{ .cmd = .write, .incr = .incremental, .func = func, .addr = addr, .len = 4 }; var buff: [2]u32 = .{ swap16(@bitCast(cmd)), swap16(value) }; _ = self.spi.spi_write_blocking(&buff); @@ -343,7 +343,7 @@ pub const Cyw43_Bus = struct { /// Builds command word and performs SPI transaction. pub fn wlan_send(self: *Self, len: usize) void { const aligned_len = (len + 3) & ~@as(usize, 3); - const cmd = Cyw43Cmd{ + const cmd = Cmd{ .cmd = .write, .incr = .incremental, .func = .wlan, @@ -360,7 +360,7 @@ pub const Cyw43_Bus = struct { /// Receive WLAN packet. Returns slice of received data. pub fn wlan_recv(self: *Self, len: usize) []const u8 { const words = (len + 3) / 4; - const cmd = Cyw43Cmd{ + const cmd = Cmd{ .cmd = .read, .incr = .incremental, .func = .wlan, @@ -385,7 +385,7 @@ const IncrMode = enum(u1) { const FuncType = enum(u2) { bus = 0, backplane = 1, wlan = 2, bt = 3 }; -const Cyw43Cmd = packed struct(u32) { +const Cmd = packed struct(u32) { len: u11, addr: u17, func: FuncType = .bus, @@ -421,7 +421,7 @@ const StatusEnableReg = packed struct(u8) { reserved1: u6 = 0, }; -const Cyw43FirstFourRegs = packed struct(u32) { +const FirstFourRegs = packed struct(u32) { ctrl: CtrlReg, response_delay: ResponseDelay, status_enable: StatusEnableReg, diff --git a/drivers/wireless/cyw43/consts.zig b/drivers/src/wireless/cyw43/consts.zig similarity index 100% rename from drivers/wireless/cyw43/consts.zig rename to drivers/src/wireless/cyw43/consts.zig diff --git a/drivers/wireless/cyw43/cyw43.zig b/drivers/src/wireless/cyw43/cyw43.zig similarity index 100% rename from drivers/wireless/cyw43/cyw43.zig rename to drivers/src/wireless/cyw43/cyw43.zig diff --git a/drivers/wireless/cyw43/firmware/43439A0_7_95_61.bin b/drivers/src/wireless/cyw43/firmware/43439A0_7_95_61.bin similarity index 100% rename from drivers/wireless/cyw43/firmware/43439A0_7_95_61.bin rename to drivers/src/wireless/cyw43/firmware/43439A0_7_95_61.bin diff --git a/drivers/wireless/cyw43/firmware/43439A0_7_95_88.bin b/drivers/src/wireless/cyw43/firmware/43439A0_7_95_88.bin similarity index 100% rename from drivers/wireless/cyw43/firmware/43439A0_7_95_88.bin rename to drivers/src/wireless/cyw43/firmware/43439A0_7_95_88.bin diff --git a/drivers/wireless/cyw43/firmware/43439A0_btfw.bin b/drivers/src/wireless/cyw43/firmware/43439A0_btfw.bin similarity index 100% rename from drivers/wireless/cyw43/firmware/43439A0_btfw.bin rename to drivers/src/wireless/cyw43/firmware/43439A0_btfw.bin diff --git a/drivers/wireless/cyw43/firmware/43439A0_clm.bin b/drivers/src/wireless/cyw43/firmware/43439A0_clm.bin similarity index 100% rename from drivers/wireless/cyw43/firmware/43439A0_clm.bin rename to drivers/src/wireless/cyw43/firmware/43439A0_clm.bin diff --git a/drivers/wireless/cyw43/firmware/LICENSE-permissive-binary-license-1.0.txt b/drivers/src/wireless/cyw43/firmware/LICENSE-permissive-binary-license-1.0.txt similarity index 100% rename from drivers/wireless/cyw43/firmware/LICENSE-permissive-binary-license-1.0.txt rename to drivers/src/wireless/cyw43/firmware/LICENSE-permissive-binary-license-1.0.txt diff --git a/drivers/wireless/cyw43/firmware/README.md b/drivers/src/wireless/cyw43/firmware/README.md similarity index 100% rename from drivers/wireless/cyw43/firmware/README.md rename to drivers/src/wireless/cyw43/firmware/README.md diff --git a/drivers/wireless/cyw43/nvram.zig b/drivers/src/wireless/cyw43/nvram.zig similarity index 100% rename from drivers/wireless/cyw43/nvram.zig rename to drivers/src/wireless/cyw43/nvram.zig diff --git a/drivers/wireless/cyw43/runner.zig b/drivers/src/wireless/cyw43/runner.zig similarity index 99% rename from drivers/wireless/cyw43/runner.zig rename to drivers/src/wireless/cyw43/runner.zig index 8e41625bc..59d44b52b 100644 --- a/drivers/wireless/cyw43/runner.zig +++ b/drivers/src/wireless/cyw43/runner.zig @@ -7,7 +7,7 @@ const wifi_mod = @import("wifi.zig"); /// Callback for microsecond delays pub const delayus_callback = fn (delay: u32) void; -pub const Cyw43_Runner = struct { +pub const CYW43_Runner = struct { const Self = @This(); const log = std.log.scoped(.cyw43_runner); const chip_log = std.log.scoped(.cyw43_chip); diff --git a/drivers/wireless/cyw43/sdpcm.zig b/drivers/src/wireless/cyw43/sdpcm.zig similarity index 100% rename from drivers/wireless/cyw43/sdpcm.zig rename to drivers/src/wireless/cyw43/sdpcm.zig diff --git a/drivers/wireless/cyw43/wifi.zig b/drivers/src/wireless/cyw43/wifi.zig similarity index 100% rename from drivers/wireless/cyw43/wifi.zig rename to drivers/src/wireless/cyw43/wifi.zig diff --git a/drivers/wireless/cyw43439.zig b/drivers/src/wireless/cyw43439.zig similarity index 100% rename from drivers/wireless/cyw43439.zig rename to drivers/src/wireless/cyw43439.zig diff --git a/drivers/wireless/cyw43439/bus.zig b/drivers/src/wireless/cyw43439/bus.zig similarity index 98% rename from drivers/wireless/cyw43439/bus.zig rename to drivers/src/wireless/cyw43439/bus.zig index 474448d20..e58e8888f 100644 --- a/drivers/wireless/cyw43439/bus.zig +++ b/drivers/src/wireless/cyw43439/bus.zig @@ -5,7 +5,7 @@ const assert = std.debug.assert; const log = std.log.scoped(.cyw43_bus); -pub const Spi = struct { +pub const SPI = struct { ptr: *anyopaque, vtable: *const VTable, @@ -32,7 +32,7 @@ pub const Spi = struct { const Self = @This(); -spi: Spi, +spi: SPI, sleep_ms: *const fn (delay: u32) void, backplane_window: u32 = 0xAAAA_AAAA, @@ -99,9 +99,9 @@ pub fn init(self: *Self) !void { // Set interrupts { // Clear error interrupt bits - self.write_int(u16, .bus, reg.interrupt, @bitCast(Irq.clear)); + self.write_int(u16, .bus, reg.interrupt, @bitCast(IRQ.clear)); // Enable a selection of interrupts - self.write_int(u16, .bus, reg.interrupt_enable, @bitCast(Irq{ + self.write_int(u16, .bus, reg.interrupt_enable, @bitCast(IRQ{ .f2_f3_fifo_rd_underflow = true, .f2_f3_fifo_wr_overflow = true, .command_error = true, @@ -350,7 +350,7 @@ pub const reg = struct { }; // interrupt register and interrupt enable register bits -pub const Irq = packed struct { +pub const IRQ = packed struct { data_unavailable: bool = false, // Requested data not available; Clear by writing a "1" f2_f3_fifo_rd_underflow: bool = false, f2_f3_fifo_wr_overflow: bool = false, @@ -365,7 +365,7 @@ pub const Irq = packed struct { f2_intr: bool = false, f3_intr: bool = false, - const clear = Irq{ + const clear = IRQ{ .data_unavailable = true, .command_error = true, .data_error = true, diff --git a/drivers/wireless/cyw43439/ioctl.zig b/drivers/src/wireless/cyw43439/ioctl.zig similarity index 95% rename from drivers/wireless/cyw43439/ioctl.zig rename to drivers/src/wireless/cyw43439/ioctl.zig index 514aae773..a300a244f 100644 --- a/drivers/wireless/cyw43439/ioctl.zig +++ b/drivers/src/wireless/cyw43439/ioctl.zig @@ -26,7 +26,7 @@ pub const response_poll_interval = 10; // SDPCM (Serial Data Packet Communication Module) header // SDIO/SPI Bus Layer (SDPCM) header // ref: https://iosoft.blog/2022/12/06/picowi_part3/ -const SdpHeader = extern struct { +const SDP_Header = extern struct { len: u16, not_len: u16, /// Rx/Tx sequence number @@ -55,11 +55,11 @@ const SdpHeader = extern struct { flags: u4 = 0, }; - pub fn channel(sdp: SdpHeader) Chan { + pub fn channel(sdp: SDP_Header) Chan { return sdp.cf.chan; } - pub fn validate(sdp: SdpHeader, n: u16) !void { + pub fn validate(sdp: SDP_Header, n: u16) !void { if (sdp.len != n) { log.err("invalid reponse len actual: {} packet: {}", .{ sdp.len, n }); return error.Cyw43SdpInvalidBusLen; @@ -71,7 +71,7 @@ const SdpHeader = extern struct { } }; -const CdcHeader = extern struct { +const CDC_Header = extern struct { cmd: Cmd, outlen: u16, inlen: u16 = 0, @@ -79,7 +79,7 @@ const CdcHeader = extern struct { id: u16, status: u32 = 0, - pub fn status_ok(self: CdcHeader) bool { + pub fn status_ok(self: CDC_Header) bool { //dev/ apsta, ampdu_rx_factor commands are returing status 0xFFFFFFFB return self.status == 0 or self.status == 0xFFFFFFFB; } @@ -104,14 +104,14 @@ pub const Cmd = enum(u32) { _, }; -const BdcHeader = extern struct { +const BDC_Header = extern struct { flags: u8, priority: u8, flags2: u8, offset: u8, // Padding after bdc header where data or event bytes starts - fn padding(self: BdcHeader) usize { + fn padding(self: BDC_Header) usize { return @as(usize, self.offset) * 4; } }; @@ -124,7 +124,7 @@ const BdcHeader = extern struct { // - xx result data in the case of get_var control command // if chan == .event // - 4 bytes bdc header -// - xx bdc padding bytes (defined in BdcHeader.offset) +// - xx bdc padding bytes (defined in BDC_Header.offset) // - 73 bytes of EventPacket // - other event bytes // if chan == .data @@ -138,39 +138,39 @@ const BdcHeader = extern struct { pub const Response = struct { const Self = @This(); - sdp: SdpHeader, + sdp: SDP_Header, buffer: []const u8, pub fn init(buf: []const u8) !Self { - const sdp: SdpHeader = @bitCast(buf[0..@sizeOf(SdpHeader)].*); + const sdp: SDP_Header = @bitCast(buf[0..@sizeOf(SDP_Header)].*); try sdp.validate(@intCast(buf.len)); return .{ .sdp = sdp, - .buffer = buf[@sizeOf(SdpHeader)..], + .buffer = buf[@sizeOf(SDP_Header)..], }; } // Number of padding bytes after bus header before cdc/bdc header fn padding(self: Self) usize { - return self.sdp.hdrlen - @sizeOf(SdpHeader); + return self.sdp.hdrlen - @sizeOf(SDP_Header); } - pub fn cdc(self: Self) CdcHeader { + pub fn cdc(self: Self) CDC_Header { assert(self.sdp.channel() == .control); - return @bitCast(self.buffer[self.padding()..][0..@sizeOf(CdcHeader)].*); + return @bitCast(self.buffer[self.padding()..][0..@sizeOf(CDC_Header)].*); } - pub fn bdc(self: Self) BdcHeader { + pub fn bdc(self: Self) BDC_Header { assert(self.sdp.channel() != .control); - return @bitCast(self.buffer[self.padding()..][0..@sizeOf(BdcHeader)].*); + return @bitCast(self.buffer[self.padding()..][0..@sizeOf(BDC_Header)].*); } pub fn data(self: Self) []const u8 { const head: usize = self.padding() + switch (self.sdp.channel()) { - .control => @sizeOf(CdcHeader), - .event, .data => @sizeOf(BdcHeader) + self.bdc().padding(), + .control => @sizeOf(CDC_Header), + .event, .data => @sizeOf(BDC_Header) + self.bdc().padding(), }; - const tail = self.sdp.len - @sizeOf(SdpHeader); + const tail = self.sdp.len - @sizeOf(SDP_Header); if (head > tail) { return &.{}; } @@ -180,8 +180,8 @@ pub const Response = struct { // head position and length of the data in the buffer sent to init pub fn data_pos(self: Self) struct { usize, usize } { const head: usize = self.sdp.hdrlen + switch (self.sdp.channel()) { - .control => @sizeOf(CdcHeader), - .event, .data => @sizeOf(BdcHeader) + self.bdc().padding(), + .control => @sizeOf(CDC_Header), + .event, .data => @sizeOf(BDC_Header) + self.bdc().padding(), }; return .{ head, self.sdp.len - head }; } @@ -274,10 +274,10 @@ pub fn request( const name_len: usize = name.len + if (name.len > 0) @as(usize, 1) else @as(usize, 0); // length of name and data rounded to 4 bytes const payload_len: u16 = @intCast(((name_len + (if (data.len > 0 and data.len < 4) 4 else data.len) + 3) >> 2) * 4); - const header_len: u16 = @sizeOf(SdpHeader) + @sizeOf(CdcHeader); + const header_len: u16 = @sizeOf(SDP_Header) + @sizeOf(CDC_Header); const txlen: u16 = header_len + payload_len; - const sdp: SdpHeader = .{ + const sdp: SDP_Header = .{ .len = txlen, .not_len = ~txlen, .seq = tx_sequence, @@ -285,16 +285,16 @@ pub fn request( .chan = .control, .flags = 0, }, - .hdrlen = @sizeOf(SdpHeader), + .hdrlen = @sizeOf(SDP_Header), }; - buf[0..@sizeOf(SdpHeader)].* = @bitCast(sdp); - const cdc: CdcHeader = .{ + buf[0..@sizeOf(SDP_Header)].* = @bitCast(sdp); + const cdc: CDC_Header = .{ .cmd = cmd, .outlen = payload_len, .id = request_id, .flags = if (data.len > 0) 0x02 else 0, }; - buf[@sizeOf(SdpHeader)..][0..@sizeOf(CdcHeader)].* = @bitCast(cdc); + buf[@sizeOf(SDP_Header)..][0..@sizeOf(CDC_Header)].* = @bitCast(cdc); if (name_len > 0) { @memcpy(buf[header_len..][0..name.len], name); buf[header_len..][name.len] = 0; // sentinel @@ -312,9 +312,9 @@ pub fn request( pub const TxHeader = extern struct { const Self = @This(); - sdp: SdpHeader = mem.zeroes(SdpHeader), + sdp: SDP_Header = mem.zeroes(SDP_Header), _padding: u16 = 0, - bdc: BdcHeader = mem.zeroes(BdcHeader), + bdc: BDC_Header = mem.zeroes(BDC_Header), pub fn init(data_len: u16, tx_sequence: u8) Self { const txlen = @sizeOf(TxHeader) + data_len; @@ -327,7 +327,7 @@ pub const TxHeader = extern struct { .chan = .data, .flags = 0, }, - .hdrlen = @sizeOf(SdpHeader) + 2, + .hdrlen = @sizeOf(SDP_Header) + 2, }; self.bdc.flags = 0x20; return self; @@ -341,9 +341,9 @@ pub fn tx_header(data_len: u16, tx_sequence: u8) [tx_header_len]u8 { } comptime { - assert(@sizeOf(SdpHeader) == 12); - assert(@sizeOf(BdcHeader) == 4); - assert(@sizeOf(CdcHeader) == 16); + assert(@sizeOf(SDP_Header) == 12); + assert(@sizeOf(BDC_Header) == 4); + assert(@sizeOf(CDC_Header) == 16); assert(@sizeOf(EventPacket) == 72); assert(@sizeOf(TxHeader) == 18); } diff --git a/drivers/wireless/cyw43439/nvram.zig b/drivers/src/wireless/cyw43439/nvram.zig similarity index 100% rename from drivers/wireless/cyw43439/nvram.zig rename to drivers/src/wireless/cyw43439/nvram.zig diff --git a/drivers/wireless/cyw43439/wifi.zig b/drivers/src/wireless/cyw43439/wifi.zig similarity index 99% rename from drivers/wireless/cyw43439/wifi.zig rename to drivers/src/wireless/cyw43439/wifi.zig index 2a029a137..97707016c 100644 --- a/drivers/wireless/cyw43439/wifi.zig +++ b/drivers/src/wireless/cyw43439/wifi.zig @@ -118,7 +118,7 @@ pub fn init(self: *Self, opt: InitOptions) !void { { // Load Country Locale Matrix (CLM) const data = @embedFile("../cyw43/firmware/43439A0_clm.bin"); - const ClmLoadControl = extern struct { + const CLM_LoadControl = extern struct { flag: u16 = 0, typ: u16 = 2, len: u32 = 0, @@ -127,8 +127,8 @@ pub fn init(self: *Self, opt: InitOptions) !void { var nbytes: usize = 0; while (nbytes < data.len) { - const head_len = @sizeOf(ClmLoadControl); - var clr: ClmLoadControl = .{}; + const head_len = @sizeOf(CLM_LoadControl); + var clr: CLM_LoadControl = .{}; var chunk: [ioctl_request_bytes_len - 64]u8 = undefined; const n = @min(chunk.len - head_len, data.len - nbytes); clr.flag = 1 << 12 | (if (nbytes > 0) @as(u16, 0) else 2) | (if (nbytes + n >= data.len) @as(u16, 4) else 0); diff --git a/examples/espressif/esp/src/i2c_display_sh1106.zig b/examples/espressif/esp/src/i2c_display_sh1106.zig index 76989076c..250a05ea3 100644 --- a/examples/espressif/esp/src/i2c_display_sh1106.zig +++ b/examples/espressif/esp/src/i2c_display_sh1106.zig @@ -5,7 +5,7 @@ const SH1106 = microzig.drivers.display.SH1106; const esp = microzig.hal; const i2c = esp.i2c; const gpio = esp.gpio; -const I2C_Datagram_Device = esp.drivers.I2C_Datagram_Device; +const I2C_DatagramDevice = esp.drivers.I2C_DatagramDevice; const sleep_ms = esp.time.sleep_ms; var i2c0 = i2c.instance.num(0); @@ -46,11 +46,11 @@ pub fn main() !void { try i2c0.apply(400_000); // Create i2c datagram device - const i2c_device = I2C_Datagram_Device.init(i2c0, @enumFromInt(0x3C), null); + const i2c_device = I2C_DatagramDevice.init(i2c0, @enumFromInt(0x3C), null); // Pass i2c device to driver to create display instance const display_driver = SH1106(.{ .mode = .i2c, - .Datagram_Device = I2C_Datagram_Device, + .DatagramDevice = I2C_DatagramDevice, }); // Configure device diff --git a/examples/espressif/esp/src/ws2812_blinky.zig b/examples/espressif/esp/src/ws2812_blinky.zig index 19ffb22f8..58e5a2423 100644 --- a/examples/espressif/esp/src/ws2812_blinky.zig +++ b/examples/espressif/esp/src/ws2812_blinky.zig @@ -34,7 +34,7 @@ pub fn main() !void { var ws2812: WS2812(.{ .max_led_count = 1, - .Datagram_Device = hal.drivers.SPI_Device, + .DatagramDevice = hal.drivers.SPI_Device, }) = .init( spi_dev, hal.drivers.clock_device(), diff --git a/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig b/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig index edf2f532a..452a0d303 100644 --- a/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig +++ b/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig @@ -43,7 +43,7 @@ pub fn main() !void { try camera.set_refresh_rate(0b101); - const i2c_dd = rp2xxx.drivers.I2C_Datagram_Device.init(i2c0, @enumFromInt(0x3C), null); + const i2c_dd = rp2xxx.drivers.I2C_DatagramDevice.init(i2c0, @enumFromInt(0x3C), null); const lcd = try display.ssd1306.init(.i2c, i2c_dd, null); try lcd.clear_screen(false); diff --git a/examples/raspberrypi/rp2xxx/src/mlx90640_image.zig b/examples/raspberrypi/rp2xxx/src/mlx90640_image.zig index fdf628f68..5930aecf5 100644 --- a/examples/raspberrypi/rp2xxx/src/mlx90640_image.zig +++ b/examples/raspberrypi/rp2xxx/src/mlx90640_image.zig @@ -43,7 +43,7 @@ pub fn main() !void { try camera.set_refresh_rate(0b101); - const i2c_dd = rp2xxx.drivers.I2C_Datagram_Device.init(i2c0, @enumFromInt(0x3C), null); + const i2c_dd = rp2xxx.drivers.I2C_DatagramDevice.init(i2c0, @enumFromInt(0x3C), null); const lcd = try display.ssd1306.init(.i2c, i2c_dd, null); try lcd.clear_screen(false); diff --git a/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig b/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig index c55683084..8e903b206 100644 --- a/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig +++ b/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig @@ -34,7 +34,7 @@ pub fn main() void { rp2xxx.i2c.I2C.apply(i2c0, .{ .baud_rate = 400_000, .clock_config = rp2xxx.clock_config }); - const i2c_dd = rp2xxx.drivers.I2C_Datagram_Device.init(i2c0, @enumFromInt(0x3C), null); + const i2c_dd = rp2xxx.drivers.I2C_DatagramDevice.init(i2c0, @enumFromInt(0x3C), null); const lcd = microzig.drivers.display.ssd1306.init(.i2c, i2c_dd, null) catch unreachable; const print_val = four_rows ++ " WELCOME"; diff --git a/examples/stmicro/stm32/src/stm32f1xx/ssd1306.zig b/examples/stmicro/stm32/src/stm32f1xx/ssd1306.zig index 69c6f3f2d..3710da6bc 100644 --- a/examples/stmicro/stm32/src/stm32f1xx/ssd1306.zig +++ b/examples/stmicro/stm32/src/stm32f1xx/ssd1306.zig @@ -9,7 +9,7 @@ const drivers = microzig.drivers; const lcd_driver = drivers.display.SSD1306_I2C; const I2C = stm32.i2c; -const I2C_Datagram_Device = stm32.drivers.I2C_Datagram_Device; +const I2C_DatagramDevice = stm32.drivers.I2C_DatagramDevice; const uart = stm32.uart.UART.init(.USART1); const TX = gpio.Pin.from_port(.A, 9); @@ -33,7 +33,7 @@ comptime { _ = microzig.export_startup(); } -const i2c_device = I2C_Datagram_Device.init(i2c, I2C.Address.new(0x3c), null); +const i2c_device = I2C_DatagramDevice.init(i2c, I2C.Address.new(0x3c), null); const zig_img = [_]u8{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/examples/wch/ch32v/src/sharp_niceview.zig b/examples/wch/ch32v/src/sharp_niceview.zig index 2b7feb2e0..03622579c 100644 --- a/examples/wch/ch32v/src/sharp_niceview.zig +++ b/examples/wch/ch32v/src/sharp_niceview.zig @@ -113,7 +113,7 @@ pub fn main() !void { spi1.apply(spi_config); // Create SPI Datagram Device wrapper - const SPI_DD = hal.drivers.SPI_Datagram_Device(spi_config); + const SPI_DD = hal.drivers.SPI_DatagramDevice(spi_config); var spi_dev = SPI_DD.init( spi1, cs_pin, diff --git a/port/espressif/esp/src/hal/drivers.zig b/port/espressif/esp/src/hal/drivers.zig index d9b87d1ab..80376d459 100644 --- a/port/espressif/esp/src/hal/drivers.zig +++ b/port/espressif/esp/src/hal/drivers.zig @@ -9,20 +9,20 @@ const mdf = microzig.drivers; const drivers = microzig.drivers.base; const time = microzig.drivers.time; -const Datagram_Device = drivers.Datagram_Device; +const DatagramDevice = drivers.DatagramDevice; const Digital_IO = drivers.Digital_IO; -const Clock_Device = drivers.Clock_Device; +const ClockDevice = drivers.Clock_Device; const I2CError = drivers.I2C_Device.Error; const I2CAddress = drivers.I2C_Device.Address; /// /// A datagram device attached to an I²C bus. /// -pub const I2C_Datagram_Device = struct { - pub const ConnectError = Datagram_Device.ConnectError; +pub const I2C_DatagramDevice = struct { + pub const ConnectError = DatagramDevice.ConnectError; - pub const WriteError = Datagram_Device.WriteError; - pub const ReadError = Datagram_Device.ReadError; + pub const WriteError = DatagramDevice.WriteError; + pub const ReadError = DatagramDevice.ReadError; /// Selects which I²C bus should be used. bus: hal.i2c.I2C, @@ -33,7 +33,7 @@ pub const I2C_Datagram_Device = struct { /// Default timeout duration timeout: ?mdf.time.Duration = null, - pub fn init(bus: hal.i2c.I2C, address: hal.i2c.Address, timeout: ?mdf.time.Duration) I2C_Datagram_Device { + pub fn init(bus: hal.i2c.I2C, address: hal.i2c.Address, timeout: ?mdf.time.Duration) I2C_DatagramDevice { return .{ .bus = bus, .address = address, @@ -41,41 +41,41 @@ pub const I2C_Datagram_Device = struct { }; } - pub fn datagram_device(dev: *I2C_Datagram_Device) Datagram_Device { + pub fn datagram_device(dev: *I2C_DatagramDevice) DatagramDevice { return .{ .ptr = dev, .vtable = &vtable, }; } - pub fn connect(dev: I2C_Datagram_Device) ConnectError!void { + pub fn connect(dev: I2C_DatagramDevice) ConnectError!void { _ = dev; } - pub fn disconnect(dev: I2C_Datagram_Device) void { + pub fn disconnect(dev: I2C_DatagramDevice) void { _ = dev; } - pub fn write(dev: I2C_Datagram_Device, datagram: []const u8) !void { + pub fn write(dev: I2C_DatagramDevice, datagram: []const u8) !void { try dev.bus.write_blocking(dev.address, datagram, dev.timeout); } - pub fn writev(dev: I2C_Datagram_Device, datagrams: []const []const u8) !void { + pub fn writev(dev: I2C_DatagramDevice, datagrams: []const []const u8) !void { try dev.bus.writev_blocking(dev.address, datagrams, dev.timeout); } - pub fn read(dev: I2C_Datagram_Device, datagram: []u8) !usize { + pub fn read(dev: I2C_DatagramDevice, datagram: []u8) !usize { try dev.bus.read_blocking(dev.address, datagram, dev.timeout); return datagram.len; } - pub fn readv(dev: I2C_Datagram_Device, datagrams: []const []u8) !usize { + pub fn readv(dev: I2C_DatagramDevice, datagrams: []const []u8) !usize { try dev.bus.readv_blocking(dev.address, datagrams, dev.timeout); return microzig.utilities.SliceVector([]u8).init(datagrams).size(); } - const vtable = Datagram_Device.VTable{ + const vtable = DatagramDevice.VTable{ .connect_fn = connect_fn, .disconnect_fn = disconnect_fn, .writev_fn = writev_fn, @@ -93,7 +93,7 @@ pub const I2C_Datagram_Device = struct { } fn writev_fn(dd: *anyopaque, chunks: []const []const u8) WriteError!void { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.writev(chunks) catch |e| switch (e) { hal.i2c.Error.Timeout => WriteError.Timeout, @@ -102,7 +102,7 @@ pub const I2C_Datagram_Device = struct { } fn readv_fn(dd: *anyopaque, chunks: []const []u8) ReadError!usize { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.readv(chunks) catch |e| switch (e) { hal.i2c.Error.Timeout => WriteError.Timeout, @@ -243,10 +243,10 @@ pub const I2C_Device = struct { /// A datagram device attached to an SPI half duplex connection. /// pub const SPI_Device = struct { - pub const ConnectError = Datagram_Device.ConnectError; + pub const ConnectError = DatagramDevice.ConnectError; - pub const WriteError = Datagram_Device.WriteError; - pub const ReadError = Datagram_Device.ReadError; + pub const WriteError = DatagramDevice.WriteError; + pub const ReadError = DatagramDevice.ReadError; pub const ChipSelect = struct { pin: hal.gpio.Pin, @@ -275,7 +275,7 @@ pub const SPI_Device = struct { return dev; } - pub fn datagram_device(dev: *SPI_Device) Datagram_Device { + pub fn datagram_device(dev: *SPI_Device) DatagramDevice { return .{ .ptr = dev, .vtable = &vtable, @@ -334,7 +334,7 @@ pub const SPI_Device = struct { _ = try dev.readv(read_chunks); } - const vtable = Datagram_Device.VTable{ + const vtable = DatagramDevice.VTable{ .connect_fn = connect_fn, .disconnect_fn = disconnect_fn, .writev_fn = writev_fn, @@ -448,11 +448,11 @@ pub const GPIO_Device = struct { }; /// -/// Implementation of a `Clock_Device` that uses the HAL's `time` module. +/// Implementation of a `ClockDevice` that uses the HAL's `time` module. /// -pub fn clock_device() Clock_Device { +pub fn clock_device() ClockDevice { const S = struct { - const vtable: Clock_Device.VTable = .{ + const vtable: ClockDevice.VTable = .{ .get_time_since_boot = get_time_since_boot_fn, }; diff --git a/port/nordic/nrf5x/src/hal/drivers.zig b/port/nordic/nrf5x/src/hal/drivers.zig index f56034dc1..2bfd87d48 100644 --- a/port/nordic/nrf5x/src/hal/drivers.zig +++ b/port/nordic/nrf5x/src/hal/drivers.zig @@ -10,20 +10,19 @@ const mdf = microzig.drivers; const drivers = microzig.drivers.base; const time = microzig.drivers.time; -const Datagram_Device = drivers.Datagram_Device; +const DatagramDevice = drivers.DatagramDevice; const Stream_Device = drivers.Stream_Device; const Digital_IO = drivers.Digital_IO; -const Clock_Device = drivers.Clock_Device; const I2CError = drivers.I2C_Device.Error; const I2CAddress = drivers.I2C_Device.Address; /// /// A datagram device attached to an I²C bus. /// -pub const I2C_Datagram_Device = struct { - pub const ConnectError = Datagram_Device.ConnectError; - pub const WriteError = Datagram_Device.WriteError; - pub const ReadError = Datagram_Device.ReadError; +pub const I2C_DatagramDevice = struct { + pub const ConnectError = DatagramDevice.ConnectError; + pub const WriteError = DatagramDevice.WriteError; + pub const ReadError = DatagramDevice.ReadError; /// Selects I²C bus should be used. bus: hal.i2c.I2C, @@ -34,7 +33,7 @@ pub const I2C_Datagram_Device = struct { /// Default timeout duration timeout: ?mdf.time.Duration = null, - pub fn init(bus: hal.i2c.I2C, address: hal.i2c.Address, timeout: ?mdf.time.Duration) I2C_Datagram_Device { + pub fn init(bus: hal.i2c.I2C, address: hal.i2c.Address, timeout: ?mdf.time.Duration) I2C_DatagramDevice { return .{ .bus = bus, .address = address, @@ -42,48 +41,48 @@ pub const I2C_Datagram_Device = struct { }; } - pub fn datagram_device(dev: *I2C_Datagram_Device) Datagram_Device { + pub fn datagram_device(dev: *I2C_DatagramDevice) DatagramDevice { return .{ .ptr = dev, .vtable = &vtable, }; } - pub fn connect(dev: I2C_Datagram_Device) ConnectError!void { + pub fn connect(dev: I2C_DatagramDevice) ConnectError!void { _ = dev; } - pub fn disconnect(dev: I2C_Datagram_Device) void { + pub fn disconnect(dev: I2C_DatagramDevice) void { _ = dev; } - pub fn write(dev: I2C_Datagram_Device, datagram: []const u8) !void { + pub fn write(dev: I2C_DatagramDevice, datagram: []const u8) !void { try dev.bus.write_blocking(dev.address, datagram, dev.timeout); } - pub fn writev(dev: I2C_Datagram_Device, datagrams: []const []const u8) !void { + pub fn writev(dev: I2C_DatagramDevice, datagrams: []const []const u8) !void { try dev.bus.writev_blocking(dev.address, datagrams, dev.timeout); } - pub fn read(dev: I2C_Datagram_Device, datagram: []u8) !usize { + pub fn read(dev: I2C_DatagramDevice, datagram: []u8) !usize { try dev.bus.read_blocking(dev.address, datagram, dev.timeout); return datagram.len; } - pub fn readv(dev: I2C_Datagram_Device, datagrams: []const []u8) !usize { + pub fn readv(dev: I2C_DatagramDevice, datagrams: []const []u8) !usize { try dev.bus.readv_blocking(dev.address, datagrams, dev.timeout); return microzig.utilities.SliceVector([]u8).init(datagrams).size(); } pub fn writev_then_readv( - dev: I2C_Datagram_Device, + dev: I2C_DatagramDevice, write_chunks: []const []const u8, read_chunks: []const []u8, ) !void { try dev.bus.writev_then_readv_blocking(dev.address, write_chunks, read_chunks, null); } - const vtable = Datagram_Device.VTable{ + const vtable = DatagramDevice.VTable{ .connect_fn = null, .disconnect_fn = null, .writev_fn = writev_fn, @@ -92,7 +91,7 @@ pub const I2C_Datagram_Device = struct { }; fn writev_fn(dd: *anyopaque, chunks: []const []const u8) WriteError!void { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.writev(chunks) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, @@ -111,7 +110,7 @@ pub const I2C_Datagram_Device = struct { } fn readv_fn(dd: *anyopaque, chunks: []const []u8) ReadError!usize { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.readv(chunks) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, @@ -134,7 +133,7 @@ pub const I2C_Datagram_Device = struct { write_chunks: []const []const u8, read_chunks: []const []u8, ) (WriteError || ReadError)!void { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.writev_then_readv(write_chunks, read_chunks) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, @@ -254,14 +253,14 @@ pub const I2C_Device = struct { /// Implementation of a time device /// pub const ClockDevice = struct { - pub fn clock_device(td: *ClockDevice) Clock_Device { + pub fn clock_device(td: *ClockDevice) drivers.ClockDevice { _ = td; - return Clock_Device{ + return drivers.ClockDevice{ .ptr = undefined, .vtable = &vtable, }; } - const vtable = Clock_Device.VTable{ + const vtable = drivers.ClockDevice.VTable{ .get_time_since_boot = get_time_since_boot_fn, }; @@ -276,9 +275,9 @@ pub const ClockDevice = struct { /// A datagram device attached to an SPI bus. /// pub const SPI_Device = struct { - pub const ConnectError = Datagram_Device.ConnectError; - pub const WriteError = Datagram_Device.WriteError; - pub const ReadError = Datagram_Device.ReadError; + pub const ConnectError = DatagramDevice.ConnectError; + pub const WriteError = DatagramDevice.WriteError; + pub const ReadError = DatagramDevice.ReadError; pub const ChipSelect = struct { pin: hal.gpio.Pin, active_level: Digital_IO.State = .low, @@ -300,7 +299,7 @@ pub const SPI_Device = struct { return dev; } - pub fn datagram_device(dev: *SPI_Device) Datagram_Device { + pub fn datagram_device(dev: *SPI_Device) DatagramDevice { return .{ .ptr = dev, .vtable = &vtable, @@ -341,7 +340,7 @@ pub const SPI_Device = struct { return microzig.utilities.SliceVector([]u8).init(datagrams).size(); } - const vtable = Datagram_Device.VTable{ + const vtable = DatagramDevice.VTable{ .connect_fn = connect_fn, .disconnect_fn = disconnect_fn, .writev_fn = writev_fn, @@ -378,11 +377,11 @@ pub const SPI_Device = struct { }; /// -/// Implementation of a `Clock_Device` that uses the HAL's `time` module. +/// Implementation of a `ClockDevice` that uses the HAL's `time` module. /// -pub fn clock_device() Clock_Device { +pub fn clock_device() drivers.ClockDevice { const S = struct { - const vtable: Clock_Device.VTable = .{ + const vtable: drivers.ClockDevice.VTable = .{ .get_time_since_boot = get_time_since_boot_fn, }; diff --git a/port/raspberrypi/rp2xxx/src/hal/drivers.zig b/port/raspberrypi/rp2xxx/src/hal/drivers.zig index 4400af0d6..9e63d0dad 100644 --- a/port/raspberrypi/rp2xxx/src/hal/drivers.zig +++ b/port/raspberrypi/rp2xxx/src/hal/drivers.zig @@ -10,20 +10,20 @@ const mdf = microzig.drivers; const drivers = microzig.drivers.base; const time = microzig.drivers.time; -const Datagram_Device = drivers.Datagram_Device; +const DatagramDevice = drivers.DatagramDevice; const Stream_Device = drivers.Stream_Device; const Digital_IO = drivers.Digital_IO; -const Clock_Device = drivers.Clock_Device; +const ClockDevice = drivers.Clock_Device; const I2CError = drivers.I2C_Device.Error; const I2CAddress = drivers.I2C_Device.Address; /// /// A datagram device attached to an I²C bus. /// -pub const I2C_Datagram_Device = struct { - pub const ConnectError = Datagram_Device.ConnectError; - pub const WriteError = Datagram_Device.WriteError; - pub const ReadError = Datagram_Device.ReadError; +pub const I2C_DatagramDevice = struct { + pub const ConnectError = DatagramDevice.ConnectError; + pub const WriteError = DatagramDevice.WriteError; + pub const ReadError = DatagramDevice.ReadError; /// Selects which I²C bus should be used. bus: hal.i2c.I2C, @@ -34,7 +34,7 @@ pub const I2C_Datagram_Device = struct { /// Default timeout duration timeout: ?mdf.time.Duration = null, - pub fn init(bus: hal.i2c.I2C, address: I2CAddress, timeout: ?mdf.time.Duration) I2C_Datagram_Device { + pub fn init(bus: hal.i2c.I2C, address: I2CAddress, timeout: ?mdf.time.Duration) I2C_DatagramDevice { return .{ .bus = bus, .address = address, @@ -42,48 +42,48 @@ pub const I2C_Datagram_Device = struct { }; } - pub fn datagram_device(dev: *I2C_Datagram_Device) Datagram_Device { + pub fn datagram_device(dev: *I2C_DatagramDevice) DatagramDevice { return .{ .ptr = dev, .vtable = &vtable, }; } - pub fn connect(dev: I2C_Datagram_Device) ConnectError!void { + pub fn connect(dev: I2C_DatagramDevice) ConnectError!void { _ = dev; } - pub fn disconnect(dev: I2C_Datagram_Device) void { + pub fn disconnect(dev: I2C_DatagramDevice) void { _ = dev; } - pub fn write(dev: I2C_Datagram_Device, datagram: []const u8) !void { + pub fn write(dev: I2C_DatagramDevice, datagram: []const u8) !void { try dev.bus.write_blocking(dev.address, datagram, dev.timeout); } - pub fn writev(dev: I2C_Datagram_Device, datagrams: []const []const u8) !void { + pub fn writev(dev: I2C_DatagramDevice, datagrams: []const []const u8) !void { try dev.bus.writev_blocking(dev.address, datagrams, dev.timeout); } - pub fn read(dev: I2C_Datagram_Device, datagram: []u8) !usize { + pub fn read(dev: I2C_DatagramDevice, datagram: []u8) !usize { try dev.bus.read_blocking(dev.address, datagram, dev.timeout); return datagram.len; } - pub fn readv(dev: I2C_Datagram_Device, datagrams: []const []u8) !usize { + pub fn readv(dev: I2C_DatagramDevice, datagrams: []const []u8) !usize { try dev.bus.readv_blocking(dev.address, datagrams, dev.timeout); return microzig.utilities.SliceVector([]u8).init(datagrams).size(); } - pub fn write_then_read(dev: I2C_Datagram_Device, src: []const u8, dst: []u8) !void { + pub fn write_then_read(dev: I2C_DatagramDevice, src: []const u8, dst: []u8) !void { try dev.bus.write_then_read_blocking(dev.address, src, dst, dev.timeout); } - pub fn writev_then_readv(dev: I2C_Datagram_Device, write_chunks: []const []const u8, read_chunks: []const []u8) !void { + pub fn writev_then_readv(dev: I2C_DatagramDevice, write_chunks: []const []const u8, read_chunks: []const []u8) !void { try dev.bus.writev_then_readv_blocking(dev.address, write_chunks, read_chunks, dev.timeout); } - const vtable = Datagram_Device.VTable{ + const vtable = DatagramDevice.VTable{ .connect_fn = null, .disconnect_fn = null, .writev_fn = writev_fn, @@ -92,7 +92,7 @@ pub const I2C_Datagram_Device = struct { }; fn writev_fn(dd: *anyopaque, chunks: []const []const u8) WriteError!void { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.writev(chunks) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, @@ -111,7 +111,7 @@ pub const I2C_Datagram_Device = struct { } fn readv_fn(dd: *anyopaque, chunks: []const []u8) ReadError!usize { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.readv(chunks) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, @@ -134,7 +134,7 @@ pub const I2C_Datagram_Device = struct { write_chunks: []const []const u8, read_chunks: []const []u8, ) (WriteError || ReadError)!void { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.writev_then_readv(write_chunks, read_chunks) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, @@ -254,9 +254,9 @@ pub const I2C_Device = struct { /// A datagram device attached to an SPI bus. /// pub const SPI_Device = struct { - pub const ConnectError = Datagram_Device.ConnectError; - pub const WriteError = Datagram_Device.WriteError; - pub const ReadError = Datagram_Device.ReadError; + pub const ConnectError = DatagramDevice.ConnectError; + pub const WriteError = DatagramDevice.WriteError; + pub const ReadError = DatagramDevice.ReadError; bus: hal.spi.SPI, chip_select: ?ChipSelect = null, @@ -291,7 +291,7 @@ pub const SPI_Device = struct { return dev; } - pub fn datagram_device(dev: *SPI_Device) Datagram_Device { + pub fn datagram_device(dev: *SPI_Device) DatagramDevice { return .{ .ptr = dev, .vtable = &vtable, @@ -339,7 +339,7 @@ pub const SPI_Device = struct { return microzig.utilities.SliceVector([]u8).init(datagrams).size(); } - const vtable = Datagram_Device.VTable{ + const vtable = DatagramDevice.VTable{ .connect_fn = connect_fn, .disconnect_fn = disconnect_fn, .writev_fn = writev_fn, @@ -446,11 +446,11 @@ pub const GPIO_Device = struct { }; /// -/// Implementation of a `Clock_Device` that uses the HAL's `time` module. +/// Implementation of a `ClockDevice` that uses the HAL's `time` module. /// -pub fn clock_device() Clock_Device { +pub fn clock_device() ClockDevice { const S = struct { - const vtable: Clock_Device.VTable = .{ + const vtable: ClockDevice.VTable = .{ .get_time_since_boot = get_time_since_boot_fn, }; diff --git a/port/stmicro/stm32/src/hals/STM32F103/drivers.zig b/port/stmicro/stm32/src/hals/STM32F103/drivers.zig index 0c7ca844f..41ea286e2 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/drivers.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/drivers.zig @@ -4,7 +4,7 @@ const I2C = @import("i2c.zig"); const drivers = microzig.drivers.base; const Duration = microzig.drivers.time.Duration; -const Datagram_Device = drivers.Datagram_Device; +const DatagramDevice = drivers.DatagramDevice; const Stream_Device = drivers.Stream_Device; const Digital_IO = drivers.Digital_IO; @@ -13,10 +13,10 @@ const I2CError = drivers.I2C_Device.Error; // we will paper over it, but we should unify them. const I2CAddress = drivers.I2C_Device.Address; -pub const I2C_Datagram_Device = struct { - pub const ConnectError = Datagram_Device.ConnectError; - pub const WriteError = Datagram_Device.WriteError; - pub const ReadError = Datagram_Device.ReadError; +pub const I2C_DatagramDevice = struct { + pub const ConnectError = DatagramDevice.ConnectError; + pub const WriteError = DatagramDevice.WriteError; + pub const ReadError = DatagramDevice.ReadError; /// Selects I²C bus should be used. bus: I2C.I2C, @@ -27,7 +27,7 @@ pub const I2C_Datagram_Device = struct { /// Default timeout duration timeout: ?Duration, - pub fn init(bus: I2C.I2C, address: I2C.Address, timeout: ?Duration) I2C_Datagram_Device { + pub fn init(bus: I2C.I2C, address: I2C.Address, timeout: ?Duration) I2C_DatagramDevice { return .{ .bus = bus, .address = address, @@ -35,32 +35,32 @@ pub const I2C_Datagram_Device = struct { }; } - pub fn datagram_device(dev: *const I2C_Datagram_Device) Datagram_Device { + pub fn datagram_device(dev: *const I2C_DatagramDevice) DatagramDevice { return .{ .ptr = @constCast(dev), .vtable = &vtable, }; } - pub fn write(dev: I2C_Datagram_Device, datagram: []const u8, timeout: ?Duration) !void { + pub fn write(dev: I2C_DatagramDevice, datagram: []const u8, timeout: ?Duration) !void { try dev.bus.write_blocking(dev.address, datagram, timeout); } - pub fn writev(dev: I2C_Datagram_Device, datagrams: []const []const u8, timeout: ?Duration) !void { + pub fn writev(dev: I2C_DatagramDevice, datagrams: []const []const u8, timeout: ?Duration) !void { try dev.bus.writev_blocking(dev.address, datagrams, timeout); } - pub fn read(dev: I2C_Datagram_Device, datagram: []u8, timeout: ?Duration) !usize { + pub fn read(dev: I2C_DatagramDevice, datagram: []u8, timeout: ?Duration) !usize { try dev.bus.read_blocking(dev.address, datagram, timeout); return datagram.len; } - pub fn readv(dev: I2C_Datagram_Device, datagrams: []const []u8, timeout: ?Duration) !usize { + pub fn readv(dev: I2C_DatagramDevice, datagrams: []const []u8, timeout: ?Duration) !usize { try dev.bus.readv_blocking(dev.address, datagrams, timeout); return microzig.utilities.SliceVector([]u8).init(datagrams).size(); } - const vtable = Datagram_Device.VTable{ + const vtable = DatagramDevice.VTable{ .connect_fn = null, .disconnect_fn = null, .writev_fn = writev_fn, @@ -68,7 +68,7 @@ pub const I2C_Datagram_Device = struct { }; fn writev_fn(dd: *anyopaque, chunks: []const []const u8) WriteError!void { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.writev(chunks, dev.timeout) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, @@ -90,7 +90,7 @@ pub const I2C_Datagram_Device = struct { } fn readv_fn(dd: *anyopaque, chunks: []const []u8) ReadError!usize { - const dev: *I2C_Datagram_Device = @ptrCast(@alignCast(dd)); + const dev: *I2C_DatagramDevice = @ptrCast(@alignCast(dd)); return dev.readv(chunks, dev.timeout) catch |err| switch (err) { error.TargetAddressReserved, error.IllegalAddress, diff --git a/port/stmicro/stm32/src/hals/common/systick_timer.zig b/port/stmicro/stm32/src/hals/common/systick_timer.zig index 12dabb9bf..f42e6ff60 100644 --- a/port/stmicro/stm32/src/hals/common/systick_timer.zig +++ b/port/stmicro/stm32/src/hals/common/systick_timer.zig @@ -1,8 +1,8 @@ const microzig = @import("microzig"); const cpu_systick = @import("systick.zig"); -const Clock_Device = microzig.drivers.base.Clock_Device; +const ClockDevice = microzig.drivers.base.Clock_Device; const time = microzig.drivers.time; -const vtable: Clock_Device.VTable = .{ .get_time_since_boot = get_time_since_boot }; +const vtable: ClockDevice.VTable = .{ .get_time_since_boot = get_time_since_boot }; const Error = error{ CpuSystickNotInitialized, @@ -13,7 +13,7 @@ pub fn get_time_since_boot(_: *anyopaque) time.Absolute { return @enumFromInt(us); } -pub fn clock_device() Error!Clock_Device { +pub fn clock_device() Error!ClockDevice { if (!cpu_systick.is_initialized()) { return Error.CpuSystickNotInitialized; } diff --git a/port/wch/ch32v/src/hals/drivers.zig b/port/wch/ch32v/src/hals/drivers.zig index 795e63247..3a95e5eef 100644 --- a/port/wch/ch32v/src/hals/drivers.zig +++ b/port/wch/ch32v/src/hals/drivers.zig @@ -13,10 +13,10 @@ const time = microzig.hal.time; const drivers = microzig.drivers.base; -const Datagram_Device = drivers.Datagram_Device; +const DatagramDevice = drivers.DatagramDevice; const Stream_Device = drivers.Stream_Device; const Digital_IO = drivers.Digital_IO; -const Clock_Device = drivers.Clock_Device; +const ClockDevice = drivers.Clock_Device; const I2CError = drivers.I2C_Device.Error; const I2CAddress = drivers.I2C_Device.Address; @@ -210,7 +210,7 @@ pub const GPIO_Device = struct { /// Generic over SPI configuration to enable compile-time DMA optimization /// Manages chip select pin via connect/disconnect /// -pub fn SPI_Datagram_Device(comptime config: spi.Config) type { +pub fn SPI_DatagramDevice(comptime config: spi.Config) type { return struct { const Self = @This(); @@ -240,7 +240,7 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { }; } - pub fn datagram_device(dev: *Self) Datagram_Device { + pub fn datagram_device(dev: *Self) DatagramDevice { return .{ .ptr = dev, .vtable = &datagram_vtable, @@ -248,7 +248,7 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { } /// Connect to the device (assert chip select) - pub fn connect(dev: Self) Datagram_Device.ConnectError!void { + pub fn connect(dev: Self) DatagramDevice.ConnectError!void { dev.cs_pin.put(if (dev.cs_active_high) 1 else 0); } @@ -257,18 +257,18 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { dev.cs_pin.put(if (dev.cs_active_high) 0 else 1); } - pub fn writev(dev: Self, chunks: []const []const u8) Datagram_Device.WriteError!void { + pub fn writev(dev: Self, chunks: []const []const u8) DatagramDevice.WriteError!void { return dev.bus.writev_auto(config, chunks, dev.timeout) catch |err| switch (err) { - error.Timeout => Datagram_Device.WriteError.Timeout, - else => Datagram_Device.WriteError.IoError, + error.Timeout => DatagramDevice.WriteError.Timeout, + else => DatagramDevice.WriteError.IoError, }; } - pub fn readv(dev: Self, chunks: []const []u8) Datagram_Device.ReadError!usize { + pub fn readv(dev: Self, chunks: []const []u8) DatagramDevice.ReadError!usize { dev.bus.readv_auto(config, chunks, dev.timeout) catch |err| return switch (err) { - error.Timeout => Datagram_Device.ReadError.Timeout, - else => Datagram_Device.ReadError.IoError, + error.Timeout => DatagramDevice.ReadError.Timeout, + else => DatagramDevice.ReadError.IoError, }; // Calculate total bytes read var total: usize = 0; @@ -282,23 +282,23 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { dev: Self, write_chunks: []const []const u8, read_chunks: []const []u8, - ) Datagram_Device.ReadError!void { + ) DatagramDevice.ReadError!void { // Send write chunks dev.bus.writev_auto(config, write_chunks, dev.timeout) catch |err| return switch (err) { - error.Timeout => Datagram_Device.ReadError.Timeout, - else => Datagram_Device.ReadError.IoError, + error.Timeout => DatagramDevice.ReadError.Timeout, + else => DatagramDevice.ReadError.IoError, }; // Receive read chunks dev.bus.readv_auto(config, read_chunks, dev.timeout) catch |err| return switch (err) { - error.Timeout => Datagram_Device.ReadError.Timeout, - else => Datagram_Device.ReadError.IoError, + error.Timeout => DatagramDevice.ReadError.Timeout, + else => DatagramDevice.ReadError.IoError, }; } - const datagram_vtable = Datagram_Device.VTable{ + const datagram_vtable = DatagramDevice.VTable{ .connect_fn = connect_fn, .disconnect_fn = disconnect_fn, .writev_fn = writev_fn, @@ -306,7 +306,7 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { .writev_then_readv_fn = writev_then_readv_fn, }; - fn connect_fn(dd: *anyopaque) Datagram_Device.ConnectError!void { + fn connect_fn(dd: *anyopaque) DatagramDevice.ConnectError!void { const dev: *Self = @ptrCast(@alignCast(dd)); try dev.connect(); } @@ -316,12 +316,12 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { dev.disconnect(); } - fn writev_fn(dd: *anyopaque, chunks: []const []const u8) Datagram_Device.WriteError!void { + fn writev_fn(dd: *anyopaque, chunks: []const []const u8) DatagramDevice.WriteError!void { const dev: *Self = @ptrCast(@alignCast(dd)); return dev.writev(chunks); } - fn readv_fn(dd: *anyopaque, chunks: []const []u8) Datagram_Device.ReadError!usize { + fn readv_fn(dd: *anyopaque, chunks: []const []u8) DatagramDevice.ReadError!usize { const dev: *Self = @ptrCast(@alignCast(dd)); return dev.readv(chunks); } @@ -330,7 +330,7 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { dd: *anyopaque, write_chunks: []const []const u8, read_chunks: []const []u8, - ) Datagram_Device.ReadError!void { + ) DatagramDevice.ReadError!void { const dev: *Self = @ptrCast(@alignCast(dd)); return dev.writev_then_readv(write_chunks, read_chunks); } @@ -341,14 +341,14 @@ pub fn SPI_Datagram_Device(comptime config: spi.Config) type { /// Implementation of a time device /// pub const ClockDevice = struct { - pub fn clock_device(td: *ClockDevice) Clock_Device { + pub fn clock_device(td: *ClockDevice) ClockDevice { _ = td; - return Clock_Device{ + return ClockDevice{ .ptr = undefined, .vtable = &vtable, }; } - const vtable = Clock_Device.VTable{ + const vtable = ClockDevice.VTable{ .get_time_since_boot = get_time_since_boot_fn, }; @@ -360,11 +360,11 @@ pub const ClockDevice = struct { }; /// -/// Implementation of a `Clock_Device` that uses the HAL's `time` module. +/// Implementation of a `ClockDevice` that uses the HAL's `time` module. /// -pub fn clock_device() Clock_Device { +pub fn clock_device() ClockDevice { const S = struct { - const vtable: Clock_Device.VTable = .{ + const vtable: ClockDevice.VTable = .{ .get_time_since_boot = get_time_since_boot_fn, }; diff --git a/port/wch/ch32v/src/hals/spi.zig b/port/wch/ch32v/src/hals/spi.zig index 28f70a59f..22274ec79 100644 --- a/port/wch/ch32v/src/hals/spi.zig +++ b/port/wch/ch32v/src/hals/spi.zig @@ -24,7 +24,7 @@ //! Chip Select (CS) Pin: //! ==================== //! CS is NOT managed by this HAL - you must handle it manually. -//! For automatic CS management, use SPI_Datagram_Device wrapper (see drivers.zig). +//! For automatic CS management, use SPI_DatagramDevice wrapper (see drivers.zig). //! //! User must configure all pins before calling apply() //! @@ -114,7 +114,7 @@ pub const Config = struct { // NOTE: Chip select (CS) must be managed manually by the caller. // This SPI HAL is stateless and does not manage CS pins. - // See SPI_Datagram_Device in drivers.zig for automatic CS management. + // See SPI_DatagramDevice in drivers.zig for automatic CS management. }; pub const instance = struct { From 9d3beb9af263d233c67808008a2f1d8804ba4a94 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 13:39:52 -0700 Subject: [PATCH 21/61] Fix examples from driver cleanup --- drivers/README.md | 2 +- drivers/src/led/ws2812.zig | 2 +- drivers/src/sensor/MPU_6050.zig | 2 +- drivers/src/sensor/TLV493D.zig | 2 +- drivers/src/wireless/cyw43/cyw43.zig | 4 ++-- drivers/src/wireless/cyw43/runner.zig | 2 +- drivers/src/wireless/cyw43/sdpcm.zig | 4 ++-- drivers/src/wireless/cyw43/wifi.zig | 2 +- drivers/src/wireless/cyw43439.zig | 2 +- drivers/src/wireless/cyw43439/wifi.zig | 2 +- examples/espressif/esp/src/stepper_driver.zig | 4 ++-- .../rp2xxx/src/rp2040_only/hd44780.zig | 2 +- .../rp2xxx/src/rp2040_only/pcf8574.zig | 2 +- .../raspberrypi/rp2xxx/src/stepper_driver.zig | 4 ++-- .../stmicro/stm32/src/stm32f1xx/hd44780.zig | 2 +- port/espressif/esp/src/hal/drivers.zig | 2 +- port/raspberrypi/rp2xxx/src/hal/cyw43.zig | 18 ++++++++--------- .../rp2xxx/src/hal/cyw43_pio_spi.zig | 14 ++++++------- port/raspberrypi/rp2xxx/src/hal/drivers.zig | 20 +++++++++---------- .../stm32/src/hals/common/systick_timer.zig | 2 +- port/wch/ch32v/src/hals/drivers.zig | 12 +++++------ 21 files changed, 52 insertions(+), 54 deletions(-) diff --git a/drivers/README.md b/drivers/README.md index 3ecadd659..70d0781d7 100644 --- a/drivers/README.md +++ b/drivers/README.md @@ -849,7 +849,7 @@ This driver accepts multiple interface types: pub fn WS2812(options: struct { max_led_count: usize = 1, DatagramDevice: type = mdf.base.DatagramDevice, - ClockDevice: type = mdf.base.Clock_Device, + ClockDevice: type = mdf.base.ClockDevice, }) type { return struct { const Self = @This(); diff --git a/drivers/src/led/ws2812.zig b/drivers/src/led/ws2812.zig index 1ec267f59..d06b33aaf 100644 --- a/drivers/src/led/ws2812.zig +++ b/drivers/src/led/ws2812.zig @@ -8,7 +8,7 @@ const mdf = @import("../root.zig"); pub fn WS2812(options: struct { max_led_count: usize = 1, DatagramDevice: type = mdf.base.DatagramDevice, - ClockDevice: type = mdf.base.Clock_Device, + ClockDevice: type = mdf.base.ClockDevice, }) type { return struct { const Self = @This(); diff --git a/drivers/src/sensor/MPU_6050.zig b/drivers/src/sensor/MPU_6050.zig index 0e95df94f..7fb8e7ac6 100644 --- a/drivers/src/sensor/MPU_6050.zig +++ b/drivers/src/sensor/MPU_6050.zig @@ -24,7 +24,7 @@ const std = @import("std"); const mdf = @import("../root.zig"); const DatagramDevice = mdf.base.DatagramDevice; -const ClockDevice = mdf.base.Clock_Device; +const ClockDevice = mdf.base.ClockDevice; pub const MPU_6050 = struct { dev: DatagramDevice, diff --git a/drivers/src/sensor/TLV493D.zig b/drivers/src/sensor/TLV493D.zig index aa2ad9892..bd74b40f3 100644 --- a/drivers/src/sensor/TLV493D.zig +++ b/drivers/src/sensor/TLV493D.zig @@ -8,7 +8,7 @@ const std = @import("std"); const mdf = @import("../root.zig"); const I2C_Device = mdf.base.I2C_Device; -const ClockDevice = mdf.base.Clock_Device; +const ClockDevice = mdf.base.ClockDevice; /// TLV493D I2C addresses pub const ADDRESS0: I2C_Device.Address = @enumFromInt(0x1F); diff --git a/drivers/src/wireless/cyw43/cyw43.zig b/drivers/src/wireless/cyw43/cyw43.zig index 98cc4c47b..e741ead42 100644 --- a/drivers/src/wireless/cyw43/cyw43.zig +++ b/drivers/src/wireless/cyw43/cyw43.zig @@ -6,9 +6,9 @@ const bus = @import("bus.zig"); const runner_mod = @import("runner.zig"); const wifi_mod = @import("wifi.zig"); -pub const Runner = runner_mod.Cyw43_Runner; +pub const Runner = runner_mod.CYW43_Runner; pub const Wifi = wifi_mod.CYW43_Wifi; -pub const Bus = bus.Cyw43_Bus; +pub const Bus = bus.CYW43_Bus; pub const Security = wifi_mod.Security; pub const Event = wifi_mod.Event; diff --git a/drivers/src/wireless/cyw43/runner.zig b/drivers/src/wireless/cyw43/runner.zig index 59d44b52b..8701b2a30 100644 --- a/drivers/src/wireless/cyw43/runner.zig +++ b/drivers/src/wireless/cyw43/runner.zig @@ -13,7 +13,7 @@ pub const CYW43_Runner = struct { const chip_log = std.log.scoped(.cyw43_chip); chip_log_state: LogState = .{}, - bus: *bus.Cyw43_Bus, + bus: *bus.CYW43_Bus, internal_delay_ms: *const delayus_callback, // WiFi instance (initialized in init()) diff --git a/drivers/src/wireless/cyw43/sdpcm.zig b/drivers/src/wireless/cyw43/sdpcm.zig index f681b473c..33d1a7d13 100644 --- a/drivers/src/wireless/cyw43/sdpcm.zig +++ b/drivers/src/wireless/cyw43/sdpcm.zig @@ -154,7 +154,7 @@ pub const SDPCM = struct { NoCredit, }; - bus: *cyw43_bus.Cyw43_Bus, + bus: *cyw43_bus.CYW43_Bus, // Sequence numbers and flow control tx_seq: u8 = 0, @@ -173,7 +173,7 @@ pub const SDPCM = struct { last_control_status: u32 = 0, last_control_valid: bool = false, - pub fn init(bus: *cyw43_bus.Cyw43_Bus) SDPCM { + pub fn init(bus: *cyw43_bus.CYW43_Bus) SDPCM { return SDPCM{ .bus = bus, }; diff --git a/drivers/src/wireless/cyw43/wifi.zig b/drivers/src/wireless/cyw43/wifi.zig index e73c0d9e8..0882f2f6e 100644 --- a/drivers/src/wireless/cyw43/wifi.zig +++ b/drivers/src/wireless/cyw43/wifi.zig @@ -118,7 +118,7 @@ pub const CYW43_Wifi = struct { const clm_data = @embedFile("firmware/43439A0_clm.bin"); - pub fn init(bus: *cyw43_bus.Cyw43_Bus) CYW43_Wifi { + pub fn init(bus: *cyw43_bus.CYW43_Bus) CYW43_Wifi { return CYW43_Wifi{ .transport = sdpcm.SDPCM.init(bus), }; diff --git a/drivers/src/wireless/cyw43439.zig b/drivers/src/wireless/cyw43439.zig index 555572a16..6d6603bb4 100644 --- a/drivers/src/wireless/cyw43439.zig +++ b/drivers/src/wireless/cyw43439.zig @@ -18,7 +18,7 @@ mac: [6]u8 = @splat(0), pub fn init( self: *Self, - spi: Bus.Spi, + spi: Bus.SPI, sleep_ms: *const fn (delay: u32) void, opt: InitOptions, ) !void { diff --git a/drivers/src/wireless/cyw43439/wifi.zig b/drivers/src/wireless/cyw43439/wifi.zig index 97707016c..239afd4b6 100644 --- a/drivers/src/wireless/cyw43439/wifi.zig +++ b/drivers/src/wireless/cyw43439/wifi.zig @@ -93,7 +93,7 @@ pub fn init(self: *Self, opt: InitOptions) !void { chip.sdiod_core_base_address + sdio_int_host_mask, i_hmb_sw_mask, ); - bus.write_int(u16, .bus, Bus.reg.interrupt_enable, @bitCast(Bus.Irq{ .f2_packet_available = true })); + bus.write_int(u16, .bus, Bus.reg.interrupt_enable, @bitCast(Bus.IRQ{ .f2_packet_available = true })); } // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped." diff --git a/examples/espressif/esp/src/stepper_driver.zig b/examples/espressif/esp/src/stepper_driver.zig index e8e8e10a1..9a2aeea49 100644 --- a/examples/espressif/esp/src/stepper_driver.zig +++ b/examples/espressif/esp/src/stepper_driver.zig @@ -47,8 +47,8 @@ pub fn main() !void { try stepper.begin(100, 1); while (true) { - const linear_profile = A4988.Speed_Profile{ .linear_speed = .{ .accel = 200, .decel = 200 } }; - const constant_profile = A4988.Speed_Profile.constant_speed; + const linear_profile = A4988.SpeedProfile{ .linear_speed = .{ .accel = 200, .decel = 200 } }; + const constant_profile = A4988.SpeedProfile.constant_speed; // Try both constant and linear acceleration profiles inline for (.{ constant_profile, linear_profile }) |profile| { stepper.set_speed_profile( diff --git a/examples/raspberrypi/rp2xxx/src/rp2040_only/hd44780.zig b/examples/raspberrypi/rp2xxx/src/rp2040_only/hd44780.zig index 6f8fd080f..37385de08 100644 --- a/examples/raspberrypi/rp2xxx/src/rp2040_only/hd44780.zig +++ b/examples/raspberrypi/rp2xxx/src/rp2040_only/hd44780.zig @@ -1,7 +1,7 @@ const microzig = @import("microzig"); const drivers = microzig.drivers; const lcd = drivers.display.HD44780; -const PCF8574 = drivers.IO_expander.PCF8574; +const PCF8574 = drivers.io_expander.PCF8574; const rp2040 = microzig.hal; const i2c = rp2040.i2c; diff --git a/examples/raspberrypi/rp2xxx/src/rp2040_only/pcf8574.zig b/examples/raspberrypi/rp2xxx/src/rp2040_only/pcf8574.zig index e46459346..ab55d1dc5 100644 --- a/examples/raspberrypi/rp2xxx/src/rp2040_only/pcf8574.zig +++ b/examples/raspberrypi/rp2xxx/src/rp2040_only/pcf8574.zig @@ -1,7 +1,7 @@ const microzig = @import("microzig"); const drivers = microzig.drivers; -const PCF8574 = drivers.IO_expander.PCF8574; +const PCF8574 = drivers.io_expander.PCF8574; const State = drivers.base.Digital_IO.State; const rp2040 = microzig.hal; diff --git a/examples/raspberrypi/rp2xxx/src/stepper_driver.zig b/examples/raspberrypi/rp2xxx/src/stepper_driver.zig index efd9f4fcf..1a7753586 100644 --- a/examples/raspberrypi/rp2xxx/src/stepper_driver.zig +++ b/examples/raspberrypi/rp2xxx/src/stepper_driver.zig @@ -58,8 +58,8 @@ pub fn main() !void { try stepper.begin(100, 1); while (true) { - const linear_profile = A4988.Speed_Profile{ .linear_speed = .{ .accel = 200, .decel = 200 } }; - const constant_profile = A4988.Speed_Profile.constant_speed; + const linear_profile = A4988.SpeedProfile{ .linear_speed = .{ .accel = 200, .decel = 200 } }; + const constant_profile = A4988.SpeedProfile.constant_speed; // Try both constant and linear acceleration profiles inline for (.{ constant_profile, linear_profile }) |profile| { stepper.set_speed_profile( diff --git a/examples/stmicro/stm32/src/stm32f1xx/hd44780.zig b/examples/stmicro/stm32/src/stm32f1xx/hd44780.zig index 205a01a2a..fa076227d 100644 --- a/examples/stmicro/stm32/src/stm32f1xx/hd44780.zig +++ b/examples/stmicro/stm32/src/stm32f1xx/hd44780.zig @@ -7,7 +7,7 @@ const time = stm32.time; const drivers = microzig.drivers; const lcd = drivers.display.HD44780; -const PCF8574 = drivers.IO_expander.PCF8574; +const PCF8574 = drivers.io_expander.PCF8574; const I2C = stm32.i2c; const I2C_Device = stm32.drivers.I2C_Device; diff --git a/port/espressif/esp/src/hal/drivers.zig b/port/espressif/esp/src/hal/drivers.zig index 80376d459..183c5a687 100644 --- a/port/espressif/esp/src/hal/drivers.zig +++ b/port/espressif/esp/src/hal/drivers.zig @@ -11,7 +11,7 @@ const time = microzig.drivers.time; const DatagramDevice = drivers.DatagramDevice; const Digital_IO = drivers.Digital_IO; -const ClockDevice = drivers.Clock_Device; +const ClockDevice = drivers.ClockDevice; const I2CError = drivers.I2C_Device.Error; const I2CAddress = drivers.I2C_Device.Address; diff --git a/port/raspberrypi/rp2xxx/src/hal/cyw43.zig b/port/raspberrypi/rp2xxx/src/hal/cyw43.zig index 30779f72f..44558b82c 100644 --- a/port/raspberrypi/rp2xxx/src/hal/cyw43.zig +++ b/port/raspberrypi/rp2xxx/src/hal/cyw43.zig @@ -2,15 +2,15 @@ const std = @import("std"); const microzig = @import("microzig"); const hal = @import("../hal.zig"); -const Cyw43PioSpi = hal.cyw49_pio_spi.Cyw43PioSpi; -const Cyw43_Spi = microzig.drivers.wireless.Cyw43_Spi; -const Cyw43_Bus = microzig.drivers.wireless.Cyw43_Bus; -const Cyw43_Runner = microzig.drivers.wireless.Cyw43_Runner; +const CYW43_PIO_SPI = hal.cyw49_pio_spi.CYW43_PIO_SPI; +const CYW43_SPI = microzig.drivers.wireless.CYW43_SPI; +const CYW43_Bus = microzig.drivers.wireless.CYW43_Bus; +const CYW43_Runner = microzig.drivers.wireless.CYW43_Runner; const GPIO_Device = hal.drivers.GPIO_Device; pub const Wifi = microzig.drivers.wireless.cyw43.Wifi; pub const Security = microzig.drivers.wireless.cyw43.Security; -pub const Runner = Cyw43_Runner; +pub const Runner = CYW43_Runner; // See page 8 of the Raspberry Pi Pico 2 W Datasheet /// Pico 2 W pin configuration for CYW43 @@ -25,10 +25,10 @@ const pico2w_config = .{ /// Static state for the CYW43 device var state: struct { pwr_gpio: GPIO_Device = undefined, - pio_spi: Cyw43PioSpi = undefined, - spi: Cyw43_Spi = undefined, - bus: Cyw43_Bus = undefined, - runner: Cyw43_Runner = undefined, + pio_spi: CYW43_PIO_SPI = undefined, + spi: CYW43_SPI = undefined, + bus: CYW43_Bus = undefined, + runner: CYW43_Runner = undefined, initialized: bool = false, } = .{}; diff --git a/port/raspberrypi/rp2xxx/src/hal/cyw43_pio_spi.zig b/port/raspberrypi/rp2xxx/src/hal/cyw43_pio_spi.zig index 81c16e348..3ab95dd2c 100644 --- a/port/raspberrypi/rp2xxx/src/hal/cyw43_pio_spi.zig +++ b/port/raspberrypi/rp2xxx/src/hal/cyw43_pio_spi.zig @@ -4,7 +4,7 @@ const std = @import("std"); const microzig = @import("microzig"); const hal = @import("../hal.zig"); -const Cyw43_Spi = microzig.drivers.wireless.Cyw43_Spi; +const CYW43_SPI = microzig.drivers.wireless.CYW43_SPI; const chip = microzig.hal.compatibility.chip; @@ -38,14 +38,14 @@ const cyw43spi_program = blk: { , .{}).get_program_by_name("cyw43spi"); }; -pub const Cyw43PioSpi_Config = struct { +pub const CYW43_PIO_SPI_Config = struct { pio: hal.pio.Pio, cs_pin: hal.gpio.Pin, io_pin: hal.gpio.Pin, clk_pin: hal.gpio.Pin, }; -pub fn init(config: Cyw43PioSpi_Config) !Cyw43PioSpi { +pub fn init(config: CYW43_PIO_SPI_Config) !CYW43_PIO_SPI { const sm = try config.pio.claim_unused_state_machine(); // Chip select pin setup @@ -102,7 +102,7 @@ pub fn init(config: Cyw43PioSpi_Config) !Cyw43PioSpi { }; } -pub const Cyw43PioSpi = struct { +pub const CYW43_PIO_SPI = struct { const Self = @This(); pio: hal.pio.Pio, @@ -233,15 +233,15 @@ pub const Cyw43PioSpi = struct { return @enumFromInt(@intFromEnum(self.pio) * @as(u6, 8) + @intFromEnum(self.sm) + 4); } - /// Cyw43_Spi interface implementation - pub fn cyw43_spi(self: *Self) Cyw43_Spi { + /// CYW43_SPI interface implementation + pub fn cyw43_spi(self: *Self) CYW43_SPI { return .{ .ptr = self, .vtable = &vtable, }; } - const vtable = Cyw43_Spi.VTable{ + const vtable = CYW43_SPI.VTable{ .spi_read_blocking_fn = spi_read_blocking_fn, .spi_write_blocking_fn = spi_write_blocking_fn, }; diff --git a/port/raspberrypi/rp2xxx/src/hal/drivers.zig b/port/raspberrypi/rp2xxx/src/hal/drivers.zig index 9e63d0dad..18ffcd4f2 100644 --- a/port/raspberrypi/rp2xxx/src/hal/drivers.zig +++ b/port/raspberrypi/rp2xxx/src/hal/drivers.zig @@ -13,7 +13,7 @@ const time = microzig.drivers.time; const DatagramDevice = drivers.DatagramDevice; const Stream_Device = drivers.Stream_Device; const Digital_IO = drivers.Digital_IO; -const ClockDevice = drivers.Clock_Device; +const ClockDevice = drivers.ClockDevice; const I2CError = drivers.I2C_Device.Error; const I2CAddress = drivers.I2C_Device.Address; @@ -465,13 +465,13 @@ pub fn clock_device() ClockDevice { }; } -const Cyw43PioSpi = microzig.hal.cyw49_pio_spi.Cyw43PioSpi; -const Cyw43_Spi = microzig.drivers.wireless.Cyw43_Spi; -const Cyw43_Bus = microzig.drivers.wireless.Cyw43_Bus; -const Cyw43_Runner = microzig.drivers.wireless.Cyw43_Runner; +const CYW43_PIO_SPI = microzig.hal.cyw49_pio_spi.CYW43_PIO_SPI; +const CYW43_SPI = microzig.drivers.wireless.CYW43_SPI; +const CYW43_Bus = microzig.drivers.wireless.CYW43_Bus; +const CYW43_Runner = microzig.drivers.wireless.CYW43_Runner; pub const CYW43_Pio_Device_Config = struct { - spi: hal.cyw49_pio_spi.Cyw43PioSpi_Config, + spi: hal.cyw49_pio_spi.CYW43_PIO_SPI_Config, pwr_pin: hal.gpio.Pin, }; @@ -479,10 +479,10 @@ pub const CYW43_Pio_Device_Config = struct { pub const CYW43_Pio_Device = struct { const Self = @This(); pwr_pin: GPIO_Device = undefined, - cyw43_pio_spi: Cyw43PioSpi = undefined, - cyw43_spi: Cyw43_Spi = undefined, - cyw43_bus: Cyw43_Bus = undefined, - cyw43_runner: Cyw43_Runner = undefined, + cyw43_pio_spi: CYW43_PIO_SPI = undefined, + cyw43_spi: CYW43_SPI = undefined, + cyw43_bus: CYW43_Bus = undefined, + cyw43_runner: CYW43_Runner = undefined, pub fn init(self: *Self, config: CYW43_Pio_Device_Config) !void { std.log.info("before gpio init", .{}); diff --git a/port/stmicro/stm32/src/hals/common/systick_timer.zig b/port/stmicro/stm32/src/hals/common/systick_timer.zig index f42e6ff60..4f08bde63 100644 --- a/port/stmicro/stm32/src/hals/common/systick_timer.zig +++ b/port/stmicro/stm32/src/hals/common/systick_timer.zig @@ -1,6 +1,6 @@ const microzig = @import("microzig"); const cpu_systick = @import("systick.zig"); -const ClockDevice = microzig.drivers.base.Clock_Device; +const ClockDevice = microzig.drivers.base.ClockDevice; const time = microzig.drivers.time; const vtable: ClockDevice.VTable = .{ .get_time_since_boot = get_time_since_boot }; diff --git a/port/wch/ch32v/src/hals/drivers.zig b/port/wch/ch32v/src/hals/drivers.zig index 3a95e5eef..6dfa419b6 100644 --- a/port/wch/ch32v/src/hals/drivers.zig +++ b/port/wch/ch32v/src/hals/drivers.zig @@ -16,7 +16,6 @@ const drivers = microzig.drivers.base; const DatagramDevice = drivers.DatagramDevice; const Stream_Device = drivers.Stream_Device; const Digital_IO = drivers.Digital_IO; -const ClockDevice = drivers.Clock_Device; const I2CError = drivers.I2C_Device.Error; const I2CAddress = drivers.I2C_Device.Address; @@ -341,16 +340,15 @@ pub fn SPI_DatagramDevice(comptime config: spi.Config) type { /// Implementation of a time device /// pub const ClockDevice = struct { - pub fn clock_device(td: *ClockDevice) ClockDevice { + pub fn clock_device(td: *ClockDevice) drivers.ClockDevice { _ = td; - return ClockDevice{ + return drivers.ClockDevice{ .ptr = undefined, - .vtable = &vtable, + .vtable = &.{ + .get_time_since_boot = get_time_since_boot_fn, + }, }; } - const vtable = ClockDevice.VTable{ - .get_time_since_boot = get_time_since_boot_fn, - }; fn get_time_since_boot_fn(td: *anyopaque) time.Absolute { _ = td; From 79d1d481795e3e376810f5472965696462d45776 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 14:11:31 -0700 Subject: [PATCH 22/61] Some CI updates --- .github/workflows/ci.yml | 25 ------------------- .github/workflows/sim-aviron.yml | 2 +- .github/workflows/unused-imports.yml | 2 +- core/src/mmio.zig | 2 +- port/stmicro/stm32/src/hals/common/i2c_v2.zig | 3 +-- 5 files changed, 4 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f68496cf..1957d769e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -250,28 +250,3 @@ jobs: - name: Build Website run: zig build working-directory: website - - dry-run-packaging: - name: Dry Run Packaging - continue-on-error: true - runs-on: macos-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Zig - uses: mlugg/setup-zig@v2 - with: - version: ${{ env.ZIG_VERSION }} - - name: Dry Run Packaging - run: | - MICROZIG_VERSION=$(zig build package -- get-version) - echo microzig version: $MICROZIG_VERSION - zig build package -- http://localhost:8000 - python3 -m http.server --directory boxzer-out & - sleep 5 - - cd tools/package-test - zig fetch --save=microzig http://localhost:8000/${MICROZIG_VERSION}/microzig.tar.gz - zig build -Doptimize=ReleaseSmall - - jobs -p | xargs kill diff --git a/.github/workflows/sim-aviron.yml b/.github/workflows/sim-aviron.yml index 053513a34..e0d369ef6 100644 --- a/.github/workflows/sim-aviron.yml +++ b/.github/workflows/sim-aviron.yml @@ -7,8 +7,8 @@ on: jobs: build: + if: false # avr is broken on 0.16.0 runs-on: ${{ matrix.os }} - strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] diff --git a/.github/workflows/unused-imports.yml b/.github/workflows/unused-imports.yml index cee1d7837..426e92af6 100644 --- a/.github/workflows/unused-imports.yml +++ b/.github/workflows/unused-imports.yml @@ -25,7 +25,7 @@ jobs: - name: Build zigimports run: | - git clone --depth 1 --revision 837804f1a677578bca7c5e028baf25684b85e6b4 https://github.com/tusharsadhwani/zigimports.git /tmp/zigimports + git clone --depth 1 --revision 0c56cb27d932f69e572fb1247213075624011f7f https://github.com/tusharsadhwani/zigimports.git /tmp/zigimports cd /tmp/zigimports zig build --release=safe # Binary is named zigimports--, find and symlink it diff --git a/core/src/mmio.zig b/core/src/mmio.zig index 98c08579a..689f32b3d 100644 --- a/core/src/mmio.zig +++ b/core/src/mmio.zig @@ -68,7 +68,7 @@ pub fn Mmio(comptime PackedT: type) type { const U = enum_info.tag_type; @field(val, field_name) = @as(FieldType, @enumFromInt(@as(U, @intFromEnum(@field(val, field_name))) ^ - @as(U, @intFromEnum(@as(FieldType, value))))); + @as(U, @intFromEnum(@as(FieldType, value))))); }, else => |T| { @compileError("unsupported register field type '" ++ @typeName(T) ++ "'"); diff --git a/port/stmicro/stm32/src/hals/common/i2c_v2.zig b/port/stmicro/stm32/src/hals/common/i2c_v2.zig index 79951c469..8ea27cb0d 100644 --- a/port/stmicro/stm32/src/hals/common/i2c_v2.zig +++ b/port/stmicro/stm32/src/hals/common/i2c_v2.zig @@ -30,8 +30,7 @@ const TimingSpec_Standard = .{ .t_min_af = 0.05, }; -const TIMINGR = blk: for (@typeInfo(I2C_Peripherals).@"struct".fields) |field| -{ +const TIMINGR = blk: for (@typeInfo(I2C_Peripherals).@"struct".fields) |field| { if (std.mem.eql(u8, "TIMINGR", field.name)) { break :blk field.type; } From 3fa0be42a0fcb654fb98bfe14316a44aa5c97dd6 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 14:42:46 -0700 Subject: [PATCH 23/61] Update zine --- website/build.zig.zon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/build.zig.zon b/website/build.zig.zon index 12a21d013..98484bde0 100644 --- a/website/build.zig.zon +++ b/website/build.zig.zon @@ -13,8 +13,8 @@ }, .dependencies = .{ .zine = .{ - .url = "git+https://github.com/kristoff-it/zine#b96e930630f8237aa4927fe14b9cb227061155d3", - .hash = "zine-0.11.1-ou6nIBB5FgAaYePTyiT2__fkGVNfImMOnpc_xKNXsYpF", + .url = "git+https://github.com/kristoff-it/zine#a16c9f1d3f3166337da47fda2de0f4addc719b92", + .hash = "zine-0.11.2-ou6nIARkLQF8Kl5xN7pmSCun5lNjZvJOpQaug8--F2m2", }, }, } From 8b1511d8fc1a78e5b493353edb047c41e6437d79 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 14:50:26 -0700 Subject: [PATCH 24/61] Fix foundation libc CI --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1957d769e..b2a74af5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -215,7 +215,7 @@ jobs: working-directory: examples/${{ matrix.example_dir }} validate-foundation-libc: - name: Validate Foundation Libc + name: Test Foundation Libc continue-on-error: true runs-on: ${{ matrix.os }} strategy: @@ -228,10 +228,10 @@ jobs: uses: mlugg/setup-zig@v2 with: version: ${{ env.ZIG_VERSION }} - - name: Generate and validate packages + - name: Generate and test packages working-directory: modules/foundation-libc run: | - zig build validate + zig build test build-website: name: Build Website From 8fc2d6a9f74554865c4398c90d60c51fb2e2fbaa Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 15:00:29 -0700 Subject: [PATCH 25/61] Only build website on linux --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2a74af5f..30ad701e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -239,7 +239,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, windows-latest] + os: [ubuntu-latest] steps: - name: Checkout uses: actions/checkout@v4 From c2d50e2b9b7e499e55d019841844440d36c5032d Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 16:34:35 -0700 Subject: [PATCH 26/61] Fix foundation-libc CI --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30ad701e2..bd75e4802 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -216,6 +216,7 @@ jobs: validate-foundation-libc: name: Test Foundation Libc + if: false # TODO: investigate libc issues on 0.16.0 continue-on-error: true runs-on: ${{ matrix.os }} strategy: @@ -229,7 +230,7 @@ jobs: with: version: ${{ env.ZIG_VERSION }} - name: Generate and test packages - working-directory: modules/foundation-libc + working-directory: modules/foundation-libc/test run: | zig build test From f8f884317cf531d660c1afb0c50a5dbd9f43d160 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 16:37:19 -0700 Subject: [PATCH 27/61] Add workaround --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd75e4802..f79ddda77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} steps: + - run: mkdir -p ~/.cache/zig - name: Checkout uses: actions/checkout@v4 - name: Setup Zig From 2398c23368dbda83f1be54d1de972af2a5cc0d1a Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 16:46:20 -0700 Subject: [PATCH 28/61] check cache dir --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f79ddda77..ba7b1cf3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - run: mkdir -p ~/.cache/zig + - run: zig env - name: Checkout uses: actions/checkout@v4 - name: Setup Zig From 631cabc8b8b3c94f9351dc885a0da67187e8a87d Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 16:51:46 -0700 Subject: [PATCH 29/61] try again --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba7b1cf3e..a5e24d462 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,13 +31,14 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - run: zig env - name: Checkout uses: actions/checkout@v4 - name: Setup Zig uses: mlugg/setup-zig@v2 with: version: ${{ env.ZIG_VERSION }} + - run: zig env + - run: mkdir -p ~/.cache/zig - name: Unit Test Regz run: zig build test working-directory: tools/regz From fa4e701c9f45e3523939f741d5707d2186cf73a9 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 18:13:39 -0700 Subject: [PATCH 30/61] try again --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5e24d462..e2859c952 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,8 @@ jobs: with: version: ${{ env.ZIG_VERSION }} - run: zig env - - run: mkdir -p ~/.cache/zig + - run: echo $ZIG_GLOBAL_CACHE_DIR + - run: mkdir -p $ZIG_GLOBAL_CACHE_DIR - name: Unit Test Regz run: zig build test working-directory: tools/regz From 7cf007da8c4801031a02f9e12851ef9f3d269b24 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 18:39:13 -0700 Subject: [PATCH 31/61] try again --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2859c952..29b2b5586 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,8 @@ jobs: - run: zig env - run: echo $ZIG_GLOBAL_CACHE_DIR - run: mkdir -p $ZIG_GLOBAL_CACHE_DIR + - run: echo $HOME/.cache/zig + - run: mkdir -p $HOME/.cache/zig - name: Unit Test Regz run: zig build test working-directory: tools/regz From d8f85c2608803b5a523dc6ab06935b6cee626c7d Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 18:46:47 -0700 Subject: [PATCH 32/61] Skip over 0.16.0 to master --- .github/workflows/ci.yml | 6 +++--- .github/workflows/deploy.yml | 2 +- .github/workflows/drivers.yaml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-github-pages.yml | 2 +- .github/workflows/sim-aviron.yml | 4 ++-- .github/workflows/unused-imports.yml | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29b2b5586..8e60db261 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: env: - ZIG_VERSION: 0.16.0 + ZIG_VERSION: master jobs: formatting-check: @@ -221,7 +221,7 @@ jobs: validate-foundation-libc: name: Test Foundation Libc - if: false # TODO: investigate libc issues on 0.16.0 + if: false # TODO: investigate libc issues on master continue-on-error: true runs-on: ${{ matrix.os }} strategy: @@ -252,7 +252,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: master - name: Build Website run: zig build working-directory: website diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ff6c32d79..d36c80ccb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: master - name: Extract version run: echo "MICROZIG_VERSION=$(zig build package -- get-version)" >> $GITHUB_ENV diff --git a/.github/workflows/drivers.yaml b/.github/workflows/drivers.yaml index b414f77a9..d60e59dd6 100644 --- a/.github/workflows/drivers.yaml +++ b/.github/workflows/drivers.yaml @@ -20,7 +20,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: master - name: Run Test Suite working-directory: drivers diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b5873d59c..781df4bfe 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: master # Build linter from trusted base branch code - name: Build linter diff --git a/.github/workflows/publish-github-pages.yml b/.github/workflows/publish-github-pages.yml index ed646331f..a58d2dcd4 100644 --- a/.github/workflows/publish-github-pages.yml +++ b/.github/workflows/publish-github-pages.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: master - name: Download and install GitHub CLI run: | diff --git a/.github/workflows/sim-aviron.yml b/.github/workflows/sim-aviron.yml index e0d369ef6..d5c58a9ef 100644 --- a/.github/workflows/sim-aviron.yml +++ b/.github/workflows/sim-aviron.yml @@ -7,7 +7,7 @@ on: jobs: build: - if: false # avr is broken on 0.16.0 + if: false # avr is broken on master runs-on: ${{ matrix.os }} strategy: matrix: @@ -19,7 +19,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: master - name: Build working-directory: sim/aviron diff --git a/.github/workflows/unused-imports.yml b/.github/workflows/unused-imports.yml index 426e92af6..2bda6f225 100644 --- a/.github/workflows/unused-imports.yml +++ b/.github/workflows/unused-imports.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.16.0 + version: master - name: Build zigimports run: | From a5d57fdd8e41dbacb414125e0c4c8a5cfff8097b Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Thu, 28 May 2026 23:08:07 -0700 Subject: [PATCH 33/61] most of the **'s to @splat --- core/src/concurrency.zig | 2 +- core/src/cpus/msp430.zig | 4 ++-- drivers/src/wireless/cyw43/bus.zig | 2 +- drivers/src/wireless/cyw43/wifi.zig | 8 ++++---- .../raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig | 2 +- examples/stmicro/stm32/src/stm32f1xx/advanced_adc.zig | 2 +- examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig | 2 +- examples/wch/ch32v/src/dma.zig | 4 ++-- modules/bounded-array/src/bounded_array.zig | 2 +- .../stm32/src/hals/STM32F103/usb_internals/usb_ll.zig | 2 +- sim/aviron/src/lib/Cpu.zig | 4 ++-- sim/aviron/src/lib/bus.zig | 4 ++-- sim/aviron/src/lib/util/hexdump.zig | 2 +- sim/aviron/tools/generate_tables.zig | 2 +- tools/sorcerer/src/RegzWindow.zig | 2 +- tools/sorcerer/src/main.zig | 6 +++--- 16 files changed, 25 insertions(+), 25 deletions(-) diff --git a/core/src/concurrency.zig b/core/src/concurrency.zig index 0e7369acd..cdcc7b746 100644 --- a/core/src/concurrency.zig +++ b/core/src/concurrency.zig @@ -18,7 +18,7 @@ pub fn AtomicStaticBitSet(comptime size: usize) type { const Bit = std.math.Log2Int(BlockType); const Self = @This(); - blocks: [BlockNum]std.atomic.Value(BlockType) = .{std.atomic.Value(BlockType){ .raw = 0 }} ** BlockNum, + blocks: [BlockNum]std.atomic.Value(BlockType) = @splat(.{ .raw = 0 }), /// Sets the bit at `bit_index` to 1. /// diff --git a/core/src/cpus/msp430.zig b/core/src/cpus/msp430.zig index ae9eaed08..52df361b3 100644 --- a/core/src/cpus/msp430.zig +++ b/core/src/cpus/msp430.zig @@ -48,12 +48,12 @@ pub const InterruptOptions = microzig.utilities.GenerateInterruptOptions(&.{ // A placeholder for now const VectorTable = if (std.mem.eql(u8, config.cpu_name, "MSP430X")) extern struct { - table: [63]interrupt.Handler = [_]interrupt.Handler{.{ .c = interrupt.unhandled }} ** 63, + table: [63]interrupt.Handler = @splat(.{ .c = interrupt.unhandled }), RESET: interrupt.Handler, } else if (std.mem.eql(u8, config.cpu_name, "MSP430")) extern struct { - table: [15]interrupt.Handler = [_]interrupt.Handler{.{ .c = interrupt.unhandled }} ** 15, + table: [15]interrupt.Handler = @splat(.{ .c = interrupt.unhandled }), RESET: interrupt.Handler, } else diff --git a/drivers/src/wireless/cyw43/bus.zig b/drivers/src/wireless/cyw43/bus.zig index ef5768723..a2542b88f 100644 --- a/drivers/src/wireless/cyw43/bus.zig +++ b/drivers/src/wireless/cyw43/bus.zig @@ -139,7 +139,7 @@ pub const CYW43_Bus = struct { fn readn(self: *Self, func: FuncType, addr: u17, len: u11) u32 { const cmd = Cmd{ .cmd = .read, .incr = .incremental, .func = func, .addr = addr, .len = len }; - var buff = [_]u32{0} ** 2; + var buff: [2]u32 = @splat(0); // if we are reading from the backplane, we need an extra word for the response delay const buff_len: usize = if (func == .backplane) 2 else 1; diff --git a/drivers/src/wireless/cyw43/wifi.zig b/drivers/src/wireless/cyw43/wifi.zig index 0882f2f6e..7d48ec080 100644 --- a/drivers/src/wireless/cyw43/wifi.zig +++ b/drivers/src/wireless/cyw43/wifi.zig @@ -113,7 +113,7 @@ pub const CYW43_Wifi = struct { mac_valid: bool = false, connected: bool = false, link_up: bool = false, - event_mask: [24]u8 = .{0xFF} ** 24, + event_mask: [24]u8 = @splat(0xFF), scan_ctx: ScanCtx = .{}, const clm_data = @embedFile("firmware/43439A0_clm.bin"); @@ -367,7 +367,7 @@ pub const CYW43_Wifi = struct { if (security == .wpa3_sae) { var sae = SAE_PassphraseInfo{ .len = @intCast(password.len), - .passphrase = .{0} ** 128, + .passphrase = @splat(0), }; const pwd_len = @min(password.len, 128); @memcpy(sae.passphrase[0..pwd_len], password[0..pwd_len]); @@ -377,7 +377,7 @@ pub const CYW43_Wifi = struct { var pmk = PassphraseInfo{ .len = @intCast(password.len), .flags = 1, - .passphrase = .{0} ** 64, + .passphrase = @splat(0), }; const pwd_len = @min(password.len, 64); @memcpy(pmk.passphrase[0..pwd_len], password[0..pwd_len]); @@ -414,7 +414,7 @@ pub const CYW43_Wifi = struct { var ssid_info = SSID_Info{ .len = @intCast(ssid.len), - .ssid = .{0} ** 32, + .ssid = @splat(0), }; const len = @min(ssid.len, 32); @memcpy(ssid_info.ssid[0..len], ssid[0..len]); diff --git a/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig b/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig index 452a0d303..bca6c9f6e 100644 --- a/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig +++ b/examples/raspberrypi/rp2xxx/src/mlx90640_hottest_point.zig @@ -88,7 +88,7 @@ inline fn find_hottest_cluster_centroid(image: *const [768]f32) struct { row: f3 hot[i] = image[i] >= threshold; } - var visited: [768]bool = .{false} ** 768; + var visited: [768]bool = @splat(false); var queue: [768]u16 = undefined; var best_sum_row: f32 = 0; diff --git a/examples/stmicro/stm32/src/stm32f1xx/advanced_adc.zig b/examples/stmicro/stm32/src/stm32f1xx/advanced_adc.zig index 0f1fdd2a4..2024a5668 100644 --- a/examples/stmicro/stm32/src/stm32f1xx/advanced_adc.zig +++ b/examples/stmicro/stm32/src/stm32f1xx/advanced_adc.zig @@ -74,7 +74,7 @@ pub fn main() !void { time.init_timer(.TIM2); const ref_ovf_flag: *volatile bool = &ovf_flag; - var adc_buf: [10]u16 = .{0} ** 10; + var adc_buf: [10]u16 = @splat(0); const dma_channel = adc_dma.get_channel(); dma_channel.apply(.{ diff --git a/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig b/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig index 9e20f1f40..a5d8bfd51 100644 --- a/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig +++ b/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig @@ -139,7 +139,7 @@ const ReportDescriptor = [63]u8{ //=============== USB DATA ================= var EP0_RX_BUFFER: [64]u8 = undefined; var USB_RX_BUFFER: [64]u8 = undefined; -var HID_send: [8]u8 = .{0} ** 8; +var HID_send: [8]u8 = @splat(0); var to_report: bool = false; var device_addr: ?u7 = null; var config: bool = false; diff --git a/examples/wch/ch32v/src/dma.zig b/examples/wch/ch32v/src/dma.zig index 6f012aa66..60accd571 100644 --- a/examples/wch/ch32v/src/dma.zig +++ b/examples/wch/ch32v/src/dma.zig @@ -19,9 +19,9 @@ comptime { } // Should be in flash .rodata -const rbuf: [1024]u32 = .{0x12345678} ** 1024; +const rbuf: [1024]u32 = @splat(0x12345678); // Should be in RAM .bss -var wbuf: [1024]u32 = .{0} ** 1024; +var wbuf: [1024]u32 = @splat(0); inline fn read_stk_cnt() u64 { const PFIC = microzig.chip.peripherals.PFIC; diff --git a/modules/bounded-array/src/bounded_array.zig b/modules/bounded-array/src/bounded_array.zig index a87ebfe12..a11d9b92d 100644 --- a/modules/bounded-array/src/bounded_array.zig +++ b/modules/bounded-array/src/bounded_array.zig @@ -328,7 +328,7 @@ test BoundedArray { try a.resize(48); try testing.expectEqual(a.len, 48); - const x = [_]u8{1} ** 10; + const x: [10]u8 = @splat(1); a = try BoundedArray(u8, 64).from_slice(&x); try testing.expectEqualSlices(u8, &x, a.const_slice()); diff --git a/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig b/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig index 9340da0b3..6a8d615c5 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig @@ -186,7 +186,7 @@ pub const Config = struct { }; var init: bool = false; -var endpoints: [8]?Endpoint = .{null} ** 8; +var endpoints: [8]?Endpoint = @splat(null); var iner_RX_buffer: []u8 = undefined; var reset_callback: ?ResetCallback = null; var reset_ctx: ?*anyopaque = null; diff --git a/sim/aviron/src/lib/Cpu.zig b/sim/aviron/src/lib/Cpu.zig index 36ff7175a..78dd77b85 100644 --- a/sim/aviron/src/lib/Cpu.zig +++ b/sim/aviron/src/lib/Cpu.zig @@ -65,7 +65,7 @@ sram_size: u16 = 0, // State pc: u24 = 0, -regs: [32]u8 = [1]u8{0} ** 32, +regs: [32]u8 = @splat(0), sreg: SREG = @bitCast(@as(u8, 0)), instr_count: u64 = 0, @@ -73,7 +73,7 @@ instr_effect: InstructionEffect = .none, pub fn reset(cpu: *Cpu) void { cpu.pc = 0; - cpu.regs = [1]u8{0} ** 32; + cpu.regs = @splat(0); cpu.sreg = @bitCast(@as(u8, 0)); } diff --git a/sim/aviron/src/lib/bus.zig b/sim/aviron/src/lib/bus.zig index dfb2c8097..4f80c878d 100644 --- a/sim/aviron/src/lib/bus.zig +++ b/sim/aviron/src/lib/bus.zig @@ -37,7 +37,7 @@ pub const Flash = struct { return struct { const Self = @This(); - data: [size]u8 align(2) = .{0} ** size, + data: [size]u8 align(2) = @splat(0), pub fn memory(self: *Self) Flash { return Flash{ @@ -236,7 +236,7 @@ pub fn FixedSizeMemory(comptime size: comptime_int, comptime bus_config: ?BusCon pub const BusType = Bus(config); const AddressType = BusType.Address; - data: [size]u8 align(2) = .{0} ** size, + data: [size]u8 align(2) = @splat(0), pub fn bus(self: *Self) BusType { return .{ .ctx = self, .vtable = &bus_vtable }; diff --git a/sim/aviron/src/lib/util/hexdump.zig b/sim/aviron/src/lib/util/hexdump.zig index c3322b109..24d816ac8 100644 --- a/sim/aviron/src/lib/util/hexdump.zig +++ b/sim/aviron/src/lib/util/hexdump.zig @@ -121,7 +121,7 @@ pub fn hexdump( // Store as previous row if (prev_row == null) { - prev_row = [_]u8{0} ** 256; + prev_row = @splat(0); } @memcpy(prev_row.?[0..row_len], cur_row[0..row_len]); prev_len = row_len; diff --git a/sim/aviron/tools/generate_tables.zig b/sim/aviron/tools/generate_tables.zig index 38bf5d442..7e2b780b8 100644 --- a/sim/aviron/tools/generate_tables.zig +++ b/sim/aviron/tools/generate_tables.zig @@ -26,7 +26,7 @@ pub fn main(init: std.process.Init) !void { var buf: std.Io.Writer.Allocating = .init(gpa); defer buf.deinit(); - var lut = [_]isa.Opcode{.unknown} ** (std.math.maxInt(u16) + 1); + var lut: [std.math.maxInt(u16) + 1]isa.Opcode = @splat(.unknown); var base_number_bit_set = std.bit_set.IntegerBitSet(16).initEmpty(); var unknown_indices = try BoundedArray(u8, 16).init(0); diff --git a/tools/sorcerer/src/RegzWindow.zig b/tools/sorcerer/src/RegzWindow.zig index 34667b857..8e9897aa2 100644 --- a/tools/sorcerer/src/RegzWindow.zig +++ b/tools/sorcerer/src/RegzWindow.zig @@ -77,7 +77,7 @@ pub const SelectedPatch = struct { pub const PendingPatchCreation = struct { peripheral_name: []const u8, group_idx: usize, - enum_name_buffer: [128]u8 = [_]u8{0} ** 128, + enum_name_buffer: [128]u8 = @splat(0), selected_file_index: ?usize = null, }; diff --git a/tools/sorcerer/src/main.zig b/tools/sorcerer/src/main.zig index 492bfda91..fa55a591d 100644 --- a/tools/sorcerer/src/main.zig +++ b/tools/sorcerer/src/main.zig @@ -48,11 +48,11 @@ const State = struct { show_from_microzig_window: bool = false, show_stats_window: bool = true, show_search_chips_window: bool = false, - chip_search_query: [256]u8 = [_]u8{0} ** 256, + chip_search_query: [256]u8 = @splat(0), show_search_boards_window: bool = false, - board_search_query: [256]u8 = [_]u8{0} ** 256, + board_search_query: [256]u8 = @splat(0), show_search_targets_window: bool = false, - target_search_query: [256]u8 = [_]u8{0} ** 256, + target_search_query: [256]u8 = @splat(0), // Target selection popup state (for chip search) show_target_selection_window: bool = false, selected_chip_name: []const u8 = "", From ab3f7be9725cb50824d241dd9e86ac12620c4487 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 14:25:12 -0700 Subject: [PATCH 34/61] regz compiling on master --- tools/regz/build.zig | 10 +++------- tools/regz/build.zig.zon | 12 ++++-------- tools/regz/src/main.zig | 4 ++-- tools/regz/src/svd.zig | 2 +- tools/regz/src/xml.zig | 7 +------ 5 files changed, 11 insertions(+), 24 deletions(-) diff --git a/tools/regz/build.zig b/tools/regz/build.zig index 0b5a9c08d..58a9b0eaf 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -13,24 +13,20 @@ pub fn build(b: *Build) !void { .iconv = false, }); - const sqlite3_dep = b.dependency("sqlite3", .{ - .target = target, - .optimize = .ReleaseSafe, - }); - const sqlite3_lib = sqlite3_dep.artifact("sqlite3"); - const zqlite_dep = b.dependency("zqlite", .{ .target = target, .optimize = optimize, }); const zqlite = zqlite_dep.module("zqlite"); - zqlite.linkLibrary(sqlite3_lib); const xml_module = b.createModule(.{ .root_source_file = b.path("src/xml.zig"), .target = target, .optimize = optimize, + .imports = &.{ + .{ .name = "xml", .module = libxml2_dep.module("xml") }, + }, }); const regz_module = b.addModule("regz", .{ diff --git a/tools/regz/build.zig.zon b/tools/regz/build.zig.zon index b4ba99920..83827b98b 100644 --- a/tools/regz/build.zig.zon +++ b/tools/regz/build.zig.zon @@ -10,16 +10,12 @@ }, .dependencies = .{ .libxml2 = .{ - .url = "git+https://github.com/allyourcodebase/libxml2.git?ref=2.15.1-2#2528fad1bf17a0a70999930cfd9280554f547787", - .hash = "libxml2-2.15.1-2-qHdjhmNMAAAiZOWqVridicq2oMf5NHv0n9W41bz9FtMM", - }, - .sqlite3 = .{ - .url = "git+https://github.com/allyourcodebase/sqlite3#b7514a2b76003bee57db1fc78e84a2abc7499efa", - .hash = "sqlite3-3.51.0-DMxLWuAOAABO27GnPH0iTeI57EkQPpGwqI7LTfiE4Pda", + .url = "git+https://github.com/allyourcodebase/libxml2.git#675b1709603929393613d0ab00a61ff11491bbbe", + .hash = "libxml2-2.15.1-2-qHdjhvNVAADdvYgiVeAqxhST_JM3VhVplmc1REvwtAYr", }, .zqlite = .{ - .url = "git+https://github.com/karlseguin/zqlite.zig#b44ed5cdc64859b08446c246f307e65ebe2b2d9c", - .hash = "zqlite-0.0.0-RWLaY_y_mADh2LdbDrG_2HT2dBAcsAR8Jig_7-dOJd0B", + .url = "git+https://github.com/karlseguin/zqlite.zig#5ac4cabe95a6d7faa7baf0da8057a8e6e8a227a1", + .hash = "zqlite-0.0.1-RWLaY64xnAAxsD2YNT8QqPMJUuaFv2GOzFRR4aGypJv3", }, }, } diff --git a/tools/regz/src/main.zig b/tools/regz/src/main.zig index c658bfb71..f4440f5a8 100644 --- a/tools/regz/src/main.zig +++ b/tools/regz/src/main.zig @@ -73,7 +73,7 @@ fn parse_args(gpa: Allocator, io: std.Io, args: []const []const u8) !Arguments { ret.help = true; } else if (std.mem.eql(u8, args[i], "--db_dump_path")) { i += 1; - ret.dump_path = try gpa.dupeZ(u8, args[i]); + ret.dump_path = try gpa.dupeSentinel(u8, args[i], 0); } else if (std.mem.eql(u8, args[i], "--format")) { i += 1; if (i >= args.len) @@ -89,7 +89,7 @@ fn parse_args(gpa: Allocator, io: std.Io, args: []const []const u8) !Arguments { }; } else if (std.mem.eql(u8, args[i], "--output_path")) { i += 1; - ret.output_path = try gpa.dupeZ(u8, args[i]); + ret.output_path = try gpa.dupeSentinel(u8, args[i], 0); } else if (std.mem.eql(u8, args[i], "--device")) { i += 1; ret.device = try gpa.dupe(u8, args[i]); diff --git a/tools/regz/src/svd.zig b/tools/regz/src/svd.zig index 69f29d9fc..29af3784d 100644 --- a/tools/regz/src/svd.zig +++ b/tools/regz/src/svd.zig @@ -835,7 +835,7 @@ const DimElements = struct { const buf = try ctx.arena.allocator().allocSentinel(u8, 16, 0); @memset(buf, 0); // dim index range is with - dim_index = try std.fmt.bufPrintZ(buf, "0-{d}", .{dim.? - 1}); + dim_index = try std.fmt.bufPrintSentinel(buf, "0-{d}", .{dim.? - 1}, 0); } if (node.get_value("dimArrayIndex") != null) { diff --git a/tools/regz/src/xml.zig b/tools/regz/src/xml.zig index a3461ab71..500fb5dff 100644 --- a/tools/regz/src/xml.zig +++ b/tools/regz/src/xml.zig @@ -1,10 +1,5 @@ const std = @import("std"); -pub const c = @cImport({ - @cDefine("LIBXML_TREE_ENABLED", {}); - @cDefine("LIBXML_SCHEMAS_ENABLED", {}); - @cDefine("LIBXML_READER_ENABLED", {}); - @cInclude("libxml/xmlreader.h"); -}); +pub const c = @import("xml").c; const Allocator = std.mem.Allocator; From 7d59bdc2a4a7d3f9665b0327b0f4cda617435c6f Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 15:15:08 -0700 Subject: [PATCH 35/61] Pass regz tests --- core/src/core/usb.zig | 3 ++- core/src/mmio.zig | 2 +- drivers/src/sensor/TLV493D.zig | 4 ++-- examples/texasinstruments/msp430/src/blinky.zig | 2 +- tools/regz/src/VirtualFilesystem.zig | 2 +- tools/regz/src/svd.zig | 5 +++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/core/src/core/usb.zig b/core/src/core/usb.zig index 3328b0b6d..5adb96ce4 100644 --- a/core/src/core/usb.zig +++ b/core/src/core/usb.zig @@ -319,7 +319,8 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { }; if (itf_start != itf_handlers.len) @compileError("interface numbering mismatch"); - itf_handlers = itf_handlers ++ &[_]DriverEnum{@field(DriverEnum, drv.name)} ** itf_count; + + itf_handlers = itf_handlers ++ @as([itf_count]DriverEnum, @splat(@field(DriverEnum, drv.name))); } switch (fld.type) { diff --git a/core/src/mmio.zig b/core/src/mmio.zig index 689f32b3d..a5b1b34ed 100644 --- a/core/src/mmio.zig +++ b/core/src/mmio.zig @@ -11,7 +11,7 @@ pub fn Mmio(comptime PackedT: type) type { if (!std.math.isPowerOfTwo(size / 8)) @compileError("size must encode a power of two number of bytes!"); - const IntT = std.meta.Int(.unsigned, size); + const IntT = @Int(.unsigned, size); if (@sizeOf(PackedT) != (size / 8)) @compileError(std.fmt.comptimePrint("IntT and PackedT must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(PackedT) })); diff --git a/drivers/src/sensor/TLV493D.zig b/drivers/src/sensor/TLV493D.zig index bd74b40f3..c9b1c4a8f 100644 --- a/drivers/src/sensor/TLV493D.zig +++ b/drivers/src/sensor/TLV493D.zig @@ -162,8 +162,8 @@ pub const TLV493D = struct { .dev = dev, .address = address, .clock = clock, - .read_data = @bitCast([_]u8{0} ** 10), - .write_data = @bitCast([_]u8{0} ** 4), + .read_data = 0, + .write_data = 0, .mode = config.access_mode, }; diff --git a/examples/texasinstruments/msp430/src/blinky.zig b/examples/texasinstruments/msp430/src/blinky.zig index 210f9c47d..310789f73 100644 --- a/examples/texasinstruments/msp430/src/blinky.zig +++ b/examples/texasinstruments/msp430/src/blinky.zig @@ -30,7 +30,7 @@ pub fn busy_sleep(comptime limit: comptime_int) void { bits += 1; } - const I = std.meta.Int(.unsigned, bits); + const I = @Int(.unsigned, bits); var i: I = 0; while (i < limit) : (i += 1) { diff --git a/tools/regz/src/VirtualFilesystem.zig b/tools/regz/src/VirtualFilesystem.zig index 040f35940..481c1b34e 100644 --- a/tools/regz/src/VirtualFilesystem.zig +++ b/tools/regz/src/VirtualFilesystem.zig @@ -93,6 +93,7 @@ fn operate(userdata: ?*anyopaque, op: std.Io.Operation) std.Io.Cancelable!std.Io .file_read_streaming => unreachable, .device_io_control => unreachable, .net_receive => unreachable, + .net_read => unreachable, }; } @@ -360,7 +361,6 @@ pub fn io(vfs: *VirtualFilesystem) std.Io { .netSocketCreatePair = std.Io.failingNetSocketCreatePair, .netSend = std.Io.failingNetSend, - .netRead = std.Io.failingNetRead, .netWrite = std.Io.failingNetWrite, .netWriteFile = std.Io.failingNetWriteFile, .netClose = std.Io.unreachableNetClose, diff --git a/tools/regz/src/svd.zig b/tools/regz/src/svd.zig index 29af3784d..e3e9df2b6 100644 --- a/tools/regz/src/svd.zig +++ b/tools/regz/src/svd.zig @@ -851,9 +851,9 @@ const DimElements = struct { } fn dim_index_value(self: DimElements, ctx: *Context, index: usize) ![]const u8 { - if (std.mem.containsAtLeastScalar(u8, self.dim_index.?, 1, '-')) { + if (std.mem.containsAtLeastScalar(u8, self.dim_index.?, '-', 1)) { return try self.dim_index_value_range(ctx, index); - } else if (std.mem.containsAtLeastScalar(u8, self.dim_index.?, 1, ',')) { + } else if (std.mem.containsAtLeastScalar(u8, self.dim_index.?, ',', 1)) { return try self.dim_index_value_csv(ctx, index); } else return error.DimIndexInvalid; } @@ -888,6 +888,7 @@ const DimElements = struct { if (start_index.len == 1 and std.ascii.isAlphabetic(start_index[0])) { return start_index; } + return error.DimIndexInvalid; } } From 5989823cd42373fe39a076a41f8ee40ef356a211 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 15:18:04 -0700 Subject: [PATCH 36/61] dfu compiles and tests --- tools/dfu/src/dfuse.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dfu/src/dfuse.zig b/tools/dfu/src/dfuse.zig index 858b1f112..3ac3fc599 100644 --- a/tools/dfu/src/dfuse.zig +++ b/tools/dfu/src/dfuse.zig @@ -208,7 +208,7 @@ fn calculate_target_size(segments: []const Segment) u32 { return size; } -fn write_elements(reader: *std.Io.File.fsReader, writer: *std.Io.Writer, segments: []const Segment) !void { +fn write_elements(reader: *std.Io.File.Reader, writer: *std.Io.Writer, segments: []const Segment) !void { var ranges = ElementRangeIterator.init(segments); while (ranges.next()) |range| { const element_size = range.size(); From 204853f6823148e73b5da41de1c1bf9763b40dd5 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 15:19:28 -0700 Subject: [PATCH 37/61] drivers compiling and testing --- drivers/src/input/debounced_button.zig | 2 +- drivers/src/input/keyboard_matrix.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/src/input/debounced_button.zig b/drivers/src/input/debounced_button.zig index ef8c932b5..136d98879 100644 --- a/drivers/src/input/debounced_button.zig +++ b/drivers/src/input/debounced_button.zig @@ -31,7 +31,7 @@ pub const Options = struct { pub fn DebouncedButton(comptime options: Options) type { return struct { const Button = @This(); - const FilterInt = std.meta.Int(.unsigned, options.filter_depth orelse 16); + const FilterInt = @Int(.unsigned, options.filter_depth orelse 16); io: options.Digital_IO, filter_buffer: FilterInt, diff --git a/drivers/src/input/keyboard_matrix.zig b/drivers/src/input/keyboard_matrix.zig index 1814b189e..87659ab9f 100644 --- a/drivers/src/input/keyboard_matrix.zig +++ b/drivers/src/input/keyboard_matrix.zig @@ -39,7 +39,7 @@ pub fn KeyboardMatrix(comptime options: Options) type { /// A set that can store if each key is set or not. pub const Set = struct { - pressed: std.StaticBitSet(key_count) = std.StaticBitSet(key_count).initEmpty(), + pressed: std.StaticBitSet(key_count) = .empty, /// Adds a key to the set. pub fn add(set: *Set, key: Key) void { From 865a356d5822e03908d9a1fdd9a75620c8eb7a8e Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 15:40:22 -0700 Subject: [PATCH 38/61] Some fixes for aviron, nrfx examples building --- drivers/src/sensor/TLV493D.zig | 4 ++-- examples/nordic/nrf5x/src/spi_master.zig | 5 +---- sim/aviron/src/lib/decoder.zig | 8 ++++---- sim/aviron/tools/generate_tables.zig | 6 +++--- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/src/sensor/TLV493D.zig b/drivers/src/sensor/TLV493D.zig index c9b1c4a8f..f1e2dcfd1 100644 --- a/drivers/src/sensor/TLV493D.zig +++ b/drivers/src/sensor/TLV493D.zig @@ -162,8 +162,8 @@ pub const TLV493D = struct { .dev = dev, .address = address, .clock = clock, - .read_data = 0, - .write_data = 0, + .read_data = std.mem.zeroes(ReadRegister), + .write_data = std.mem.zeroes(WriteRegister), .mode = config.access_mode, }; diff --git a/examples/nordic/nrf5x/src/spi_master.zig b/examples/nordic/nrf5x/src/spi_master.zig index 3bb4dd2c0..fb4499fe8 100644 --- a/examples/nordic/nrf5x/src/spi_master.zig +++ b/examples/nordic/nrf5x/src/spi_master.zig @@ -8,7 +8,6 @@ const gpio = nrf.gpio; const uart = nrf.uart.num(0); -const BUF_LEN = 0x100; const spi = nrf.spim.num(0); pub const panic = microzig.panic; @@ -41,12 +40,10 @@ pub fn main() !void { .mosi_pin = gpio.num(0, 10), }); - var out_buf: [BUF_LEN]u8 = .{ 'h', 'e', 'y', ' ', 'y', 'o', 'u', '!' } ** (BUF_LEN / 8); - while (true) { std.log.info("Sending some data", .{}); csn.put(0); - try spi.write_blocking(&out_buf, null); + try spi.write_blocking("hello world!\r\n", null); csn.put(1); time.sleep_ms(1000); } diff --git a/sim/aviron/src/lib/decoder.zig b/sim/aviron/src/lib/decoder.zig index d4bfe3e69..4760edb04 100644 --- a/sim/aviron/src/lib/decoder.zig +++ b/sim/aviron/src/lib/decoder.zig @@ -25,9 +25,9 @@ pub fn decode(inst_val: u16) !Instruction { } const positionals = @field(tables.positionals, @tagName(tag)); - const Bitsets = std.meta.Tuple(types: { + const Bitsets = @Tuple(types: { var bs_types: [positionals.len]type = undefined; - inline for (positionals, 0..) |pos, i| { + for (positionals, 0..) |pos, i| { bs_types[i] = std.bit_set.IntegerBitSet(pos[1].len); } break :types &bs_types; @@ -35,10 +35,10 @@ pub fn decode(inst_val: u16) !Instruction { var bitsets: Bitsets = undefined; inline for (&bitsets) |*bs| { - bs.* = @TypeOf(bs.*).initEmpty(); + bs.* = .empty; } - var bitset = std.bit_set.IntegerBitSet(16).initEmpty(); + var bitset: std.bit_set.IntegerBitSet(16) = .empty; bitset.mask = @bitReverse(inst_val); var result: Result = undefined; diff --git a/sim/aviron/tools/generate_tables.zig b/sim/aviron/tools/generate_tables.zig index 7e2b780b8..304858c92 100644 --- a/sim/aviron/tools/generate_tables.zig +++ b/sim/aviron/tools/generate_tables.zig @@ -28,10 +28,10 @@ pub fn main(init: std.process.Init) !void { var lut: [std.math.maxInt(u16) + 1]isa.Opcode = @splat(.unknown); - var base_number_bit_set = std.bit_set.IntegerBitSet(16).initEmpty(); + var base_number_bit_set: std.bit_set.IntegerBitSet(16) = .empty; var unknown_indices = try BoundedArray(u8, 16).init(0); - var unknown_indices_bit_set = std.bit_set.IntegerBitSet(16).initEmpty(); - var result_bit_set = std.bit_set.IntegerBitSet(16).initEmpty(); + var unknown_indices_bit_set: std.bit_set.IntegerBitSet(16) = .empty; + var result_bit_set: std.bit_set.IntegerBitSet(16) = .empty; var positionals = std.enums.EnumArray(isa.Opcode, std.AutoArrayHashMapUnmanaged(u8, BoundedArray(u8, 16))).initFill(.{}); defer for (&positionals.values) |*map| { From 1ff325ac95950aa0c3ed65df0c367cecbb04e3c4 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 17:07:02 -0700 Subject: [PATCH 39/61] Examples building, minus any depending on foundation-libc --- core/src/core/usb.zig | 7 ++- examples/microchip/atmega/src/blinky.zig | 2 +- examples/microchip/attiny/src/blinky.zig | 2 +- examples/nxp/lpc/src/blinky.zig | 2 +- .../rp2xxx/src/spi_loopback_dma.zig | 6 ++- .../raspberrypi/rp2xxx/src/spi_master.zig | 6 +-- .../raspberrypi/rp2xxx/src/ssd1306_oled.zig | 4 +- examples/raspberrypi/rp2xxx/src/usb_hid.zig | 2 +- modules/rtt/src/rtt.zig | 2 +- port/microchip/attiny/build.zig | 2 +- port/raspberrypi/rp2xxx/build.zig | 16 +++++-- port/raspberrypi/rp2xxx/src/hal/dma.zig | 2 +- .../rp2xxx/src/hal/pio/assembler.zig | 6 ++- .../src/hal/pio/assembler/comparison_tests.h | 32 +++++++++++++ .../hal/pio/assembler/comparison_tests.zig | 31 +----------- port/raspberrypi/rp2xxx/src/hal/usb.zig | 6 ++- port/stmicro/stm32/build.zig | 40 ++++++++-------- port/texasinstruments/msp430/build.zig | 42 ++++++++-------- port/texasinstruments/tm4c/build.zig | 48 ++++++++++--------- tools/regz/src/mmio.zig | 2 +- 20 files changed, 141 insertions(+), 119 deletions(-) create mode 100644 port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.h diff --git a/core/src/core/usb.zig b/core/src/core/usb.zig index 5adb96ce4..4b5eeac24 100644 --- a/core/src/core/usb.zig +++ b/core/src/core/usb.zig @@ -209,7 +209,7 @@ pub const Config = struct { var field_types: [self.configurations.len]type = undefined; for (self.configurations, &field_types) |cfg, *dst| dst.* = cfg.Args(); - return std.meta.Tuple(&field_types); + return @Tuple(&field_types); } }; @@ -350,10 +350,9 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type { } // Finally, bind the handler functions based on the data collected above. - const Tuple = std.meta.Tuple; // Create a tuple with the appropriate types - const ep_handlers_types: [2]type = .{ Tuple(&ep_handler_types[0]), Tuple(&ep_handler_types[1]) }; - var ep_handlers: Tuple(&ep_handlers_types) = undefined; + const ep_handlers_types: [2]type = .{ @Tuple(&ep_handler_types[0]), @Tuple(&ep_handler_types[1]) }; + var ep_handlers: @Tuple(&ep_handlers_types) = undefined; // Iterate over all IN and OUT endpoints and bind the handler for any that are set. for (&ep_handler_types, &ep_handler_names, &ep_handler_drivers, 0..) |htypes, hnames, hdrivers, dir| { for (&htypes, &hnames, &hdrivers, 0..) |T, name, drv_id, ep| { diff --git a/examples/microchip/atmega/src/blinky.zig b/examples/microchip/atmega/src/blinky.zig index 4908113bc..54dbf8f12 100644 --- a/examples/microchip/atmega/src/blinky.zig +++ b/examples/microchip/atmega/src/blinky.zig @@ -29,7 +29,7 @@ pub fn busy_sleep(comptime limit: comptime_int) void { bits += 1; } - const I = std.meta.Int(.unsigned, bits); + const I = @Int(.unsigned, bits); var i: I = 0; while (i < limit) : (i += 1) { diff --git a/examples/microchip/attiny/src/blinky.zig b/examples/microchip/attiny/src/blinky.zig index 8e94f4b61..8e49f0467 100644 --- a/examples/microchip/attiny/src/blinky.zig +++ b/examples/microchip/attiny/src/blinky.zig @@ -20,7 +20,7 @@ pub fn busy_sleep(comptime limit: comptime_int) void { bits += 1; } - const I = std.meta.Int(.unsigned, bits); + const I = @Int(.unsigned, bits); var i: I = 0; while (i < limit) : (i += 1) { diff --git a/examples/nxp/lpc/src/blinky.zig b/examples/nxp/lpc/src/blinky.zig index b7fb809ac..3b85ab938 100644 --- a/examples/nxp/lpc/src/blinky.zig +++ b/examples/nxp/lpc/src/blinky.zig @@ -71,7 +71,7 @@ pub fn busy_sleep(comptime limit: comptime_int) void { bits += 1; } - const I = std.meta.Int(.unsigned, bits); + const I = @Int(.unsigned, bits); var i: I = 0; while (i < limit) : (i += 1) { diff --git a/examples/raspberrypi/rp2xxx/src/spi_loopback_dma.zig b/examples/raspberrypi/rp2xxx/src/spi_loopback_dma.zig index cb518068e..3a602b40b 100644 --- a/examples/raspberrypi/rp2xxx/src/spi_loopback_dma.zig +++ b/examples/raspberrypi/rp2xxx/src/spi_loopback_dma.zig @@ -32,8 +32,12 @@ pub fn main() !void { rp2xxx.uart.init_logger(uart); - var in_buf: [BUF_LEN]u8 = .{ 'h', 'e', 'y', ' ', 'y', 'o', 'u', '!' } ** (BUF_LEN / 8); var out_buf = std.mem.zeroes([BUF_LEN]u8); + var in_buf: [BUF_LEN]u8 = undefined; + for (0..8) |i| { + for (in_buf[(8 * i)..(8 * (i + 1))], "hey you!") |*dst, c| + dst.* = c; + } try spi.apply(.{ .clock_config = rp2xxx.clock_config }); spi.set_loopback_mode(true); diff --git a/examples/raspberrypi/rp2xxx/src/spi_master.zig b/examples/raspberrypi/rp2xxx/src/spi_master.zig index 0c7f1d406..798acdd66 100644 --- a/examples/raspberrypi/rp2xxx/src/spi_master.zig +++ b/examples/raspberrypi/rp2xxx/src/spi_master.zig @@ -34,11 +34,9 @@ pub fn main() !void { } try spi.apply(.{ .clock_config = rp2xxx.clock_config }); - var out_buf: [BUF_LEN]u8 = .{ 'h', 'e', 'y', ' ', 'y', 'o', 'u', '!' } ** (BUF_LEN / 8); - while (true) { - std.log.info("Sending some data\n", .{}); - spi.write_blocking(u8, &out_buf); + std.log.info("Sending some data", .{}); + spi.write_blocking(u8, "hello world\r\n"); time.sleep_ms(1 * 1000); } } diff --git a/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig b/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig index 8e903b206..32abf9786 100644 --- a/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig +++ b/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig @@ -7,8 +7,8 @@ const i2c = rp2xxx.i2c; const font8x8 = @import("font8x8"); const i2c0 = i2c.instance.num(0); -const empty_row: []const u8 = " " ** 16; -const four_rows = empty_row ** 4; +const empty_row: [16]u8 = @splat(' '); +const four_rows: [16 * 4]u8 = @splat(' '); pub const panic = microzig.panic; diff --git a/examples/raspberrypi/rp2xxx/src/usb_hid.zig b/examples/raspberrypi/rp2xxx/src/usb_hid.zig index e1a331624..a6262915c 100644 --- a/examples/raspberrypi/rp2xxx/src/usb_hid.zig +++ b/examples/raspberrypi/rp2xxx/src/usb_hid.zig @@ -180,7 +180,7 @@ pub fn main() !void { } else { idx += @intFromBool(if (idx & 1 == 0 and idx < 2 * message.len) drivers.keyboard.send_report( - &.{ .modifiers = .none, .keys = .{message[@intCast(idx / 2)]} ++ .{.reserved} ** 5 }, + &.{ .modifiers = .none, .keys = .{message[@intCast(idx / 2)]} ++ @as([5]Code, @splat(.reserved)) }, ) else drivers.keyboard.send_report(&.empty)); diff --git a/modules/rtt/src/rtt.zig b/modules/rtt/src/rtt.zig index f81c09fdd..36ab921c7 100644 --- a/modules/rtt/src/rtt.zig +++ b/modules/rtt/src/rtt.zig @@ -305,7 +305,7 @@ pub const channel = struct { } pub fn mode(self: *Self) Mode { - return std.meta.intToEnum(Mode, self.mode & 3); + return @enumFromInt(self.mode & 3); } pub fn set_mode(self: *Self, mode_: Mode) void { diff --git a/port/microchip/attiny/build.zig b/port/microchip/attiny/build.zig index ff5291819..290cbab4d 100644 --- a/port/microchip/attiny/build.zig +++ b/port/microchip/attiny/build.zig @@ -16,7 +16,7 @@ boards: struct { pub fn init(dep: *std.Build.Dependency) ?Self { const b = dep.builder; - const atpack = b.lazyDependdency("atpack", .{}) orelse return null; + const atpack = b.lazyDependency("atpack", .{}) orelse return null; const avr25_target: std.Target.Query = .{ .cpu_arch = .avr, .cpu_model = .{ .explicit = &std.Target.avr.cpu.avr25 }, diff --git a/port/raspberrypi/rp2xxx/build.zig b/port/raspberrypi/rp2xxx/build.zig index 2cb9aaa95..83b3e9e64 100644 --- a/port/raspberrypi/rp2xxx/build.zig +++ b/port/raspberrypi/rp2xxx/build.zig @@ -286,15 +286,23 @@ pub fn build(b: *std.Build) !void { const bounded_array_dep = b.dependency("bounded-array", .{}); + const translate_c = b.addTranslateC(.{ + .root_source_file = b.path("src/hal/pio/assembler/comparison_tests.h"), + .target = target, + .optimize = optimize, + .link_libc = false, + }); + translate_c.defineCMacro("PICO_NO_HARDWARE", "1"); + const unit_tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("src/hal.zig"), .target = target, .optimize = optimize, - .imports = &.{.{ - .name = "bounded-array", - .module = bounded_array_dep.module("bounded-array"), - }}, + .imports = &.{ + .{ .name = "bounded-array", .module = bounded_array_dep.module("bounded-array") }, + .{ .name = "c", .module = translate_c.createModule() }, + }, }), }); unit_tests.root_module.addIncludePath(b.path("src/hal/pio/assembler")); diff --git a/port/raspberrypi/rp2xxx/src/hal/dma.zig b/port/raspberrypi/rp2xxx/src/hal/dma.zig index e50f7fab8..88ca5773f 100644 --- a/port/raspberrypi/rp2xxx/src/hal/dma.zig +++ b/port/raspberrypi/rp2xxx/src/hal/dma.zig @@ -15,7 +15,7 @@ const num_channels = switch (chip) { .RP2350 => 16, }; var claimed_channels = microzig.concurrency.AtomicStaticBitSet(num_channels){}; -const MaskType = std.meta.Int(.unsigned, num_channels); +const MaskType = @Int(.unsigned, num_channels); pub fn channel(n: u4) Channel { assert(n < num_channels); diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig index 1aa48b5da..d109169cb 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig @@ -131,6 +131,8 @@ fn format_compile_error(comptime message: []const u8, comptime source: []const u } } + const indent: [column]u8 = @splat(' '); + return std.fmt.comptimePrint( \\failed to assemble PIO code: \\ @@ -140,8 +142,8 @@ fn format_compile_error(comptime message: []const u8, comptime source: []const u \\ , .{ line_str, - [_]u8{' '} ** column, - [_]u8{' '} ** column, + indent, + indent, message, }); } diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.h b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.h new file mode 100644 index 000000000..f6a0d79de --- /dev/null +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.h @@ -0,0 +1,32 @@ +#ifndef _RP2XXX_COMPARISON_TESTS_H_ +#define _RP2XXX_COMPARISON_TESTS_H_ + +#include +#include "comparison_tests/addition.pio.h" +#include "comparison_tests/apa102.pio.h" +#include "comparison_tests/blink.pio.h" +#include "comparison_tests/clocked_input.pio.h" +#include "comparison_tests/differential_manchester.pio.h" +#include "comparison_tests/hello.pio.h" +#include "comparison_tests/hub75.pio.h" +#include "comparison_tests/i2c.pio.h" +#include "comparison_tests/irq.pio.h" +#include "comparison_tests/manchester_encoding.pio.h" +#include "comparison_tests/movrx.pio.h" +#include "comparison_tests/nec_carrier_burst.pio.h" +#include "comparison_tests/nec_carrier_control.pio.h" +#include "comparison_tests/nec_receive.pio.h" +#include "comparison_tests/pio_serialiser.pio.h" +#include "comparison_tests/pwm.pio.h" +#include "comparison_tests/quadrature_encoder.pio.h" +#include "comparison_tests/resistor_dac.pio.h" +#include "comparison_tests/spi.pio.h" +#include "comparison_tests/squarewave.pio.h" +#include "comparison_tests/squarewave_fast.pio.h" +#include "comparison_tests/squarewave_wrap.pio.h" +#include "comparison_tests/st7789_lcd.pio.h" +#include "comparison_tests/uart_rx.pio.h" +#include "comparison_tests/uart_tx.pio.h" +#include "comparison_tests/ws2812.pio.h" + +#endif diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig index 32e8e2212..4a4bcdb4e 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig @@ -3,36 +3,7 @@ const assembler = @import("../assembler.zig"); const tokenizer = @import("tokenizer.zig"); const Chip = @import("../../chip.zig").Chip; -const c = @cImport({ - @cDefine("PICO_NO_HARDWARE", "1"); - @cInclude("stdint.h"); - @cInclude("comparison_tests/addition.pio.h"); - @cInclude("comparison_tests/apa102.pio.h"); - @cInclude("comparison_tests/blink.pio.h"); - @cInclude("comparison_tests/clocked_input.pio.h"); - @cInclude("comparison_tests/differential_manchester.pio.h"); - @cInclude("comparison_tests/hello.pio.h"); - @cInclude("comparison_tests/hub75.pio.h"); - @cInclude("comparison_tests/i2c.pio.h"); - @cInclude("comparison_tests/irq.pio.h"); - @cInclude("comparison_tests/manchester_encoding.pio.h"); - @cInclude("comparison_tests/movrx.pio.h"); - @cInclude("comparison_tests/nec_carrier_burst.pio.h"); - @cInclude("comparison_tests/nec_carrier_control.pio.h"); - @cInclude("comparison_tests/nec_receive.pio.h"); - @cInclude("comparison_tests/pio_serialiser.pio.h"); - @cInclude("comparison_tests/pwm.pio.h"); - @cInclude("comparison_tests/quadrature_encoder.pio.h"); - @cInclude("comparison_tests/resistor_dac.pio.h"); - @cInclude("comparison_tests/spi.pio.h"); - @cInclude("comparison_tests/squarewave.pio.h"); - @cInclude("comparison_tests/squarewave_fast.pio.h"); - @cInclude("comparison_tests/squarewave_wrap.pio.h"); - @cInclude("comparison_tests/st7789_lcd.pio.h"); - @cInclude("comparison_tests/uart_rx.pio.h"); - @cInclude("comparison_tests/uart_tx.pio.h"); - @cInclude("comparison_tests/ws2812.pio.h"); -}); +const c = @import("c"); fn pio_comparison(comptime source: []const u8) !void { inline for (comptime .{ Chip.RP2040, Chip.RP2350 }) |chip| { diff --git a/port/raspberrypi/rp2xxx/src/hal/usb.zig b/port/raspberrypi/rp2xxx/src/hal/usb.zig index 2cc0de80d..db0957ba1 100644 --- a/port/raspberrypi/rp2xxx/src/hal/usb.zig +++ b/port/raspberrypi/rp2xxx/src/hal/usb.zig @@ -298,7 +298,8 @@ pub fn Polled(config: Config) type { // separately to the rest of the data in the buffer control register, // so that the rest of the data in the buffer control register is // accurate when the AVAILABLE bit is set. - asm volatile ("nop\n" ** config.sync_noops); + inline for (0..config.sync_noops) |_| + asm volatile ("nop"); } // Set available bit bufctrl.AVAILABLE_0 = 1; @@ -360,7 +361,8 @@ pub fn Polled(config: Config) type { // separately to the rest of the data in the buffer control register, // so that the rest of the data in the buffer control register is // accurate when the AVAILABLE bit is set. - asm volatile ("nop\n" ** config.sync_noops); + inline for (0..config.sync_noops) |_| + asm volatile ("nop"); } // Set available bit bufctrl.AVAILABLE_0 = 1; diff --git a/port/stmicro/stm32/build.zig b/port/stmicro/stm32/build.zig index d4ea01374..4fcdf1ccf 100644 --- a/port/stmicro/stm32/build.zig +++ b/port/stmicro/stm32/build.zig @@ -81,29 +81,31 @@ pub fn init(dep: *std.Build.Dependency) ?Self { } pub fn build(b: *std.Build) !void { - const stm32_data_generated = b.lazyDependency("stm32-data-generated", .{}) orelse return; + const generate = b.option(bool, "generate", "") orelse false; + if (generate) { + const stm32_data_generated = b.lazyDependency("stm32-data-generated", .{}) orelse return; - const generate_optimize = .ReleaseSafe; - const regz_dep = b.dependency("microzig/tools/regz", .{ - .optimize = generate_optimize, - }); - const regz = regz_dep.module("regz"); - - const generate_exe = b.addExecutable(.{ - .name = "generate", - .root_module = b.createModule(.{ - .root_source_file = b.path("src/generate.zig"), - .target = b.graph.host, + const generate_optimize = .ReleaseSafe; + const regz_dep = b.dependency("microzig/tools/regz", .{ .optimize = generate_optimize, - }), - }); - generate_exe.root_module.addImport("regz", regz); + }); + const regz = regz_dep.module("regz"); + + const generate_exe = b.addExecutable(.{ + .name = "generate", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/generate.zig"), + .target = b.graph.host, + .optimize = generate_optimize, + }), + }); + generate_exe.root_module.addImport("regz", regz); - const generate_run = b.addRunArtifact(generate_exe); - generate_run.addFileArg(stm32_data_generated.path(".")); + const generate_run = b.addRunArtifact(generate_exe); + generate_run.addFileArg(stm32_data_generated.path(".")); - const generate_step = b.step("generate", "Generate chips file 'src/Chips.zig'"); - generate_step.dependOn(&generate_run.step); + b.getInstallStep().dependOn(&generate_run.step); + } _ = b.step("test", "Run platform agnostic unit tests"); } diff --git a/port/texasinstruments/msp430/build.zig b/port/texasinstruments/msp430/build.zig index a0457641c..1d5b87036 100644 --- a/port/texasinstruments/msp430/build.zig +++ b/port/texasinstruments/msp430/build.zig @@ -38,28 +38,30 @@ pub fn init(dep: *std.Build.Dependency) ?Self { } pub fn build(b: *std.Build) void { - const ti_data = b.lazyDependency("ti_data", .{}) orelse return; - const targetdb = ti_data.path("targetdb"); + const generate = b.option(bool, "generate", "") orelse false; + if (generate) { + const ti_data = b.lazyDependency("ti_data", .{}) orelse return; + const targetdb = ti_data.path("targetdb"); - const generate_optimize = .ReleaseSafe; - const regz_dep = b.dependency("microzig/tools/regz", .{ - .optimize = generate_optimize, - }); - const regz = regz_dep.module("regz"); - - const generate_exe = b.addExecutable(.{ - .name = "generate", - .root_module = b.createModule(.{ - .root_source_file = b.path("src/generate.zig"), - .target = b.graph.host, + const generate_optimize = .ReleaseSafe; + const regz_dep = b.dependency("microzig/tools/regz", .{ .optimize = generate_optimize, - }), - }); - generate_exe.root_module.addImport("regz", regz); + }); + const regz = regz_dep.module("regz"); + + const generate_exe = b.addExecutable(.{ + .name = "generate", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/generate.zig"), + .target = b.graph.host, + .optimize = generate_optimize, + }), + }); + generate_exe.root_module.addImport("regz", regz); - const generate_run = b.addRunArtifact(generate_exe); - generate_run.addFileArg(targetdb); + const generate_run = b.addRunArtifact(generate_exe); + generate_run.addFileArg(targetdb); - const generate_step = b.step("generate", "Generate chips file 'src/Chips.zig'"); - generate_step.dependOn(&generate_run.step); + b.getInstallStep().dependOn(&generate_run.step); + } } diff --git a/port/texasinstruments/tm4c/build.zig b/port/texasinstruments/tm4c/build.zig index 65fa782dc..d094664ec 100644 --- a/port/texasinstruments/tm4c/build.zig +++ b/port/texasinstruments/tm4c/build.zig @@ -30,28 +30,30 @@ pub fn init(dep: *std.Build.Dependency) ?Self { } pub fn build(b: *std.Build) void { - const ti_data = b.lazyDependency("ti_data", .{}) orelse return; - const targetdb = ti_data.path("targetdb"); - - const generate_optimize = .ReleaseSafe; - const regz_dep = b.dependency("microzig/tools/regz", .{ - .optimize = generate_optimize, - }); - const regz = regz_dep.module("regz"); - - const generate_exe = b.addExecutable(.{ - .name = "generate", - .root_module = b.createModule(.{ - .root_source_file = b.path("src/generate.zig"), - .target = b.graph.host, - .optimize = generate_optimize, - }), - }); - generate_exe.root_module.addImport("regz", regz); + const generate = b.option(bool, "generate", "") orelse false; + if (generate) { + const ti_data = b.lazyDependency("ti_data", .{}) orelse return; + const targetdb = ti_data.path("targetdb"); - const generate_run = b.addRunArtifact(generate_exe); - generate_run.addFileArg(targetdb); - - const generate_step = b.step("generate", "Generate chips file 'src/Chips.zig'"); - generate_step.dependOn(&generate_run.step); + const generate_optimize = .ReleaseSafe; + const regz_dep = b.dependency("microzig/tools/regz", .{ + .optimize = generate_optimize, + }); + const regz = regz_dep.module("regz"); + + const generate_exe = b.addExecutable(.{ + .name = "generate", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/generate.zig"), + .target = b.graph.host, + .optimize = generate_optimize, + }), + }); + generate_exe.root_module.addImport("regz", regz); + + const generate_run = b.addRunArtifact(generate_exe); + generate_run.addFileArg(targetdb); + + b.getInstallStep().dependOn(&generate_run.step); + } } diff --git a/tools/regz/src/mmio.zig b/tools/regz/src/mmio.zig index 22714cfbb..c5753b07e 100644 --- a/tools/regz/src/mmio.zig +++ b/tools/regz/src/mmio.zig @@ -7,7 +7,7 @@ pub fn Mmio(comptime size: u8, comptime PackedT: type) type { if (!std.math.isPowerOfTwo(size / 8)) @compileError("size must encode a power of two number of bytes!"); - const IntT = std.meta.Int(.unsigned, size); + const IntT = @Int(.unsigned, size); if (@sizeOf(PackedT) != (size / 8)) @compileError(std.fmt.comptimePrint("IntT and PackedT must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(PackedT) })); From c9dcde376c372ce5b5ec470afd8835d5ded5a7f7 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 17:17:58 -0700 Subject: [PATCH 40/61] foundation-libc using TranslateC step --- modules/foundation-libc/build.zig | 11 +++++++++++ modules/foundation-libc/include/foundation/libc.h | 10 ++++++++++ modules/foundation-libc/src/libc.zig | 15 +-------------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/modules/foundation-libc/build.zig b/modules/foundation-libc/build.zig index c89ba9b5e..e42c22dd8 100644 --- a/modules/foundation-libc/build.zig +++ b/modules/foundation-libc/build.zig @@ -6,6 +6,14 @@ pub fn build(b: *std.Build) void { const single_threaded = b.option(bool, "single_threaded", "Create a single-threaded libc implementation (default: false)") orelse false; + const translate_c = b.addTranslateC(.{ + .root_source_file = b.path("include/foundation/libc.h"), + .target = target, + .optimize = optimize, + .link_libc = false, + }); + translate_c.addIncludePath(b.path("include")); + const libc = b.addLibrary(.{ .name = "foundation", .root_module = b.createModule(.{ @@ -13,6 +21,9 @@ pub fn build(b: *std.Build) void { .optimize = optimize, .root_source_file = b.path("src/libc.zig"), .single_threaded = single_threaded, + .imports = &.{ + .{ .name = "h", .module = translate_c.createModule() }, + }, }), }); diff --git a/modules/foundation-libc/include/foundation/libc.h b/modules/foundation-libc/include/foundation/libc.h index 7b245c800..1af70ab5d 100644 --- a/modules/foundation-libc/include/foundation/libc.h +++ b/modules/foundation-libc/include/foundation/libc.h @@ -1,7 +1,17 @@ #ifndef _FOUNDATION_LIBC_INTERNALS_H_ #define _FOUNDATION_LIBC_INTERNALS_H_ +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include /// /// Panic handler for undefined, but catchable behaviour in safe modes. diff --git a/modules/foundation-libc/src/libc.zig b/modules/foundation-libc/src/libc.zig index d3788af5f..5571bdf04 100644 --- a/modules/foundation-libc/src/libc.zig +++ b/modules/foundation-libc/src/libc.zig @@ -1,20 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); -pub const h = @cImport({ - @cInclude("assert.h"); - @cInclude("ctype.h"); - @cInclude("errno.h"); - @cInclude("inttypes.h"); - @cInclude("math.h"); - @cInclude("setjmp.h"); - @cInclude("stdlib.h"); - @cInclude("string.h"); - @cInclude("tgmath.h"); - @cInclude("uchar.h"); - - @cInclude("foundation/libc.h"); -}); +pub const h = @import("h"); comptime { // Some assertions over the target platform: From 88731c4966e08e88041b64333fde6b05fbe4414f Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 22:31:09 -0700 Subject: [PATCH 41/61] TranslateC for lwip Note that TranslateC steps link to libc by default --- .../raspberrypi/rp2xxx/src/ssd1306_oled.zig | 2 +- modules/lwip/build.zig | 25 ++++++++--- modules/lwip/include/lwip.h | 14 ++++++ modules/lwip/src/root.zig | 1 + modules/network/build.zig | 45 ++++++++----------- modules/network/src/root.zig | 12 +---- port/espressif/esp/build.zig | 1 - 7 files changed, 55 insertions(+), 45 deletions(-) create mode 100644 modules/lwip/include/lwip.h create mode 100644 modules/lwip/src/root.zig diff --git a/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig b/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig index 32abf9786..658289163 100644 --- a/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig +++ b/examples/raspberrypi/rp2xxx/src/ssd1306_oled.zig @@ -68,7 +68,7 @@ fn center_to_screen(buf: []u8, str: []u8) []u8 { const padding = @divTrunc(ldc_row_len - str.len, 2); // Copy the initial four rows - @memcpy(buf[0..four_rows_len], four_rows); + @memcpy(buf[0..four_rows_len], &four_rows); // Add left padding const left_pad_start = four_rows_len; diff --git a/modules/lwip/build.zig b/modules/lwip/build.zig index 425b0c0c2..6ea5c10a5 100644 --- a/modules/lwip/build.zig +++ b/modules/lwip/build.zig @@ -12,14 +12,26 @@ pub fn build(b: *std.Build) void { const upstream = b.dependency("lwip", .{}); + const translate_c = b.addTranslateC(.{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("include/lwip.h"), + .link_libc = false, + }); + translate_c.addIncludePath(upstream.path("src/include")); + + const lwip_module = b.addModule("lwip", .{ + .optimize = optimize, + .target = target, + .root_source_file = b.path("src/root.zig"), + .imports = &.{ + .{ .name = "c", .module = translate_c.createModule() }, + }, + }); + const lwip = b.addLibrary(.{ .name = "lwip", - .root_module = b.createModule(.{ - .optimize = optimize, - .target = target, - .link_libc = false, - }), - .linkage = .static, + .root_module = lwip_module, }); lwip.root_module.addCSourceFiles(.{ @@ -30,6 +42,7 @@ pub fn build(b: *std.Build) void { lwip.root_module.addIncludePath(upstream.path("src/include")); if (maybe_include_dir) |include_dir| { + translate_c.addIncludePath(include_dir); lwip.root_module.addIncludePath(include_dir); lwip.installHeadersDirectory(include_dir, "", .{}); } diff --git a/modules/lwip/include/lwip.h b/modules/lwip/include/lwip.h new file mode 100644 index 000000000..a21f30f23 --- /dev/null +++ b/modules/lwip/include/lwip.h @@ -0,0 +1,14 @@ +#ifndef _MICROZIG_LWIP_H +#define _MICROZIG_LWIP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/modules/lwip/src/root.zig b/modules/lwip/src/root.zig new file mode 100644 index 000000000..a068e467c --- /dev/null +++ b/modules/lwip/src/root.zig @@ -0,0 +1 @@ +pub const c = @import("c"); diff --git a/modules/network/build.zig b/modules/network/build.zig index 4b1bf9100..93d26f85f 100644 --- a/modules/network/build.zig +++ b/modules/network/build.zig @@ -37,16 +37,6 @@ pub fn build(b: *std.Build) void { @panic("Invalid lwip packet buffer length"); } - const net_mod = b.addModule("net", .{ - .target = target, - .optimize = optimize, - .root_source_file = b.path("src/root.zig"), - .imports = &.{.{ - .name = "link", - .module = b.dependency("link", .{}).module("link"), - }}, - }); - var buf: [32]u8 = undefined; const foundation_dep = b.dependency("foundationlibc", .{ @@ -54,32 +44,35 @@ pub fn build(b: *std.Build) void { .optimize = optimize, .single_threaded = true, }); + const lwip_dep = b.dependency("lwip", .{ .target = target, .optimize = optimize, .include_dir = b.path("src/include"), }); - const lwip_lib = lwip_dep.artifact("lwip"); - lwip_lib.root_module.linkLibrary(foundation_dep.artifact("foundation")); - net_mod.linkLibrary(lwip_lib); + const lwip = lwip_dep.module("lwip"); + lwip.linkLibrary(foundation_dep.artifact("foundation")); - const lwip_mod = lwip_lib.root_module; // MEM_ALIGNMENT of 4 bytes allows us to use packet buffers in u32 dma. - lwip_mod.addCMacro("MEM_ALIGNMENT", "4"); - lwip_mod.addCMacro("MEM_SIZE", to_s(&buf, mem_size)); - lwip_mod.addCMacro("PBUF_POOL_SIZE", to_s(&buf, pbuf_pool_size)); - lwip_mod.addCMacro("PBUF_LINK_HLEN", to_s(&buf, ethernet_header)); - lwip_mod.addCMacro("PBUF_POOL_BUFSIZE", to_s(&buf, pbuf_length)); - lwip_mod.addCMacro("PBUF_LINK_ENCAPSULATION_HLEN", to_s(&buf, pbuf_header_length)); + lwip.addCMacro("MEM_ALIGNMENT", "4"); + lwip.addCMacro("MEM_SIZE", to_s(&buf, mem_size)); + lwip.addCMacro("PBUF_POOL_SIZE", to_s(&buf, pbuf_pool_size)); + lwip.addCMacro("PBUF_LINK_HLEN", to_s(&buf, ethernet_header)); + lwip.addCMacro("PBUF_POOL_BUFSIZE", to_s(&buf, pbuf_length)); + lwip.addCMacro("PBUF_LINK_ENCAPSULATION_HLEN", to_s(&buf, pbuf_header_length)); // 40 bytes IPv6 header, 20 bytes TCP header - lwip_mod.addCMacro("TCP_MSS", to_s(&buf, mtu - 40 - 20)); + lwip.addCMacro("TCP_MSS", to_s(&buf, mtu - 40 - 20)); - // Copy macros from lwip to net, so we have same values when calling - // translate-c from cImport. - for (lwip_mod.c_macros.items) |m| { - net_mod.c_macros.append(b.allocator, m) catch @panic("out of memory"); - } + const net_mod = b.addModule("net", .{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/root.zig"), + .imports = &.{ + .{ .name = "link", .module = b.dependency("link", .{}).module("link") }, + .{ .name = "lwip", .module = lwip }, + }, + }); const options = b.addOptions(); options.addOption(u16, "mtu", mtu); diff --git a/modules/network/src/root.zig b/modules/network/src/root.zig index 339b4c39f..af3a46969 100644 --- a/modules/network/src/root.zig +++ b/modules/network/src/root.zig @@ -9,17 +9,7 @@ fn assert_panic(ok: bool, msg: []const u8) void { if (!ok) @panic(msg); } -pub const lwip = @cImport({ - @cInclude("lwip/init.h"); - @cInclude("lwip/tcpip.h"); - @cInclude("lwip/netif.h"); - @cInclude("lwip/dhcp.h"); - @cInclude("lwip/tcp.h"); - @cInclude("lwip/udp.h"); - @cInclude("lwip/etharp.h"); - @cInclude("lwip/ethip6.h"); - @cInclude("lwip/timeouts.h"); -}); +pub const lwip = @import("lwip").c; const log = std.log.scoped(.lwip); diff --git a/port/espressif/esp/build.zig b/port/espressif/esp/build.zig index b945aba06..07571b959 100644 --- a/port/espressif/esp/build.zig +++ b/port/espressif/esp/build.zig @@ -208,7 +208,6 @@ fn make_esp_wifi_driver_module( .root_source_file = esp_wifi_sys_dep.path("c/include/include.h"), .target = esp32_c3_resolved_zig_target, .optimize = .Debug, - .link_libc = false, }); translate_c.addIncludePath(b.path("src/hal/radio/libc_dummy_include")); From c09bf4172831d3862e398b5776570e6da77a229f Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 22:38:27 -0700 Subject: [PATCH 42/61] Remove last ** --- port/nxp/mcx/src/mcxn947/scripts/generate.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/nxp/mcx/src/mcxn947/scripts/generate.zig b/port/nxp/mcx/src/mcxn947/scripts/generate.zig index d5cba184c..0595aeb63 100644 --- a/port/nxp/mcx/src/mcxn947/scripts/generate.zig +++ b/port/nxp/mcx/src/mcxn947/scripts/generate.zig @@ -50,7 +50,7 @@ pub fn print_fields(comptime ty: []const u8, comptime suffix_: ?[]const u8) []Fi } const fields = fields_[0..len]; var last_i = fields[0].i; - const spaces = " " ** 20; + const spaces: [20]u8 = @splat(' '); for (fields) |field| { if (last_i != field.i) { last_i = field.i; From 57135f3f7a4cf10a1194b028d2d667a393a332ef Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 22:39:46 -0700 Subject: [PATCH 43/61] Cleanup CI --- .github/workflows/ci.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e60db261..b9f21a743 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,11 +37,6 @@ jobs: uses: mlugg/setup-zig@v2 with: version: ${{ env.ZIG_VERSION }} - - run: zig env - - run: echo $ZIG_GLOBAL_CACHE_DIR - - run: mkdir -p $ZIG_GLOBAL_CACHE_DIR - - run: echo $HOME/.cache/zig - - run: mkdir -p $HOME/.cache/zig - name: Unit Test Regz run: zig build test working-directory: tools/regz From 348d196ce420b37abd5478344d400c851e6ad909 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 22:40:29 -0700 Subject: [PATCH 44/61] Fix code generation --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9f21a743..a5996d53d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,7 +134,7 @@ jobs: with: version: ${{ env.ZIG_VERSION }} - name: Generate Code - run: zig build generate + run: zig build -Dgenerate working-directory: port/stmicro/stm32 - name: Check for code diffs run: | From 91260566a435b11e917f1c31fcf4ee621ad51d93 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 22:48:44 -0700 Subject: [PATCH 45/61] Fix libxml2 --- .github/workflows/ci.yml | 8 ++++++++ tools/regz/build.zig.zon | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5996d53d..bb372c2d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,6 +164,14 @@ jobs: - name: Build run: zig build -Doptimize=ReleaseSmall + # Make sure that we are building examples and invoking tests for each port + validate-ports-checks: + name: Validate Port Checks + continue-on-error: true + runs-on: ubuntu-latest + steps: + - run: apt install -y yq + unit-test-ports: name: Unit Test Ports continue-on-error: true diff --git a/tools/regz/build.zig.zon b/tools/regz/build.zig.zon index 83827b98b..5d37f4f2a 100644 --- a/tools/regz/build.zig.zon +++ b/tools/regz/build.zig.zon @@ -10,8 +10,8 @@ }, .dependencies = .{ .libxml2 = .{ - .url = "git+https://github.com/allyourcodebase/libxml2.git#675b1709603929393613d0ab00a61ff11491bbbe", - .hash = "libxml2-2.15.1-2-qHdjhvNVAADdvYgiVeAqxhST_JM3VhVplmc1REvwtAYr", + .url = "git+https://github.com/allyourcodebase/libxml2.git#b4c3088d6b7135a7e0a343f262d0b88e890d1eef", + .hash = "libxml2-2.15.1-2-qHdjhtpVAAAwBCQRC2r9Dsf235zPKmG_u8WnMVEwIjwI", }, .zqlite = .{ .url = "git+https://github.com/karlseguin/zqlite.zig#5ac4cabe95a6d7faa7baf0da8057a8e6e8a227a1", From a8bc23f361493ee40c19e3f9dccfca01e2f9cfaa Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 22:59:11 -0700 Subject: [PATCH 46/61] update libxml2 --- tools/regz/build.zig.zon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/regz/build.zig.zon b/tools/regz/build.zig.zon index 5d37f4f2a..6e3fe2193 100644 --- a/tools/regz/build.zig.zon +++ b/tools/regz/build.zig.zon @@ -10,8 +10,8 @@ }, .dependencies = .{ .libxml2 = .{ - .url = "git+https://github.com/allyourcodebase/libxml2.git#b4c3088d6b7135a7e0a343f262d0b88e890d1eef", - .hash = "libxml2-2.15.1-2-qHdjhtpVAAAwBCQRC2r9Dsf235zPKmG_u8WnMVEwIjwI", + .url = "git+https://github.com/allyourcodebase/libxml2.git#65209841954cc881d86ffe503c3ff05e04f47fee", + .hash = "libxml2-2.15.1-2-qHdjhpJWAABjdzShtxe-X_ZE3pJrGfLgwO4H4ZM6HjG9", }, .zqlite = .{ .url = "git+https://github.com/karlseguin/zqlite.zig#5ac4cabe95a6d7faa7baf0da8057a8e6e8a227a1", From ab4202ac8955c1f096697c3c53b6662d7ecdb68e Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 23:38:24 -0700 Subject: [PATCH 47/61] Fix windows issues in CI --- .github/workflows/ci.yml | 2 +- port/espressif/esp/build.zig | 1 + tools/regz/src/VirtualFilesystem.zig | 14 +++++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb372c2d4..9014cb1fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,7 +170,7 @@ jobs: continue-on-error: true runs-on: ubuntu-latest steps: - - run: apt install -y yq + - run: sudo apt install -y yq unit-test-ports: name: Unit Test Ports diff --git a/port/espressif/esp/build.zig b/port/espressif/esp/build.zig index 07571b959..b945aba06 100644 --- a/port/espressif/esp/build.zig +++ b/port/espressif/esp/build.zig @@ -208,6 +208,7 @@ fn make_esp_wifi_driver_module( .root_source_file = esp_wifi_sys_dep.path("c/include/include.h"), .target = esp32_c3_resolved_zig_target, .optimize = .Debug, + .link_libc = false, }); translate_c.addIncludePath(b.path("src/hal/radio/libc_dummy_include")); diff --git a/tools/regz/src/VirtualFilesystem.zig b/tools/regz/src/VirtualFilesystem.zig index 481c1b34e..65ae2b76c 100644 --- a/tools/regz/src/VirtualFilesystem.zig +++ b/tools/regz/src/VirtualFilesystem.zig @@ -12,9 +12,17 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const Map = std.AutoArrayHashMapUnmanaged; const assert = std.debug.assert; - const log = std.log.scoped(.vfs); +const builtin = @import("builtin"); + +fn id_from_handle(handle: std.posix.fd_t) ID { + return switch (builtin.os.tag) { + .windows => @enumFromInt(@intFromPtr(handle)), + else => @enumFromInt(handle), + }; +} + pub const Kind = enum { file, directory, @@ -29,7 +37,7 @@ pub const Dir = struct { fn create_file(userdata: ?*anyopaque, dir: std.Io.Dir, sub_path: []const u8, _: std.Io.Dir.CreateFileOptions) std.Io.File.OpenError!std.Io.File { const vfs: *VirtualFilesystem = @ptrCast(@alignCast(userdata.?)); - const dir_id: ID = @enumFromInt(dir.handle); + const dir_id = id_from_handle(dir.handle); if (std.mem.findScalar(u8, sub_path, '/') != null) { log.err("path includes '/': '{s}'", .{sub_path}); @@ -55,7 +63,7 @@ pub const Dir = struct { _: std.Io.Dir.OpenOptions, ) std.Io.Dir.CreateDirPathOpenError!std.Io.Dir { const vfs: *VirtualFilesystem = @ptrCast(@alignCast(userdata.?)); - const parent: ID = @enumFromInt(parent_dir.handle); + const parent = id_from_handle(parent_dir.handle); const id = vfs.create_dir(parent, sub_path) catch return error.NoSpaceLeft; return .{ From dee4e504a1c8fcaa21e83d2ffc873f2881f0ce6f Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Fri, 29 May 2026 23:50:41 -0700 Subject: [PATCH 48/61] More fixes --- tools/regz/src/VirtualFilesystem.zig | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/regz/src/VirtualFilesystem.zig b/tools/regz/src/VirtualFilesystem.zig index 65ae2b76c..6650c6d25 100644 --- a/tools/regz/src/VirtualFilesystem.zig +++ b/tools/regz/src/VirtualFilesystem.zig @@ -23,6 +23,13 @@ fn id_from_handle(handle: std.posix.fd_t) ID { }; } +fn handle_from_id(id: ID) std.posix.fd_t { + return switch (builtin.os.tag) { + .windows => @ptrFromInt(@intFromEnum(id)), + else => @intFromEnum(id), + }; +} + pub const Kind = enum { file, directory, @@ -48,7 +55,7 @@ pub const Dir = struct { error.OutOfMemory => return error.NoSpaceLeft, }; return .{ - .handle = @intFromEnum(id), + .handle = handle_from_id(id), .flags = .{ .nonblocking = false, }, @@ -67,7 +74,7 @@ pub const Dir = struct { const id = vfs.create_dir(parent, sub_path) catch return error.NoSpaceLeft; return .{ - .handle = @intFromEnum(id), + .handle = handle_from_id(id), }; } @@ -90,7 +97,7 @@ fn operate(userdata: ?*anyopaque, op: std.Io.Operation) std.Io.Cancelable!std.Io const vfs: *VirtualFilesystem = @ptrCast(@alignCast(userdata.?)); return switch (op) { .file_write_streaming => |write_op| blk: { - const file = vfs.files.getPtr(@enumFromInt(write_op.file.handle)).?; + const file = vfs.files.getPtr(id_from_handle(write_op.file.handle)).?; const header = write_op.header; const data = write_op.data; const splat = write_op.splat; @@ -127,7 +134,7 @@ pub fn deinit(fs: *VirtualFilesystem) void { pub fn root_dir(fs: *VirtualFilesystem) std.Io.Dir { _ = fs; - return .{ .handle = @intFromEnum(ID.root) }; + return .{ .handle = handle_from_id(ID.root) }; } pub fn get_file(fs: *VirtualFilesystem, path: []const u8) !?ID { From ce5a253a62b758f9826ee4028e576c55a93e59c4 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 00:03:11 -0700 Subject: [PATCH 49/61] esp examples building --- examples/espressif/esp/build.zig | 6 +++--- examples/espressif/esp/src/lwip/include.zig | 13 +------------ modules/lwip/include/lwip.h | 11 ++++++----- port/espressif/esp/src/hal/rtos.zig | 2 +- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/examples/espressif/esp/build.zig b/examples/espressif/esp/build.zig index 20cbe3234..41a4e6d44 100644 --- a/examples/espressif/esp/build.zig +++ b/examples/espressif/esp/build.zig @@ -71,10 +71,10 @@ pub fn build(b: *std.Build) void { }); const libc_lib = foundation_dep.artifact("foundation"); - const lwip_lib = lwip_dep.artifact("lwip"); + const lwip = lwip_dep.module("lwip"); - lwip_lib.root_module.linkLibrary(libc_lib); - fw.exe.root_module.linkLibrary(lwip_lib); + lwip.linkLibrary(libc_lib); + fw.exe.root_module.addImport("lwip", lwip); } // `installFirmware()` is the MicroZig pendant to `Build.installArtifact()` diff --git a/examples/espressif/esp/src/lwip/include.zig b/examples/espressif/esp/src/lwip/include.zig index 3d7888c7c..3b33c0808 100644 --- a/examples/espressif/esp/src/lwip/include.zig +++ b/examples/espressif/esp/src/lwip/include.zig @@ -1,15 +1,4 @@ -pub const c = @cImport({ - @cInclude("lwip/init.h"); - @cInclude("lwip/tcpip.h"); - @cInclude("lwip/netifapi.h"); - @cInclude("lwip/netif.h"); - @cInclude("lwip/dhcp.h"); - @cInclude("lwip/tcp.h"); - @cInclude("lwip/udp.h"); - @cInclude("lwip/etharp.h"); - @cInclude("lwip/ethip6.h"); - @cInclude("lwip/timeouts.h"); -}); +pub const c = @import("lwip").c; pub fn c_err(res: c.err_t) Error!void { return switch (res) { diff --git a/modules/lwip/include/lwip.h b/modules/lwip/include/lwip.h index a21f30f23..b80d90c87 100644 --- a/modules/lwip/include/lwip.h +++ b/modules/lwip/include/lwip.h @@ -1,14 +1,15 @@ #ifndef _MICROZIG_LWIP_H #define _MICROZIG_LWIP_H -#include -#include -#include #include -#include -#include #include #include +#include +#include +#include +#include +#include #include +#include #endif diff --git a/port/espressif/esp/src/hal/rtos.zig b/port/espressif/esp/src/hal/rtos.zig index 1d58708c0..d087fb0fb 100644 --- a/port/espressif/esp/src/hal/rtos.zig +++ b/port/espressif/esp/src/hal/rtos.zig @@ -752,7 +752,7 @@ pub const ReadyTaskConstraint = union(enum) { pub const ReadyPriorityQueue = if (ready_queue_use_buckets) struct { const ReadySet = std.EnumSet(Priority); - ready: ReadySet = .initEmpty(), + ready: ReadySet = .empty, lists: std.EnumArray(Priority, DoublyLinkedList) = .initFill(.{}), pub fn max_ready_priority(pq: *ReadyPriorityQueue) ?Priority { From eb40e5f7d6e38d309f4302f158dd1e425546fb53 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 00:37:04 -0700 Subject: [PATCH 50/61] Update serial --- tools/printer/build.zig.zon | 4 ++-- tools/printer/tests/test_program.dwarf32.zon | 22 ++++++++++---------- tools/printer/tests/test_program.dwarf64.zon | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/printer/build.zig.zon b/tools/printer/build.zig.zon index 21864693d..740e760ce 100644 --- a/tools/printer/build.zig.zon +++ b/tools/printer/build.zig.zon @@ -5,8 +5,8 @@ .minimum_zig_version = "0.15.1", .dependencies = .{ .serial = .{ - .url = "git+https://github.com/ZigEmbeddedGroup/serial#4c4caabad4a78e699034a95ba7145bf07cdd8e78", - .hash = "serial-0.0.1-PoeRzPq5AAAHeo07adkaBjANT4JUaOpNWcnxQGqjxcQY", + .url = "git+https://github.com/ZigEmbeddedGroup/serial#25b58d0ea62f7bfc33e6c147c1c02193a50c65fb", + .hash = "serial-0.0.1-PoeRzD66AACCQUHzsIssi6bOcEtnQFPebT6WLvno0I_p", }, // used to compile the test program // .microzig = .{ .path = "../..", .lazy = true }, diff --git a/tools/printer/tests/test_program.dwarf32.zon b/tools/printer/tests/test_program.dwarf32.zon index 9e4453876..bfbcd992d 100644 --- a/tools/printer/tests/test_program.dwarf32.zon +++ b/tools/printer/tests/test_program.dwarf32.zon @@ -1,68 +1,68 @@ -.{ .zig_version = "0.16.0", .tests = .{ - .{ .address = 16924672, .expected = .{ +.{ .zig_version = "0.17.0-dev.420+8086ae176", .tests = .{ + .{ .address = 16928768, .expected = .{ .line = 163, .column = 33, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924745, .expected = .{ + .{ .address = 16928841, .expected = .{ .line = 164, .column = 13, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924753, .expected = .{ + .{ .address = 16928849, .expected = .{ .line = 164, .column = 67, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924773, .expected = .{ + .{ .address = 16928869, .expected = .{ .line = 165, .column = 13, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924781, .expected = .{ + .{ .address = 16928877, .expected = .{ .line = 165, .column = 67, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924801, .expected = .{ + .{ .address = 16928897, .expected = .{ .line = 166, .column = 40, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924801, .expected = .{ + .{ .address = 16928897, .expected = .{ .line = 166, .column = 40, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924809, .expected = .{ + .{ .address = 16928905, .expected = .{ .line = 166, .column = 52, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924815, .expected = .{ + .{ .address = 16928911, .expected = .{ .line = 166, .column = 52, .file_path = "ubsan_rt.zig", .function_name = null, .module_name = "ubsan_rt.zig", } }, - .{ .address = 16924918, .expected = .{ + .{ .address = 16929014, .expected = .{ .line = 167, .column = 18, .file_path = "ubsan_rt.zig", diff --git a/tools/printer/tests/test_program.dwarf64.zon b/tools/printer/tests/test_program.dwarf64.zon index d5f4ad06c..876730f06 100644 --- a/tools/printer/tests/test_program.dwarf64.zon +++ b/tools/printer/tests/test_program.dwarf64.zon @@ -1 +1 @@ -.{ .zig_version = "0.16.0", .tests = .{} } +.{ .zig_version = "0.17.0-dev.420+8086ae176", .tests = .{} } From 52361dda2d8847372c1b444d70d9069ca0a173d3 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 08:08:12 -0700 Subject: [PATCH 51/61] Try vfs workaround on windows --- tools/regz/src/VirtualFilesystem.zig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/regz/src/VirtualFilesystem.zig b/tools/regz/src/VirtualFilesystem.zig index 6650c6d25..4b8cffa2b 100644 --- a/tools/regz/src/VirtualFilesystem.zig +++ b/tools/regz/src/VirtualFilesystem.zig @@ -4,7 +4,7 @@ directories: Map(ID, Dir) = .empty, files: Map(ID, File) = .empty, // child -> parent hierarchy: Map(ID, ID) = .empty, -next_id: u16 = 1, +next_id: u16 = 2, const VirtualFilesystem = @This(); @@ -113,7 +113,11 @@ fn operate(userdata: ?*anyopaque, op: std.Io.Operation) std.Io.Cancelable!std.Io } pub const ID = enum(u16) { - root = 0, + // Don't use this one, because on windows, fd_t is actually a *anyopaque, + // and setting that null under the hood is ILLEGAL, and I don't want to go + // to jail. + invalid = 0, + root = 1, _, }; From 3bca2f67e70cf7d6782b57e310fe735f9e604d78 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 08:28:55 -0700 Subject: [PATCH 52/61] Pass thru args and printer test updates for master churn --- sim/aviron/build.zig | 4 +--- tools/linter/build.zig | 4 +--- tools/printer/tests/test_program.dwarf32.zon | 2 +- tools/printer/tests/test_program.dwarf64.zon | 2 +- tools/regz/build.zig | 4 +--- tools/sorcerer/build.zig | 10 +++------- 6 files changed, 8 insertions(+), 18 deletions(-) diff --git a/sim/aviron/build.zig b/sim/aviron/build.zig index fdc329d1a..54ace84a6 100644 --- a/sim/aviron/build.zig +++ b/sim/aviron/build.zig @@ -73,9 +73,7 @@ pub fn build(b: *Build) !void { const run_cmd = b.addRunArtifact(aviron_exe); run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } + run_cmd.addPassthruArgs(); run_step.dependOn(&run_cmd.step); const avr_target = b.resolveTargetQuery(avr_target_query); diff --git a/tools/linter/build.zig b/tools/linter/build.zig index 0d09686b1..8673e3be4 100644 --- a/tools/linter/build.zig +++ b/tools/linter/build.zig @@ -18,10 +18,8 @@ pub fn build(b: *std.Build) void { b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); + run_cmd.addPassThruArgs(); run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); diff --git a/tools/printer/tests/test_program.dwarf32.zon b/tools/printer/tests/test_program.dwarf32.zon index bfbcd992d..4352ed34b 100644 --- a/tools/printer/tests/test_program.dwarf32.zon +++ b/tools/printer/tests/test_program.dwarf32.zon @@ -1,4 +1,4 @@ -.{ .zig_version = "0.17.0-dev.420+8086ae176", .tests = .{ +.{ .zig_version = "0.17.0-dev.607+456b2ec07", .tests = .{ .{ .address = 16928768, .expected = .{ .line = 163, .column = 33, diff --git a/tools/printer/tests/test_program.dwarf64.zon b/tools/printer/tests/test_program.dwarf64.zon index 876730f06..d6c2b0ac8 100644 --- a/tools/printer/tests/test_program.dwarf64.zon +++ b/tools/printer/tests/test_program.dwarf64.zon @@ -1 +1 @@ -.{ .zig_version = "0.17.0-dev.420+8086ae176", .tests = .{} } +.{ .zig_version = "0.17.0-dev.607+456b2ec07", .tests = .{} } diff --git a/tools/regz/build.zig b/tools/regz/build.zig index 58a9b0eaf..a28e937ec 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -68,10 +68,8 @@ pub fn build(b: *Build) !void { b.installArtifact(regz); const run_cmd = b.addRunArtifact(regz); + run_cmd.addPassThruArgs(); run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); diff --git a/tools/sorcerer/build.zig b/tools/sorcerer/build.zig index 0f01c4006..3406647d0 100644 --- a/tools/sorcerer/build.zig +++ b/tools/sorcerer/build.zig @@ -63,10 +63,9 @@ pub fn build(b: *std.Build) void { b.installArtifact(cli_exe); const run_cli_cmd = b.addRunArtifact(cli_exe); + run_cli_cmd.addPassThruArgs(); run_cli_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cli_cmd.addArgs(args); - } + const run_cli_step = b.step("run-cli", "Run the CLI tool"); run_cli_step.dependOn(&run_cli_cmd.step); @@ -153,6 +152,7 @@ pub fn build(b: *std.Build) void { b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); + run_cmd.addPassThruArgs(); // I only want the path to the register schema file, not the lazy path, // because I want to be able to refresh it with `zig build` while sorcerer @@ -160,10 +160,6 @@ pub fn build(b: *std.Build) void { // automatically. run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - const run_step = b.step("run", "Run the GUI app"); run_step.dependOn(&run_cmd.step); From 2c8e99945abd2fe4ceae806beaf7c859011402ab Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 08:37:20 -0700 Subject: [PATCH 53/61] typo and cleanup --- core/src/mmio.zig | 22 +++++++++---------- .../stmicro/stm32/src/stm32f1xx/usb_hid.zig | 6 ++--- tools/linter/build.zig | 2 +- tools/regz/build.zig | 2 +- tools/sorcerer/build.zig | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/src/mmio.zig b/core/src/mmio.zig index a5b1b34ed..0a4695be7 100644 --- a/core/src/mmio.zig +++ b/core/src/mmio.zig @@ -1,40 +1,40 @@ const std = @import("std"); const assert = std.debug.assert; -pub fn Mmio(comptime PackedT: type) type { +pub fn Mmio(comptime Packed: type) type { @setEvalBranchQuota(2_000); - const size = @bitSizeOf(PackedT); + const size = @bitSizeOf(Packed); if ((size % 8) != 0) @compileError("size must be divisible by 8!"); if (!std.math.isPowerOfTwo(size / 8)) @compileError("size must encode a power of two number of bytes!"); - const IntT = @Int(.unsigned, size); + const Int = @Int(.unsigned, size); - if (@sizeOf(PackedT) != (size / 8)) - @compileError(std.fmt.comptimePrint("IntT and PackedT must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(PackedT) })); + if (@sizeOf(Packed) != (size / 8)) + @compileError(std.fmt.comptimePrint("Int and Packed must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(Packed) })); return extern struct { const Self = @This(); - raw: IntT, + raw: Int, - pub const underlying_type = PackedT; + pub const underlying_type = Packed; - pub inline fn read(addr: *volatile Self) PackedT { + pub inline fn read(addr: *volatile Self) Packed { return @bitCast(addr.raw); } - pub inline fn write(addr: *volatile Self, val: PackedT) void { + pub inline fn write(addr: *volatile Self, val: Packed) void { comptime { - assert(@bitSizeOf(PackedT) == @bitSizeOf(IntT)); + assert(@bitSizeOf(Packed) == @bitSizeOf(Int)); } addr.write_raw(@bitCast(val)); } - pub inline fn write_raw(addr: *volatile Self, val: IntT) void { + pub inline fn write_raw(addr: *volatile Self, val: Int) void { addr.raw = val; } diff --git a/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig b/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig index a5d8bfd51..ead85e656 100644 --- a/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig +++ b/examples/stmicro/stm32/src/stm32f1xx/usb_hid.zig @@ -139,7 +139,7 @@ const ReportDescriptor = [63]u8{ //=============== USB DATA ================= var EP0_RX_BUFFER: [64]u8 = undefined; var USB_RX_BUFFER: [64]u8 = undefined; -var HID_send: [8]u8 = @splat(0); +var hid_send: [8]u8 = @splat(0); var to_report: bool = false; var device_addr: ?u7 = null; var config: bool = false; @@ -254,9 +254,9 @@ fn report(keys: []const u8) void { const report_flag: *volatile bool = &to_report; if (!config) return; while (report_flag.*) {} - std.mem.copyForwards(u8, HID_send[3..], keys[0..len]); + std.mem.copyForwards(u8, hid_send[3..], keys[0..len]); report_flag.* = true; - epc.USB_send(&HID_send, .no_change) catch unreachable; + epc.USB_send(&hid_send, .no_change) catch unreachable; } pub fn main() !void { diff --git a/tools/linter/build.zig b/tools/linter/build.zig index 8673e3be4..77477e9e7 100644 --- a/tools/linter/build.zig +++ b/tools/linter/build.zig @@ -18,7 +18,7 @@ pub fn build(b: *std.Build) void { b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); - run_cmd.addPassThruArgs(); + run_cmd.addPassthruArgs(); run_cmd.step.dependOn(b.getInstallStep()); const run_step = b.step("run", "Run the app"); diff --git a/tools/regz/build.zig b/tools/regz/build.zig index a28e937ec..c161571c1 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -68,7 +68,7 @@ pub fn build(b: *Build) !void { b.installArtifact(regz); const run_cmd = b.addRunArtifact(regz); - run_cmd.addPassThruArgs(); + run_cmd.addPassthruArgs(); run_cmd.step.dependOn(b.getInstallStep()); const run_step = b.step("run", "Run the app"); diff --git a/tools/sorcerer/build.zig b/tools/sorcerer/build.zig index 3406647d0..6f4980879 100644 --- a/tools/sorcerer/build.zig +++ b/tools/sorcerer/build.zig @@ -63,7 +63,7 @@ pub fn build(b: *std.Build) void { b.installArtifact(cli_exe); const run_cli_cmd = b.addRunArtifact(cli_exe); - run_cli_cmd.addPassThruArgs(); + run_cli_cmd.addPassthruArgs(); run_cli_cmd.step.dependOn(b.getInstallStep()); const run_cli_step = b.step("run-cli", "Run the CLI tool"); @@ -152,7 +152,7 @@ pub fn build(b: *std.Build) void { b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); - run_cmd.addPassThruArgs(); + run_cmd.addPassthruArgs(); // I only want the path to the register schema file, not the lazy path, // because I want to be able to refresh it with `zig build` while sorcerer From 72f51f4ccb083ce5e05ce2f362407697f62bd234 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 09:22:53 -0700 Subject: [PATCH 54/61] Remove unused file --- tools/regz/src/mmio.zig | 49 ----------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 tools/regz/src/mmio.zig diff --git a/tools/regz/src/mmio.zig b/tools/regz/src/mmio.zig deleted file mode 100644 index c5753b07e..000000000 --- a/tools/regz/src/mmio.zig +++ /dev/null @@ -1,49 +0,0 @@ -const std = @import("std"); - -pub fn Mmio(comptime size: u8, comptime PackedT: type) type { - if ((size % 8) != 0) - @compileError("size must be divisible by 8!"); - - if (!std.math.isPowerOfTwo(size / 8)) - @compileError("size must encode a power of two number of bytes!"); - - const IntT = @Int(.unsigned, size); - - if (@sizeOf(PackedT) != (size / 8)) - @compileError(std.fmt.comptimePrint("IntT and PackedT must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(PackedT) })); - - return extern struct { - const Self = @This(); - - raw: IntT, - - pub const underlying_type = PackedT; - - pub inline fn read(addr: *volatile Self) PackedT { - return @as(PackedT, @bitCast(addr.raw)); - } - - pub inline fn write(addr: *volatile Self, val: PackedT) void { - // This is a workaround for a compiler bug related to miscompilation - // If the tmp var is not used, result location will fuck things up - const tmp = @as(IntT, @bitCast(val)); - addr.raw = tmp; - } - - pub inline fn modify(addr: *volatile Self, fields: anytype) void { - var val = read(addr); - inline for (@typeInfo(@TypeOf(fields)).@"struct".fields) |field| { - @field(val, field.name) = @field(fields, field.name); - } - write(addr, val); - } - - pub inline fn toggle(addr: *volatile Self, fields: anytype) void { - var val = read(addr); - inline for (@typeInfo(@TypeOf(fields)).@"struct".fields) |field| { - @field(val, field.name) = @field(val, field.name) ^ @field(fields, field.name); - } - write(addr, val); - } - }; -} From e15266c591acd67ac7eb0eba7544acd30045b554 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 09:34:22 -0700 Subject: [PATCH 55/61] Update libxml2 --- tools/regz/build.zig | 1 - tools/regz/build.zig.zon | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/regz/build.zig b/tools/regz/build.zig index c161571c1..ab9f02247 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -10,7 +10,6 @@ pub fn build(b: *Build) !void { const libxml2_dep = b.dependency("libxml2", .{ .target = target, .optimize = .ReleaseSafe, - .iconv = false, }); const zqlite_dep = b.dependency("zqlite", .{ diff --git a/tools/regz/build.zig.zon b/tools/regz/build.zig.zon index 6e3fe2193..7336b1600 100644 --- a/tools/regz/build.zig.zon +++ b/tools/regz/build.zig.zon @@ -10,8 +10,8 @@ }, .dependencies = .{ .libxml2 = .{ - .url = "git+https://github.com/allyourcodebase/libxml2.git#65209841954cc881d86ffe503c3ff05e04f47fee", - .hash = "libxml2-2.15.1-2-qHdjhpJWAABjdzShtxe-X_ZE3pJrGfLgwO4H4ZM6HjG9", + .url = "git+https://github.com/allyourcodebase/libxml2.git#e682540d7b912fe890967c3c0dd07b23c8b2de50", + .hash = "libxml2-2.15.1-2-qHdjhgtWAADAdXw_2NzEGoIh4hme4ypvYNc-N1dCt-m7", }, .zqlite = .{ .url = "git+https://github.com/karlseguin/zqlite.zig#5ac4cabe95a6d7faa7baf0da8057a8e6e8a227a1", From 0ae7be01e96ad73e62e8245acfc0b6a92afcfe85 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 11:04:50 -0700 Subject: [PATCH 56/61] Consider keeping website on 0.15.2 for now --- .github/workflows/deploy.yml | 42 ---------------------- .github/workflows/publish-github-pages.yml | 2 +- sim/aviron/src/testconfig.zig | 2 +- 3 files changed, 2 insertions(+), 44 deletions(-) delete mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index d36c80ccb..000000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Continuous Deployment - -permissions: - contents: write - -on: - push: - tags: - - "*.*.*" - -jobs: - deploy-packages: - runs-on: macos-latest - steps: - - name: Extract tag name - run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Zig - uses: mlugg/setup-zig@v2 - with: - version: master - - - name: Extract version - run: echo "MICROZIG_VERSION=$(zig build package -- get-version)" >> $GITHUB_ENV - - - name: Assemble Packages - run: zig build package -- https://github.com/ZigEmbeddedGroup/microzig/releases/download - - - name: Create Release Draft - uses: ncipollo/release-action@v1 - id: create_release - with: - tag: ${{ env.TAG_NAME }} - artifactErrorsFailBuild: true - draft: true - generateReleaseNotes: true - artifacts: boxzer-out/${{ env.MICROZIG_VERSION }}/* diff --git a/.github/workflows/publish-github-pages.yml b/.github/workflows/publish-github-pages.yml index a58d2dcd4..3f646d281 100644 --- a/.github/workflows/publish-github-pages.yml +++ b/.github/workflows/publish-github-pages.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: master + version: 0.15.2 - name: Download and install GitHub CLI run: | diff --git a/sim/aviron/src/testconfig.zig b/sim/aviron/src/testconfig.zig index 9ed10aba2..a28daf448 100644 --- a/sim/aviron/src/testconfig.zig +++ b/sim/aviron/src/testconfig.zig @@ -89,7 +89,7 @@ pub const TestSuiteConfig = struct { }) catch @panic("oom"); } - pub fn load(allocator: std.mem.Allocator, io: std.Io, file: std.Io.File) !TestSuiteConfig { + pub fn load(allocator: std.mem.Allocator, io: std.Io, file: *std.Io.File) !TestSuiteConfig { var buf: [4096]u8 = undefined; var file_reader = file.reader(io, &buf); var json_reader = std.json.Reader.init(allocator, &file_reader.interface); From 5f8f7bfaabff6c8bee18ee43b958fc3607d72ea2 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 11:16:59 -0700 Subject: [PATCH 57/61] revert zine --- website/build.zig.zon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/build.zig.zon b/website/build.zig.zon index 98484bde0..12a21d013 100644 --- a/website/build.zig.zon +++ b/website/build.zig.zon @@ -13,8 +13,8 @@ }, .dependencies = .{ .zine = .{ - .url = "git+https://github.com/kristoff-it/zine#a16c9f1d3f3166337da47fda2de0f4addc719b92", - .hash = "zine-0.11.2-ou6nIARkLQF8Kl5xN7pmSCun5lNjZvJOpQaug8--F2m2", + .url = "git+https://github.com/kristoff-it/zine#b96e930630f8237aa4927fe14b9cb227061155d3", + .hash = "zine-0.11.1-ou6nIBB5FgAaYePTyiT2__fkGVNfImMOnpc_xKNXsYpF", }, }, } From 48c5d1e619551a1e576b11a0ca6ad191b478e063 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 13:19:26 -0700 Subject: [PATCH 58/61] Clone HEAD of zigimports --- .github/workflows/unused-imports.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unused-imports.yml b/.github/workflows/unused-imports.yml index 2bda6f225..29b550ab6 100644 --- a/.github/workflows/unused-imports.yml +++ b/.github/workflows/unused-imports.yml @@ -25,7 +25,7 @@ jobs: - name: Build zigimports run: | - git clone --depth 1 --revision 0c56cb27d932f69e572fb1247213075624011f7f https://github.com/tusharsadhwani/zigimports.git /tmp/zigimports + git clone --depth 1 https://github.com/tusharsadhwani/zigimports.git /tmp/zigimports cd /tmp/zigimports zig build --release=safe # Binary is named zigimports--, find and symlink it From 451840becbd82e6da82c867fc3357dabd3278572 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 13:41:33 -0700 Subject: [PATCH 59/61] Get rid of messy linter CI logic --- .github/workflows/lint.yml | 316 ------------------------------------- 1 file changed, 316 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 781df4bfe..17daa71c1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -57,319 +57,3 @@ jobs: # Debug output echo "Raw lint results:" cat lint_results_raw.json - - - name: Filter lint results to changed lines - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - const { execSync } = require('child_process'); - - // Change to pr directory - process.chdir('pr'); - - if (!fs.existsSync('lint_results_raw.json')) { - fs.writeFileSync('lint_results.json', '[]'); - console.log('No raw lint results found'); - return; - } - - const rawIssues = JSON.parse(fs.readFileSync('lint_results_raw.json', 'utf8')); - - if (rawIssues.length === 0) { - fs.writeFileSync('lint_results.json', '[]'); - console.log('No lint issues found'); - return; - } - - console.log(`Found ${rawIssues.length} total lint issue(s)`); - - const baseSha = '${{ github.event.pull_request.base.sha }}'; - const headSha = '${{ github.event.pull_request.head.sha }}'; - - // Get the list of files actually changed in this PR - let changedFiles; - try { - const changedFilesOutput = execSync( - `git diff --name-only --diff-filter=d ${baseSha} ${headSha}`, - { encoding: 'utf8' } - ); - changedFiles = new Set(changedFilesOutput.trim().split('\n').filter(f => f)); - console.log(`PR contains ${changedFiles.size} changed file(s)`); - } catch (error) { - console.log(`Could not get changed files: ${error.message}`); - changedFiles = new Set(); - } - - // Parse diff to get added/modified line numbers per file - // We parse the actual diff content to find lines starting with '+' (additions) - const changedLines = {}; - - for (const file of changedFiles) { - if (!file.endsWith('.zig')) continue; - - try { - // Get the diff with context to properly track line numbers - const diff = execSync( - `git diff --unified=0 ${baseSha} ${headSha} -- "${file}"`, - { encoding: 'utf8' } - ); - - const lines = new Set(); - const diffLines = diff.split('\n'); - let currentNewLine = 0; - - for (const line of diffLines) { - // Match the @@ -oldStart,oldCount +newStart,newCount @@ format - const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/); - if (hunkMatch) { - currentNewLine = parseInt(hunkMatch[1]); - const count = hunkMatch[2] !== undefined ? parseInt(hunkMatch[2]) : 1; - - // With --unified=0, the count represents actual added lines - // Add all lines in this range as they are additions - for (let i = 0; i < count; i++) { - lines.add(currentNewLine + i); - } - continue; - } - } - - changedLines[file] = lines; - if (lines.size > 0) { - console.log(`File ${file}: ${lines.size} added/modified line(s): ${[...lines].slice(0, 10).join(', ')}${lines.size > 10 ? '...' : ''}`); - } - } catch (error) { - console.log(`Could not get diff for ${file}: ${error.message}`); - changedLines[file] = new Set(); - } - } - - // Filter issues to only those: - // 1. In files that are part of this PR - // 2. On lines that were actually added/modified - const filteredIssues = rawIssues.filter(issue => { - // First check: is this file even in the PR? - if (!changedFiles.has(issue.file)) { - console.log(`Filtered out: ${issue.file}:${issue.line} (file not in PR)`); - return false; - } - - // Second check: is this line actually changed? - const fileLines = changedLines[issue.file] || new Set(); - if (!fileLines.has(issue.line)) { - console.log(`Filtered out: ${issue.file}:${issue.line} (line not changed)`); - return false; - } - - return true; - }); - - // Save filtered issues - fs.writeFileSync('lint_results.json', JSON.stringify(filteredIssues, null, 2)); - - const filtered = rawIssues.length - filteredIssues.length; - if (filtered > 0) { - console.log(`Filtered out ${filtered} issue(s) not on changed lines`); - } - - console.log(`Kept ${filteredIssues.length} issue(s) on changed lines for inline comments`); - - - name: Post review with grouped comments - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const fs = require('fs'); - const crypto = require('crypto'); - - // Change to pr directory - process.chdir('pr'); - - // Helper function to delete all existing bot review comments - async function deleteExistingBotComments() { - try { - // List all review comments on this PR - const comments = await github.paginate( - github.rest.pulls.listReviewComments, - { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.issue.number, - per_page: 100 - } - ); - - // Filter to only bot comments with our marker - const botComments = comments.filter(c => - c.user.login === 'github-actions[bot]' - ); - - console.log(`Found ${botComments.length} existing bot review comment(s) to delete`); - - // Delete each bot comment - for (const comment of botComments) { - try { - await github.rest.pulls.deleteReviewComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id - }); - console.log(`Deleted comment ${comment.id}`); - } catch (error) { - console.log(`Could not delete comment ${comment.id}: ${error.message}`); - } - } - } catch (error) { - console.log(`Error deleting bot comments: ${error.message}`); - } - } - - // Helper function to find and update or delete bot issue comment - async function findBotIssueComment() { - try { - const comments = await github.paginate( - github.rest.issues.listComments, - { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - per_page: 100 - } - ); - - return comments.find(c => - c.user.login === 'github-actions[bot]' && - c.body && c.body.includes('') - ); - } catch (error) { - console.log(`Error finding bot comment: ${error.message}`); - return null; - } - } - - if (!fs.existsSync('lint_results.json')) { - console.log('No lint results file found'); - return; - } - - const content = fs.readFileSync('lint_results.json', 'utf8').trim(); - - // Check if there are filtered issues - const hasFilteredIssues = fs.existsSync('filtered_issues.txt'); - const filteredContent = hasFilteredIssues ? fs.readFileSync('filtered_issues.txt', 'utf8') : ''; - - const issues = content && content !== '[]' ? JSON.parse(content) : []; - - // Create hash of current issues to detect changes - const issuesHash = crypto.createHash('md5') - .update(JSON.stringify(issues.map(i => `${i.file}:${i.line}:${i.message}`)) + filteredContent) - .digest('hex') - .substring(0, 8); - - // Find existing bot comment - const existingComment = await findBotIssueComment(); - - // Check if the existing comment already has the same hash - if (existingComment && existingComment.body.includes(``)) { - console.log('Comment already exists with same issues, skipping'); - return; - } - - // Delete all existing bot review comments (inline comments) - await deleteExistingBotComments(); - - // If no issues, delete the summary comment and return - if (issues.length === 0 && !hasFilteredIssues) { - console.log('No lint issues found'); - if (existingComment) { - try { - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existingComment.id - }); - console.log('Deleted existing lint comment (no issues remaining)'); - } catch (error) { - console.log(`Could not delete comment: ${error.message}`); - } - } - return; - } - - // Prepare inline review comments - const reviewComments = []; - const issuesByFile = {}; - - for (const issue of issues) { - if (!issuesByFile[issue.file]) { - issuesByFile[issue.file] = []; - } - issuesByFile[issue.file].push(issue); - - reviewComments.push({ - path: issue.file, - line: issue.line, - side: 'RIGHT', - body: issue.message - }); - } - - // Create summary comment body - const totalIssues = issues.length; - const fileCount = Object.keys(issuesByFile).length; - - let commentBody = `## Lint Results\n\n`; - - if (totalIssues > 0) { - commentBody += `Found **${totalIssues}** issue${totalIssues !== 1 ? 's' : ''} on changed lines in **${fileCount}** file${fileCount !== 1 ? 's' : ''}:\n\n`; - - for (const [file, fileIssues] of Object.entries(issuesByFile)) { - commentBody += `- **${file}**: ${fileIssues.length} issue${fileIssues.length !== 1 ? 's' : ''}\n`; - } - } else { - commentBody += `No issues on changed lines.\n`; - } - - commentBody += `\n\n`; - - // Update or create the summary comment - try { - if (existingComment) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existingComment.id, - body: commentBody - }); - console.log('Updated existing lint summary comment'); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: commentBody - }); - console.log('Created new lint summary comment'); - } - } catch (error) { - console.error(`Failed to update/create summary comment: ${error.message}`); - } - - // Create inline review comments if there are issues - if (reviewComments.length > 0) { - try { - const review = await github.rest.pulls.createReview({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.issue.number, - commit_id: context.payload.pull_request.head.sha, - event: 'COMMENT', - comments: reviewComments - }); - - console.log(`Created review with ${reviewComments.length} inline comment(s)`); - } catch (error) { - console.error(`Failed to create inline comments: ${error.message}`); - } - } From 4a94ab1a7117149b1d1ff926c721c7a94bb41638 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 18:10:04 -0700 Subject: [PATCH 60/61] Freertos and objcopy format from bin to binary --- build-internals/build.zig | 4 +- build.zig | 4 +- examples/raspberrypi/rp2xxx/build.zig | 12 +- modules/freertos/build.zig | 164 ++++++++++++++++++-------- port/espressif/esp/build.zig | 2 +- port/raspberrypi/rp2xxx/build.zig | 2 +- port/wch/ch32v/build.zig | 2 +- sim/aviron/build.zig | 17 +-- sim/aviron/src/testconfig.zig | 2 +- tools/dfu/build.zig | 2 +- 10 files changed, 133 insertions(+), 78 deletions(-) diff --git a/build-internals/build.zig b/build-internals/build.zig index e74fdd18f..481ebb65e 100644 --- a/build-internals/build.zig +++ b/build-internals/build.zig @@ -210,7 +210,7 @@ pub const BinaryFormat = union(enum) { elf, /// A flat binary, contains only the loaded portions of the firmware with an unspecified base offset. - bin, + binary, /// The [Intel HEX](https://en.wikipedia.org/wiki/Intel_HEX) format, contains /// an ASCII description of what memory to load where. @@ -233,7 +233,7 @@ pub const BinaryFormat = union(enum) { pub fn get_extension(format: BinaryFormat) []const u8 { return switch (format) { .elf => ".elf", - .bin, .esp => ".bin", + .binary, .esp => ".bin", .hex => ".hex", .dfu => ".dfu", .uf2 => ".uf2", diff --git a/build.zig b/build.zig index 75a61853f..ee8ebccbb 100644 --- a/build.zig +++ b/build.zig @@ -601,10 +601,10 @@ pub fn MicroBuild(port_select: PortSelect) type { result.value_ptr.* = switch (resolved_format) { .elf => elf_file, - .bin => blk: { + .binary => blk: { const objcopy = fw.mb.builder.addObjCopy(elf_file, .{ .basename = basename, - .format = .bin, + .format = .binary, }); break :blk objcopy.getOutput(); diff --git a/examples/raspberrypi/rp2xxx/build.zig b/examples/raspberrypi/rp2xxx/build.zig index 8072717e5..ad5cd7bfd 100644 --- a/examples/raspberrypi/rp2xxx/build.zig +++ b/examples/raspberrypi/rp2xxx/build.zig @@ -23,15 +23,15 @@ pub fn build(b: *std.Build) void { .{ .target = raspberrypi.pico, .name = "pico_hd44780", .file = "src/rp2040_only/hd44780.zig" }, .{ .target = raspberrypi.pico, .name = "pico_pcf8574", .file = "src/rp2040_only/pcf8574.zig" }, .{ .target = raspberrypi.pico, .name = "pico_i2c_slave", .file = "src/rp2040_only/i2c_slave.zig" }, - //.{ .target = raspberrypi.pico, .name = "pico_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, - //.{ .target = raspberrypi.pico, .name = "pico_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, - //.{ .target = raspberrypi.pico, .name = "pico_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, + .{ .target = raspberrypi.pico, .name = "pico_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, + .{ .target = raspberrypi.pico, .name = "pico_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, + .{ .target = raspberrypi.pico, .name = "pico_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_multicore", .file = "src/blinky_core1.zig" }, .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_board_blinky", .file = "src/board_blinky.zig" }, - //.{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, - //.{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, - //.{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, + .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-hello-task", .file = "src/freertos/hello_task.zig" }, + .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-queue-demo", .file = "src/freertos/queue_demo.zig" }, + .{ .target = raspberrypi.pico2_arm, .name = "pico2_arm_freertos-multitask-demo", .file = "src/freertos/multitask_demo.zig" }, .{ .target = raspberrypi.pico_flashless, .name = "pico_flashless_blinky", .file = "src/blinky.zig" }, diff --git a/modules/freertos/build.zig b/modules/freertos/build.zig index ccc63db24..62a96f40e 100644 --- a/modules/freertos/build.zig +++ b/modules/freertos/build.zig @@ -99,12 +99,9 @@ pub fn build(b: *std.Build) void { // Pico SDK include paths const picosdk_dep = b.dependency("picosdk", .{}); - const picosdk_root = picosdk_dep.path("."); - - if (port_name == .RP2040) { - addPicoSDKIncludeDirs(b, freertos_lib, picosdk_root, .RP2040); - } else if (port_name == .RP2350_ARM or port_name == .RP2350_RISCV) { - addPicoSDKIncludeDirs(b, freertos_lib, picosdk_root, .RP2350); + switch (port_name) { + .RP2040 => addPicoSDKIncludeDirs(b, freertos_lib, picosdk_dep, .RP2040), + .RP2350_ARM, .RP2350_RISCV => addPicoSDKIncludeDirs(b, freertos_lib, picosdk_dep, .RP2350), } // TODO: USE addConfigHeader instead? @@ -152,13 +149,13 @@ const Chip = enum { fn addPicoSDKIncludeDirs( b: *std.Build, mod: *std.Build.Module, - pico_root: std.Build.LazyPath, + pico_sdk: *std.Build.Dependency, chip: Chip, ) void { const wf = b.addWriteFiles(); // Generate version.h - const cmake_version_file = b.addConfigHeader(.{ .style = .{ .cmake = pico_root.path(b, "src/common/pico_base_headers/include/pico/version.h.in") } }, .{ + const cmake_version_file = b.addConfigHeader(.{ .style = .{ .cmake = pico_sdk.path("src/common/pico_base_headers/include/pico/version.h.in") } }, .{ .PICO_SDK_VERSION_STRING = "2.2.0", .PICO_SDK_VERSION_MAJOR = "2", .PICO_SDK_VERSION_MINOR = "2", @@ -168,7 +165,7 @@ fn addPicoSDKIncludeDirs( _ = wf.addCopyFile(cmake_version_file.getOutputFile(), "picosdk_generated/pico/version.h"); // Generate required config_autogen.h (this support custom #include directives) - _ = wf.addCopyFile(pico_root.path(b, "bazel/include/pico/config_autogen.h"), "picosdk_generated/pico/config_autogen.h"); + _ = wf.addCopyFile(pico_sdk.path("bazel/include/pico/config_autogen.h"), "picosdk_generated/pico/config_autogen.h"); _ = wf.add("picosdk_generated/pico/pico_config_extra_headers.h", ""); _ = wf.add("picosdk_generated/pico/pico_config_platform_headers.h", ""); @@ -179,50 +176,115 @@ fn addPicoSDKIncludeDirs( // with our automatic include-path registration logic. Because is expected // to be found directly under "sys/", we copy it into a synthetic include directory with // the correct relative structure. - _ = wf.addCopyFile(pico_root.path(b, "src/rp2_common/pico_clib_interface/include/llvm_libc/sys/cdefs.h"), "llvm_libc/sys/cdefs.h"); + _ = wf.addCopyFile(pico_sdk.path("src/rp2_common/pico_clib_interface/include/llvm_libc/sys/cdefs.h"), "llvm_libc/sys/cdefs.h"); mod.addIncludePath(wf.getDirectory().path(b, "llvm_libc")); // Add all relevant include directories from Pico SDK - addAllIncludeDirs(b, mod, pico_root, "src/common"); - addAllIncludeDirs(b, mod, pico_root, "src/rp2_common"); - - if (chip == .RP2040) { - mod.addCMacro("PICO_RP2040", "1"); - addAllIncludeDirs(b, mod, pico_root, "src/rp2040"); - } else if (chip == .RP2350) { - mod.addCMacro("PICO_RP2350", "1"); - // By default RP2350 is using software spinlocks because of some errata - // don't know what it is exactly but we will force hardware spinlocks anyway - // to simplify compilation of this module - mod.addCMacro("PICO_USE_SW_SPIN_LOCKS", "0"); - addAllIncludeDirs(b, mod, pico_root, "src/rp2350"); - } -} - -fn addAllIncludeDirs( - b: *std.Build, - mod: *std.Build.Module, - base: std.Build.LazyPath, - subdir: []const u8, -) void { - const allocator = b.allocator; - const io = b.graph.io; - const full = std.fs.path.join(allocator, &.{ base.getPath(b), subdir }) catch @panic("join"); - defer allocator.free(full); - - var dir = std.Io.Dir.cwd().openDir(io, full, .{ .iterate = true }) catch return; - defer dir.close(io); - - var walker = dir.walk(allocator) catch @panic("walk"); - defer walker.deinit(); - - while (walker.next(io) catch @panic("next")) |e| { - if (e.kind != .directory) continue; - if (!std.mem.eql(u8, std.fs.path.basename(e.path), "include")) continue; - - const inc = std.fs.path.join(allocator, &.{ full, e.path }) catch @panic("join2"); - defer allocator.free(inc); - - mod.addIncludePath(.{ .cwd_relative = inc }); + mod.addIncludePath(pico_sdk.path("src/common/boot_picobin_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/boot_picoboot_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/boot_uf2_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/hardware_claim/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_base_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_binary_info/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_bit_ops_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_divider_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_stdlib_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_sync/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_time/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_usb_reset_interface_headers/include")); + mod.addIncludePath(pico_sdk.path("src/common/pico_util/include")); + + mod.addIncludePath(pico_sdk.path("src/rp2_common/boot_bootrom_headers/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/cmsis/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_adc/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_base/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_boot_lock/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_clocks/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_dcp/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_divider/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_dma/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_exception/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_flash/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_gpio/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_hazard3/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_i2c/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_interp/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_irq/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_pio/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_pll/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_powman/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_pwm/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_rcp/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_resets/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_riscv/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_riscv_platform_timer/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_rtc/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_sha256/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_spi/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_sync/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_sync_spin_lock/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_ticks/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_timer/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_uart/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_vreg/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_watchdog/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_xip_cache/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/hardware_xosc/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_aon_timer/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_async_context/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_atomic/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_bootrom/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_btstack/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_clib_interface/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_cyw43_arch/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_cyw43_driver/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_double/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_fix/rp2040_usb_device_enumeration/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_flash/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_float/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_i2c_slave/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_int64_ops/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_lwip/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_malloc/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_mbedtls/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_mem_ops/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_multicore/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_platform_common/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_platform_compiler/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_platform_panic/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_platform_sections/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_printf/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_rand/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_runtime/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_runtime_init/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_sha256/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_status_led/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_stdio/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_stdio_rtt/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_stdio_semihosting/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_stdio_uart/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_stdio_usb/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_time_adapter/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/pico_unique_id/include")); + mod.addIncludePath(pico_sdk.path("src/rp2_common/tinyusb/include")); + switch (chip) { + .RP2040 => { + mod.addCMacro("PICO_RP2040", "1"); + mod.addIncludePath(pico_sdk.path("src/rp2040/boot_stage2/include")); + mod.addIncludePath(pico_sdk.path("src/rp2040/hardware_regs/include")); + mod.addIncludePath(pico_sdk.path("src/rp2040/hardware_structs/include")); + mod.addIncludePath(pico_sdk.path("src/rp2040/pico_platform/include")); + }, + .RP2350 => { + mod.addCMacro("PICO_RP2350", "1"); + // By default RP2350 is using software spinlocks because of some errata + // don't know what it is exactly but we will force hardware spinlocks anyway + // to simplify compilation of this module + mod.addCMacro("PICO_USE_SW_SPIN_LOCKS", "0"); + mod.addIncludePath(pico_sdk.path("src/rp2350/boot_stage2/include")); + mod.addIncludePath(pico_sdk.path("src/rp2350/hardware_regs/include")); + mod.addIncludePath(pico_sdk.path("src/rp2350/hardware_structs/include")); + mod.addIncludePath(pico_sdk.path("src/rp2350/pico_platform/include")); + }, } } diff --git a/port/espressif/esp/build.zig b/port/espressif/esp/build.zig index b945aba06..2df4634d2 100644 --- a/port/espressif/esp/build.zig +++ b/port/espressif/esp/build.zig @@ -100,7 +100,7 @@ pub fn init(dep: *std.Build.Dependency) ?Self { .chips = .{ .esp32_c3 = chip_esp32_c3.derive(.{}), .esp32_c3_direct_boot = chip_esp32_c3.derive(.{ - .preferred_binary_format = .bin, + .preferred_binary_format = .binary, .cpu = .{ .name = "esp_riscv", .root_source_file = b.path("src/cpus/esp_riscv.zig"), diff --git a/port/raspberrypi/rp2xxx/build.zig b/port/raspberrypi/rp2xxx/build.zig index 83b3e9e64..fcb3e2ab0 100644 --- a/port/raspberrypi/rp2xxx/build.zig +++ b/port/raspberrypi/rp2xxx/build.zig @@ -343,7 +343,7 @@ fn get_bootrom(b: *std.Build, target: *const microzig.Target, rom: BootROM) std. const rom_objcopy = b.addObjCopy(rom_exe.getEmittedBin(), .{ .basename = b.fmt("{s}.bin", .{@tagName(rom)}), - .format = .bin, + .format = .binary, }); return rom_objcopy.getOutput(); diff --git a/port/wch/ch32v/build.zig b/port/wch/ch32v/build.zig index 8f0a60b89..a683e4b5e 100644 --- a/port/wch/ch32v/build.zig +++ b/port/wch/ch32v/build.zig @@ -40,7 +40,7 @@ const BaseChip = struct { const ret = b.allocator.create(microzig.Target) catch @panic("out of memory"); ret.* = .{ .dep = dep, - .preferred_binary_format = .bin, + .preferred_binary_format = .binary, .zig_target = std.Target.Query{ .cpu_arch = .riscv32, .cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic }, diff --git a/sim/aviron/build.zig b/sim/aviron/build.zig index 54ace84a6..b719781d7 100644 --- a/sim/aviron/build.zig +++ b/sim/aviron/build.zig @@ -156,7 +156,7 @@ fn add_test_suite( // Scan the testsuite directory for files. Based on the extension, either load or compile them. // Files in testsuite.avr-gcc will be compiled with avr-gcc and have the output copied to // this directory. - var walkdir = try b.build_root.handle.openDir(io, "testsuite", .{ .iterate = true }); + var walkdir = try b.root.root_dir.handle.openDir(io, "testsuite", .{ .iterate = true }); defer walkdir.close(io); var walker = try walkdir.walk(b.allocator); @@ -331,19 +331,12 @@ fn add_test_suite_update( b: *Build, invoke_step: *Build.Step, ) !void { - const avr_gcc = if (b.findProgram(&.{"avr-gcc"}, &.{})) |path| LazyPath{ - .cwd_relative = path, - } else |_| b.addExecutable(.{ - .name = "no-avr-gcc", - .root_module = b.createModule(.{ - .root_source_file = b.path("tools/no-avr-gcc.zig"), - .target = b.graph.host, - }), - .use_llvm = true, - }).getEmittedBin(); + const avr_gcc = b.findProgramLazy(.{ + .names = &.{"avr-gcc"}, + }); const io = b.graph.io; - var walkdir = try b.build_root.handle.openDir(io, "testsuite.avr-gcc", .{ .iterate = true }); + var walkdir = try b.root.root_dir.handle.openDir(io, "testsuite.avr-gcc", .{ .iterate = true }); defer walkdir.close(io); var walker = try walkdir.walk(b.allocator); diff --git a/sim/aviron/src/testconfig.zig b/sim/aviron/src/testconfig.zig index a28daf448..9ed10aba2 100644 --- a/sim/aviron/src/testconfig.zig +++ b/sim/aviron/src/testconfig.zig @@ -89,7 +89,7 @@ pub const TestSuiteConfig = struct { }) catch @panic("oom"); } - pub fn load(allocator: std.mem.Allocator, io: std.Io, file: *std.Io.File) !TestSuiteConfig { + pub fn load(allocator: std.mem.Allocator, io: std.Io, file: std.Io.File) !TestSuiteConfig { var buf: [4096]u8 = undefined; var file_reader = file.reader(io, &buf); var json_reader = std.json.Reader.init(allocator, &file_reader.interface); diff --git a/tools/dfu/build.zig b/tools/dfu/build.zig index 79b7264b6..bcdb923d7 100644 --- a/tools/dfu/build.zig +++ b/tools/dfu/build.zig @@ -26,7 +26,7 @@ pub fn from_elf(dep: *Dependency, elf_file: std.Build.LazyPath, opts: Options) s .standard => blk: { // Use objcopy to extract binary from ELF const objcopy = b.addObjCopy(elf_file, .{ - .format = .bin, + .format = .binary, }); const bin_file = objcopy.getOutput(); From 669b03d3a73f194bdcb679e27ea103328df652b7 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 30 May 2026 19:21:50 -0700 Subject: [PATCH 61/61] Fix ch32v examples build.zig --- .github/workflows/publish-github-pages.yml | 2 +- examples/gigadevice/gd32/build.zig | 2 +- examples/wch/ch32v/build.zig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-github-pages.yml b/.github/workflows/publish-github-pages.yml index 3f646d281..4becbe241 100644 --- a/.github/workflows/publish-github-pages.yml +++ b/.github/workflows/publish-github-pages.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.2 + version: 0.15.1 - name: Download and install GitHub CLI run: | diff --git a/examples/gigadevice/gd32/build.zig b/examples/gigadevice/gd32/build.zig index 02bea494d..384923891 100644 --- a/examples/gigadevice/gd32/build.zig +++ b/examples/gigadevice/gd32/build.zig @@ -41,7 +41,7 @@ pub fn build(b: *std.Build) void { // and allows installing the firmware as a typical firmware file. // // This will also install into `$prefix/firmware` instead of `$prefix/bin`. - mb.install_firmware(fw, .{ .format = .bin }); + mb.install_firmware(fw, .{ .format = .binary }); // For debugging, we also always install the firmware as an ELF file mb.install_firmware(fw, .{}); diff --git a/examples/wch/ch32v/build.zig b/examples/wch/ch32v/build.zig index b94066eb9..73fb0c6de 100644 --- a/examples/wch/ch32v/build.zig +++ b/examples/wch/ch32v/build.zig @@ -15,7 +15,7 @@ pub fn build(b: *std.Build) void { // Use GNU objcopy instead of LLVM objcopy to avoid 512MB binary issue. // LLVM objcopy includes LOAD segments for NOLOAD sections, causing the binary // to span from flash (0x0) to RAM (0x20000000) = 512MB of zeros. - const gnu_objcopy = b.findProgram(&.{"riscv64-unknown-elf-objcopy"}, &.{}) catch null; + const gnu_objcopy = b.findProgram(.{ .names = &.{"riscv64-unknown-elf-objcopy"} }); const available_examples = [_]Example{ // CH32V003