From 91f8615956c3740d8e3c38a97ac6fd7d1d503726 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sun, 28 Dec 2025 19:39:37 -0800 Subject: [PATCH 1/3] WIP --- build.zig | 74 ++++++------ core/src/core/usb.zig | 26 ++--- core/src/cpus/cortex_m.zig | 32 ++--- core/src/microzig.zig | 16 ++- core/src/start.zig | 141 +++++++++++++++++++++++ core/src/utilities.zig | 75 ++++++------ modules/foundation-libc/build.zig | 16 +-- modules/rtt/src/rtt.zig | 51 +++----- port/raspberrypi/rp2xxx/build.zig | 4 +- port/raspberrypi/rp2xxx/src/hal/pins.zig | 57 +++++---- port/stmicro/stm32/build.zig | 2 +- sim/aviron/build.zig | 41 ++++--- sim/aviron/src/testconfig.zig | 4 +- tools/generate_linker_script.zig | 31 +++-- tools/regz/build.zig | 4 +- tools/regz/build.zig.zon | 8 +- tools/regz/src/Database.zig | 8 +- tools/regz/src/FS_Directory.zig | 20 ++-- tools/regz/src/embassy.zig | 26 ++--- tools/regz/src/main.zig | 47 ++++---- tools/uf2/src/elf2uf2.zig | 27 ++--- tools/uf2/src/uf2.zig | 2 +- 22 files changed, 414 insertions(+), 298 deletions(-) diff --git a/build.zig b/build.zig index f37abaefb..c003de3d3 100644 --- a/build.zig +++ b/build.zig @@ -110,25 +110,27 @@ 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), - }}; + 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| { + const typ = custom_lazy_import(port.dep_name) orelse struct {}; + const default: ?typ = null; + field_names[i] = port.name; + field_types[i] = ?typ; + field_attrs[i] = .{ + .default_value_ptr = &default, + }; } - break :blk @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = fields, - .decls = &.{}, - .is_tuple = false, - }, - }); + + break :blk @Struct( + .auto, + null, + &field_names, + &field_types, + &field_attrs, + ); }; var port_cache: PortCache = .{}; @@ -172,29 +174,31 @@ pub fn MicroBuild(port_select: PortSelect) type { const Self = @This(); const SelectedPorts = blk: { - var fields: []const std.builtin.Type.StructField = &.{}; + 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; + var count: usize = 0; for (port_list) |port| { if (@field(port_select, port.name)) { + const i = count; const typ = custom_lazy_import(port.dep_name) orelse struct {}; - fields = fields ++ [_]std.builtin.Type.StructField{.{ - .name = port.name, - .type = typ, - .default_value_ptr = null, - .is_comptime = false, - .alignment = @alignOf(typ), - }}; + + field_names[i] = port.name; + field_types[i] = typ; + field_attrs[i] = .{}; + + count += 1; } } - break :blk @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = fields, - .decls = &.{}, - .is_tuple = false, - }, - }); + break :blk @Struct( + .auto, + null, + field_names[0..count], + field_types[0..count], + field_attrs[0..count], + ); }; const InitReturnType = blk: { @@ -395,7 +399,7 @@ pub fn MicroBuild(port_select: PortSelect) type { cpu_mod.addImport("microzig", core_mod); core_mod.addImport("cpu", cpu_mod); - const regz_exe = b.dependency("tools/regz", .{ .optimize = .ReleaseSafe }).artifact("regz"); + const regz_exe = b.dependency("tools/regz", .{ .optimize = .Debug }).artifact("regz"); const chip_source = switch (target.chip.register_definition) { .atdf, .svd => |file| blk: { const regz_run = b.addRunArtifact(regz_exe); diff --git a/core/src/core/usb.zig b/core/src/core/usb.zig index d5e04641b..bda8c5425 100644 --- a/core/src/core/usb.zig +++ b/core/src/core/usb.zig @@ -83,18 +83,18 @@ pub fn DeviceController(config: Config) type { var num_ep_out = 1; var size = @sizeOf(descriptor.Configuration); - var fields: [driver_fields.len + 1]std.builtin.Type.StructField = undefined; - + var field_names: [driver_fields.len + 1][]const u8 = undefined; + var field_types: [driver_fields.len + 1]type = undefined; + var field_attrs: [driver_fields.len + 1]std.builtin.Type.StructField.Attributes = undefined; for (driver_fields, 1..) |drv, i| { const payload = drv.type.Descriptor.create(num_interfaces, num_strings, num_ep_in, num_ep_out); const Payload = @TypeOf(payload); size += @sizeOf(Payload); - fields[i] = .{ - .name = drv.name, - .type = Payload, + field_names[i] = drv.name; + field_types[i] = Payload; + field_attrs[i] = .{ .default_value_ptr = &payload, - .is_comptime = false, .alignment = 1, }; @@ -131,20 +131,14 @@ pub fn DeviceController(config: Config) type { .max_current = .from_ma(config0.max_current_ma), }; - fields[0] = .{ - .name = "__configuration_descriptor", - .type = descriptor.Configuration, + field_names[0] = "__configuration_descriptor"; + field_types[0] = descriptor.Configuration; + field_attrs[0] = .{ .default_value_ptr = &desc_cfg, - .is_comptime = false, .alignment = 1, }; - break :blk @Type(.{ .@"struct" = .{ - .decls = &.{}, - .fields = &fields, - .is_tuple = false, - .layout = .auto, - } }){}; + break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs); }; /// When the host sets the device address, the acknowledgement diff --git a/core/src/cpus/cortex_m.zig b/core/src/cpus/cortex_m.zig index 2a8e2e425..eda6645a4 100644 --- a/core/src/cpus/cortex_m.zig +++ b/core/src/cpus/cortex_m.zig @@ -69,25 +69,19 @@ pub const ExternalInterrupt = blk: { if (result_len == 0) break :blk enum {}; - var fields: [result_len]std.builtin.Type.EnumField = undefined; + var field_names: [result_len][]const u8 = undefined; + var field_values: [result_len]u8 = undefined; var field_index: usize = 0; for (microzig.chip.interrupts) |intr| { if (intr.index >= 0) { - fields[field_index] = .{ - .name = intr.name, - .value = intr.index, - }; + field_names[field_index] = intr.name; + field_values[field_index] = intr.index; field_index += 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. @@ -105,25 +99,19 @@ pub const Exception = blk: { if (result_len == 0) break :blk enum {}; - var fields: [result_len]std.builtin.Type.EnumField = undefined; + var field_names: [result_len][]const u8 = undefined; + var field_values: [result_len]u4 = undefined; var field_index: 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_names[field_index] = intr.name; + field_values[field_index] = 16 + intr.index; // Cortex-M exceptions are mapped to vector table slots 0 - 15 field_index += 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/microzig.zig b/core/src/microzig.zig index 96b8b551f..9a44b9ca0 100644 --- a/core/src/microzig.zig +++ b/core/src/microzig.zig @@ -45,10 +45,16 @@ pub const panic = std.debug.FullPanic(struct { var frame_index: usize = 0; if (@errorReturnTrace()) |trace| frame_index = utilities.dump_stack_trace(trace); - 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 addr_buf: [20]usize = undefined; + var stacktrace = std.debug.captureCurrentStackTrace(.{ + .first_address = first_trace_address orelse @returnAddress(), + }, &addr_buf); + + _ = utilities.dump_stack_trace(&stacktrace); + //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. @@ -77,7 +83,7 @@ pub const Options = struct { ) void = struct { fn log( comptime message_level: std.log.Level, - comptime scope: @Type(.enum_literal), + comptime scope: @EnumLiteral(), comptime format: []const u8, args: anytype, ) void { diff --git a/core/src/start.zig b/core/src/start.zig index 004e20a5f..fdf92926b 100644 --- a/core/src/start.zig +++ b/core/src/start.zig @@ -16,6 +16,8 @@ pub const std_options: std.Options = .{ .logFn = microzig.options.logFn, }; +pub const std_options_debug_io: std.Io = nop(); + // Startup logic: comptime { // Instantiate the startup logic for the given CPU type. @@ -93,3 +95,142 @@ export fn microzig_main() noreturn { // Main returned, just hang around here a bit. microzig.hang(); } + +fn nop() std.Io { + return .{ + .userdata = null, + .vtable = &.{ + .async = async, + .concurrent = concurrent, + .await = await, + .cancel = cancel, + .select = select, + + .groupAsync = groupAsync, + .groupConcurrent = groupConcurrent, + .groupAwait = groupAwait, + .groupCancel = groupCancel, + + .recancel = recancel, + .swapCancelProtection = swapCancelProtection, + .checkCancel = checkCancel, + + .futexWait = futexWait, + .futexWaitUncancelable = futexWaitUncancelable, + .futexWake = futexWake, + + .dirCreateDir = dirCreateDir, + .dirCreateDirPath = dirCreateDirPath, + .dirCreateDirPathOpen = dirCreateDirPathOpen, + .dirStat = dirStat, + .dirStatFile = dirStatFile, + .dirAccess = dirAccess, + .dirCreateFile = dirCreateFile, + .dirCreateFileAtomic = dirCreateFileAtomic, + .dirOpenFile = dirOpenFile, + .dirOpenDir = dirOpenDir, + .dirClose = dirClose, + .dirRead = dirRead, + .dirRealPath = dirRealPath, + .dirRealPathFile = dirRealPathFile, + .dirDeleteFile = dirDeleteFile, + .dirDeleteDir = dirDeleteDir, + .dirRename = dirRename, + .dirRenamePreserve = dirRenamePreserve, + .dirSymLink = dirSymLink, + .dirReadLink = dirReadLink, + .dirSetOwner = dirSetOwner, + .dirSetFileOwner = dirSetFileOwner, + .dirSetPermissions = dirSetPermissions, + .dirSetFilePermissions = dirSetFilePermissions, + .dirSetTimestamps = dirSetTimestamps, + .dirHardLink = dirHardLink, + + .fileStat = fileStat, + .fileLength = fileLength, + .fileClose = fileClose, + .fileWriteStreaming = fileWriteStreaming, + .fileWritePositional = fileWritePositional, + .fileWriteFileStreaming = fileWriteFileStreaming, + .fileWriteFilePositional = fileWriteFilePositional, + .fileReadStreaming = fileReadStreaming, + .fileReadPositional = fileReadPositional, + .fileSeekBy = fileSeekBy, + .fileSeekTo = fileSeekTo, + .fileSync = fileSync, + .fileIsTty = fileIsTty, + .fileEnableAnsiEscapeCodes = fileEnableAnsiEscapeCodes, + .fileSupportsAnsiEscapeCodes = fileSupportsAnsiEscapeCodes, + .fileSetLength = fileSetLength, + .fileSetOwner = fileSetOwner, + .fileSetPermissions = fileSetPermissions, + .fileSetTimestamps = fileSetTimestamps, + .fileLock = fileLock, + .fileTryLock = fileTryLock, + .fileUnlock = fileUnlock, + .fileDowngradeLock = fileDowngradeLock, + .fileRealPath = fileRealPath, + .fileHardLink = fileHardLink, + + .processExecutableOpen = processExecutableOpen, + .processExecutablePath = processExecutablePath, + .lockStderr = lockStderr, + .tryLockStderr = tryLockStderr, + .unlockStderr = unlockStderr, + .processSetCurrentDir = processSetCurrentDir, + .processReplace = processReplace, + .processReplacePath = processReplacePath, + .processSpawn = processSpawn, + .processSpawnPath = processSpawnPath, + .childWait = childWait, + .childKill = childKill, + + .progressParentFile = progressParentFile, + + .now = now, + .sleep = sleep, + + .random = random, + .randomSecure = randomSecure, + + .netListenIp = netListenIpUnavailable, + .netListenUnix = netListenUnixUnavailable, + .netAccept = netAcceptUnavailable, + .netBindIp = netBindIpUnavailable, + .netConnectIp = netConnectIpUnavailable, + .netConnectUnix = netConnectUnixUnavailable, + .netClose = netCloseUnavailable, + .netShutdown = netShutdownUnavailable, + .netRead = netReadUnavailable, + .netWrite = netWriteUnavailable, + .netWriteFile = netWriteFileUnavailable, + .netSend = netSendUnavailable, + .netReceive = netReceiveUnavailable, + .netInterfaceNameResolve = netInterfaceNameResolveUnavailable, + .netInterfaceName = netInterfaceNameUnavailable, + .netLookup = netLookupUnavailable, + }, + }; +} + +fn async( + _: ?*anyopaque, + _: []u8, + _: std.Alignment, + _: []const u8, + _: std.Alignment, + _: *const fn (context: *const anyopaque, result: *anyopaque) void, +) ?*std.Io.AnyFuture { + return null; +} + +fn concurrent( + _: ?*anyopaque, + _: usize, + _: std.mem.Alignment, + _: []const u8, + _: std.mem.Alignment, + _: *const fn (context: *const anyopaque, result: *anyopaque) void, +) std.Io.ConcurrentError!*std.Io.AnyFuture { + return error.ConcurrencyUnavailable; +} diff --git a/core/src/utilities.zig b/core/src/utilities.zig index 9bcad56bf..ff60ec2df 100644 --- a/core/src/utilities.zig +++ b/core/src/utilities.zig @@ -60,24 +60,19 @@ 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, - }, + const item_ptr_attrs: std.builtin.Type.Pointer.Attributes = .{ + .alignment = @min(type_info.pointer.alignment, @alignOf(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, }; return struct { const Vector = @This(); pub const Item = type_info.pointer.child; - pub const ItemPtr = @Type(item_ptr_info); + pub const ItemPtr = @Pointer(.one, item_ptr_attrs, 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. @@ -257,21 +252,15 @@ 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; + var field_names: [microzig.chip.interrupts.len][]const u8 = undefined; + var field_values: [microzig.chip.interrupts.len]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, *name, *value| { + name.* = interrupt.name; + value.* = interrupt.index; } - 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 +269,38 @@ pub const Source = struct { }; pub fn GenerateInterruptOptions(sources: []const Source) type { - var ret_fields: []const std.builtin.Type.StructField = &.{}; + const len = blk: { + var len: usize = 0; + for (sources) |source| { + if (@typeInfo(source.InterruptEnum) != .@"enum") @compileError("expected an enum type"); + for (@typeInfo(source.InterruptEnum).@"enum".fields) |_| { + len += 1; + } + } + + break :blk len; + }; + + var field_names: [len][]const u8 = undefined; + var field_types: [len]type = undefined; + var field_attrs: [len]std.builtin.Type.StructField.Attributes = undefined; + var idx: usize = 0; for (sources) |source| { if (@typeInfo(source.InterruptEnum) != .@"enum") @compileError("expected an enum type"); for (@typeInfo(source.InterruptEnum).@"enum".fields) |enum_field| { - ret_fields = ret_fields ++ .{std.builtin.Type.StructField{ - .name = enum_field.name, - .type = ?source.HandlerFn, + field_names[idx] = enum_field.name; + field_types[idx] = ?source.HandlerFn; + field_attrs[idx] = .{ .default_value_ptr = @as(*const anyopaque, @ptrCast(&@as(?source.HandlerFn, null))), - .is_comptime = false, - .alignment = @alignOf(?source.HandlerFn), - }}; + }; + + idx += 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/modules/foundation-libc/build.zig b/modules/foundation-libc/build.zig index 31ae1c883..c26c9ffbf 100644 --- a/modules/foundation-libc/build.zig +++ b/modules/foundation-libc/build.zig @@ -13,17 +13,19 @@ pub fn build(b: *std.Build) void { b.getInstallStep().dependOn(validation_step); } + const mod = b.createModule(.{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/libc.zig"), + .single_threaded = single_threaded, + }); + const libc = b.addLibrary(.{ .name = "foundation", - .root_module = b.createModule(.{ - .target = target, - .optimize = optimize, - .root_source_file = b.path("src/libc.zig"), - .single_threaded = single_threaded, - }), + .root_module = mod, }); - libc.addIncludePath(b.path("include")); + mod.addIncludePath(b.path("include")); for (header_files) |header_name| libc.installHeader( b.path(b.fmt("include/{s}", .{header_name})), diff --git a/modules/rtt/src/rtt.zig b/modules/rtt/src/rtt.zig index 9956f6141..9696b26af 100644 --- a/modules/rtt/src/rtt.zig +++ b/modules/rtt/src/rtt.zig @@ -422,39 +422,26 @@ 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 len = up_channels.len + down_channels.len; + var field_names: [len][]const u8 = undefined; + var field_types: [len]type = undefined; + var field_attrs: [len]std.builtin.Type.StructField.Attributes = undefined; + + for (up_channels, 0..) |up_cfg, idx| { + const buffer_type = [up_cfg.buffer_size]u8; + field_names[idx] = std.fmt.comptimePrint("up_buffer_{d}", .{idx}); + field_types[idx] = buffer_type; + field_attrs[idx] = .{}; + } + + for (down_channels, 0..) |down_cfg, idx| { + const buffer_type = [down_cfg.buffer_size]u8; + field_names[idx + up_channels.len] = std.fmt.comptimePrint("down_buffer_{d}", .{idx}); + field_types[idx + up_channels.len] = buffer_type; + field_attrs[idx + up_channels.len] = .{}; + } - 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/raspberrypi/rp2xxx/build.zig b/port/raspberrypi/rp2xxx/build.zig index 4036e74a4..4db612f2f 100644 --- a/port/raspberrypi/rp2xxx/build.zig +++ b/port/raspberrypi/rp2xxx/build.zig @@ -298,7 +298,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"); @@ -331,7 +331,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/pins.zig b/port/raspberrypi/rp2xxx/src/hal/pins.zig index e1a82c0e8..efd325cfb 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pins.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pins.zig @@ -767,44 +767,41 @@ pub const GlobalConfiguration = struct { } pub fn PinsType(self: GlobalConfiguration) type { - var fields: []const StructField = &.{}; + const len = blk: { + var len: usize = 0; + for (@typeInfo(GlobalConfiguration).@"struct".fields) |field| { + if (@field(self, field.name)) |_| { + len += 1; + } + } + + break :blk len; + }; + + var field_names: [len][]const u8 = undefined; + var field_types: [len]type = undefined; + var field_attrs: [len]std.builtin.Type.StructField.Attributes = undefined; + var idx: 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, - }; - - 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 { + field_names[idx] = pin_config.name orelse field.name; + field_types[idx] = 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 { continue; - } + }; - pin_field.alignment = @alignOf(field.type); + field_attrs[idx] = .{}; - fields = fields ++ &[_]StructField{pin_field}; + idx += 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 40150bdcd..1fd6bae5d 100644 --- a/port/stmicro/stm32/build.zig +++ b/port/stmicro/stm32/build.zig @@ -99,7 +99,7 @@ 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.stdio_limit = .unlimited; generate_run.addFileArg(stm32_data_generated.path(".")); const generate_step = b.step("generate", "Generate chips file 'src/Chips.zig'"); diff --git a/sim/aviron/build.zig b/sim/aviron/build.zig index 388b4bfa5..c9caed0b7 100644 --- a/sim/aviron/build.zig +++ b/sim/aviron/build.zig @@ -123,6 +123,7 @@ fn add_test_suite( args_module: *Build.Module, aviron_module: *Build.Module, ) !void { + const io = b.graph.io; const unit_tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), @@ -161,13 +162,13 @@ 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("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 +218,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 +255,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 +263,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 +295,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(io, b.allocator, 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 }); @@ -336,6 +337,7 @@ fn add_test_suite_update( b: *Build, invoke_step: *Build.Step, ) !void { + const io = b.graph.io; const avr_gcc = if (b.findProgram(&.{"avr-gcc"}, &.{})) |path| LazyPath{ .cwd_relative = path, } else |_| b.addExecutable(.{ @@ -347,13 +349,13 @@ 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(); + 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 +391,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,12 +449,13 @@ 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) { diff --git a/sim/aviron/src/testconfig.zig b/sim/aviron/src/testconfig.zig index 14d3b4375..c99e61fcd 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(io: std.Io, allocator: std.mem.Allocator, 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/tools/generate_linker_script.zig b/tools/generate_linker_script.zig index ef1f4079b..bc96a82ad 100644 --- a/tools/generate_linker_script.zig +++ b/tools/generate_linker_script.zig @@ -14,15 +14,12 @@ 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(); +pub fn main(init: std.process.Init) !void { + const io = init.io; + const gpa = init.gpa; + const arena = init.arena; - var arena: std.heap.ArenaAllocator = .init(debug_allocator.allocator()); - defer arena.deinit(); - - const allocator = arena.allocator(); - const args = try std.process.argsAlloc(allocator); + const args = try init.minimal.args.toSlice(arena.allocator()); if (args.len < 3 or args.len > 4) { return error.UsageError; } @@ -30,17 +27,17 @@ pub fn main() !void { const json_args = args[1]; const output_path = args[2]; - const parsed_args = try std.json.parseFromSliceLeaky(Args, allocator, json_args, .{}); + const parsed_args = try std.json.parseFromSliceLeaky(Args, gpa, 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], gpa, .limited(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} @@ -54,14 +51,14 @@ pub fn main() !void { }); // name all unnamed regions - const region_names: [][]const u8 = try allocator.alloc([]const u8, parsed_args.memory_regions.len); + const region_names: [][]const u8 = try gpa.alloc([]const u8, parsed_args.memory_regions.len); { var counters: [5]usize = @splat(0); for (region_names, parsed_args.memory_regions) |*region_name, region| { if (region.name) |name| { - region_name.* = try allocator.dupe(u8, name); + region_name.* = try gpa.dupe(u8, name); } else { - region_name.* = try std.fmt.allocPrint(allocator, "{s}{}", .{ + region_name.* = try std.fmt.allocPrint(gpa, "{s}{}", .{ @tagName(region.tag), counters[@intFromEnum(region.tag)], }); @@ -252,7 +249,7 @@ pub fn main() !void { \\ , .{ if (!parsed_args.ram_image) - try std.fmt.allocPrint(allocator, "{s} AT> {s}", .{ ram_region_name, flash_region_name }) + try std.fmt.allocPrint(gpa, "{s} AT> {s}", .{ ram_region_name, flash_region_name }) else ram_region_name, ram_region_name, diff --git a/tools/regz/build.zig b/tools/regz/build.zig index 1570f018b..a54b2e729 100644 --- a/tools/regz/build.zig +++ b/tools/regz/build.zig @@ -39,7 +39,7 @@ pub fn build(b: *Build) !void { }), .use_llvm = true, }); - regz.linkLibrary(libxml2_dep.artifact("xml2")); + regz.root_module.linkLibrary(libxml2_dep.artifact("xml2")); regz.root_module.addImport("zqlite", zqlite); b.installArtifact(regz); @@ -66,7 +66,7 @@ pub fn build(b: *Build) !void { }), .use_llvm = true, }); - tests.linkLibrary(libxml2_dep.artifact("xml2")); + tests.root_module.linkLibrary(libxml2_dep.artifact("xml2")); tests.root_module.addImport("zqlite", zqlite); tests.step.dependOn(®z.step); diff --git a/tools/regz/build.zig.zon b/tools/regz/build.zig.zon index 154dc6eaa..7c0bf2693 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/mattnite/zig-build-libxml2.git#0a410ac11a842e7f366dac13d0ca59adbc7b4c5e", + .hash = "libxml2-0.0.0-Kr0Y1C44ngAn0qlZ5eZXiDDAnjbAk1TWMqRiuKyIMmUZ", }, .sqlite3 = .{ - .url = "git+https://github.com/allyourcodebase/sqlite3#8f840560eae88ab66668c6827c64ffbd0d74ef37", - .hash = "sqlite3-3.51.0-DMxLWssOAABZ8cAvU_LfBIbp0kZjm824PU8sSLXpEDdr", + .url = "git+https://github.com/allyourcodebase/sqlite3#42c703d0c800dcc39d3e0a2ca40380691274380f", + .hash = "sqlite3-3.51.0-DMxLWtcOAADDoP7M630_Ws36wFHX5WHwcs-zjlswwakL", }, .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 1cbd203e3..ebbe12306 100644 --- a/tools/regz/src/Database.zig +++ b/tools/regz/src/Database.zig @@ -611,7 +611,7 @@ 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(io: std.Io, allocator: Allocator, format: Format, path: []const u8, device: ?[]const u8) !*Database { return switch (format) { .embassy => blk: { var db = try Database.create(allocator); @@ -620,7 +620,7 @@ pub fn create_from_path(allocator: Allocator, format: Format, path: []const u8, db.destroy(); } - try embassy.load_into_db(db, path); + try embassy.load_into_db(io, db, path); break :blk db; }, .targetdb => blk: { @@ -634,7 +634,7 @@ pub fn create_from_path(allocator: Allocator, format: Format, path: []const u8, break :blk db; }, .svd, .atdf => blk: { - const text = try std.fs.cwd().readFileAlloc(allocator, path, file_size_max); + const text = try std.Io.Dir.cwd().readFileAlloc(io, path, allocator, .limited(file_size_max)); defer allocator.free(text); break :blk create_from_xml(allocator, format, text); @@ -2054,7 +2054,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| { diff --git a/tools/regz/src/FS_Directory.zig b/tools/regz/src/FS_Directory.zig index 69e0bd8e5..32e8e3d18 100644 --- a/tools/regz/src/FS_Directory.zig +++ b/tools/regz/src/FS_Directory.zig @@ -1,4 +1,5 @@ -dir: std.fs.Dir, +io: std.Io, +dir: std.Io.Dir, const vtable = Directory.VTable{ .create_file = create_file, @@ -6,19 +7,20 @@ const vtable = Directory.VTable{ 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(); + const file: std.Io.File = if (std.fs.path.dirname(filename)) |dirname| blk: { + var dir = fs.dir.createDirPathOpen(fs.io, dirname, .{}) catch return error.System; + defer dir.close(fs.io); - 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(); + break :blk dir.createFile(fs.io, std.fs.path.basename(filename), .{}) catch return error.System; + } else fs.dir.createFile(fs.io, filename, .{}) catch return error.System; + defer file.close(fs.io); - file.writeAll(contents) catch return error.System; + file.writeStreamingAll(fs.io, contents) catch return error.System; } -pub fn init(dir: std.fs.Dir) FS_Directory { +pub fn init(io: std.Io, dir: std.Io.Dir) FS_Directory { return FS_Directory{ + .io = io, .dir = dir, }; } diff --git a/tools/regz/src/embassy.zig b/tools/regz/src/embassy.zig index c97602c41..e7c164dd3 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) !void { - var package_dir = try std.fs.cwd().openDir(path, .{}); - defer package_dir.close(); +pub fn load_into_db(io: std.Io, db: *Database, path: []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(); @@ -171,17 +171,17 @@ pub fn load_into_db(db: *Database, path: []const u8) !void { register_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); @@ -201,8 +201,8 @@ pub fn load_into_db(db: *Database, path: []const u8) !void { try chip_files.append(allocator, chips_file); } - 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); @@ -210,13 +210,13 @@ pub fn load_into_db(db: *Database, path: []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); diff --git a/tools/regz/src/main.zig b/tools/regz/src/main.zig index 4a1cd79ad..5e3d2e8e1 100644 --- a/tools/regz/src/main.zig +++ b/tools/regz/src/main.zig @@ -9,13 +9,16 @@ const Allocator = std.mem.Allocator; const assert = std.debug.assert; pub const std_options = std.Options{ - .log_level = .warn, + .log_level = .debug, }; -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, + else => { + return err; + }, }; } @@ -62,9 +65,10 @@ 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(init: std.process.Init) !Arguments { + const io = init.io; + const allocator = init.arena.allocator(); + const args = try init.minimal.args.toSlice(allocator); var ret = Arguments{ .allocator = allocator, @@ -104,7 +108,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) { @@ -120,20 +124,20 @@ fn parse_args(allocator: Allocator) !Arguments { 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 io = init.io; + const arena = init.arena.allocator(); - const allocator = gpa.allocator(); + const allocator = init.gpa; - var args = try parse_args(allocator); + var args = try parse_args(init); 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,11 +150,11 @@ 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(io, allocator, 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); + const patch = try std.Io.Dir.cwd().readFileAllocOptions(io, patch_path, allocator, .limited(1024 * 1024), .@"1", 0); defer allocator.free(patch); var diags: std.zon.parse.Diagnostics = .{}; @@ -167,10 +171,7 @@ 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(arena)) |device| { if (device.arch.is_arm()) { const arm = @import("arch/arm.zig"); try arm.load_system_interrupts(db, device.id, device.arch); @@ -182,9 +183,9 @@ 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); + var fs = FS_Directory.init(io, output_dir); try db.to_zig(fs.directory(), .{}); } diff --git a/tools/uf2/src/elf2uf2.zig b/tools/uf2/src/elf2uf2.zig index c4fb66e38..ce1107eb2 100644 --- a/tools/uf2/src/elf2uf2.zig +++ b/tools/uf2/src/elf2uf2.zig @@ -37,15 +37,12 @@ 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 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; }; @@ -74,21 +71,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/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 ec94b74db36d077fb56b6a97bebaaf3c32b6826d Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 15 Jan 2026 10:29:56 -0800 Subject: [PATCH 2/3] Update CI --- .github/workflows/ci.yml | 10 ++++++---- .github/workflows/deploy.yml | 2 +- .github/workflows/drivers.yaml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-github-pages.yml | 4 +--- .github/workflows/sim-aviron.yml | 2 +- README.md | 2 +- website/content/docs/getting-started.smd | 4 ++-- website/content/index.smd | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f3210d51..b229b5889 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: master jobs: formatting-check: @@ -170,7 +170,8 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - port_dir: [gigadevice/gd32, raspberrypi/rp2xxx, stmicro/stm32, wch/ch32v] + port_dir: + [gigadevice/gd32, raspberrypi/rp2xxx, stmicro/stm32, wch/ch32v] steps: - name: Checkout uses: actions/checkout@v4 @@ -188,7 +189,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - example_dir: [ + example_dir: + [ espressif/esp, gigadevice/gd32, microchip/atmega, @@ -245,7 +247,7 @@ jobs: - name: Setup Zig uses: mlugg/setup-zig@v2 with: - version: 0.15.1 + version: master - name: Build Website run: zig build working-directory: website diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 196df1259..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.15.1 + 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 7f510ffd8..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.15.1 + version: master - name: Run Test Suite working-directory: drivers diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4c674fabf..96c9abf84 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: 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 4becbe241..8e2ccca88 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: master - name: Download and install GitHub CLI run: | @@ -65,8 +65,6 @@ jobs: echo "Generating metadata.json" echo "{ \"releases\": [$(IFS=,; echo "${releases_with_artifact[*]}")] }" > website/zig-out/downloads/microzig/metadata.json - - - name: List Contents run: tree zig-out working-directory: website diff --git a/.github/workflows/sim-aviron.yml b/.github/workflows/sim-aviron.yml index ed71a1fa2..a824a359b 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: master - name: Build working-directory: sim/aviron diff --git a/README.md b/README.md index 3bb05577c..09e1898a9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## What version of Zig to use -Zig 0.15.1 +Zig master ## Getting Started With MicroZig diff --git a/website/content/docs/getting-started.smd b/website/content/docs/getting-started.smd index d52ba8917..4d7403389 100644 --- a/website/content/docs/getting-started.smd +++ b/website/content/docs/getting-started.smd @@ -22,7 +22,7 @@ used for the [2024 SYCL](https://sycl.it) ## Let's Begin -Quickly check that you have Zig `0.15.1` installed by running `zig version`. +Quickly check that you have Zig `master` installed by running `zig version`. Assuming you've initialized a zig project with `zig init`, or have set one up yourself, you can add microzig as a dependency with the following command: @@ -114,4 +114,4 @@ Copy the uf2 file into the mounted drive. Execution should take place immediatel ## Further Resources -- [Zig Language Reference](https://ziglang.org/documentation/0.15.1/) +- [Zig Language Reference](https://ziglang.org/documentation/master/) diff --git a/website/content/index.smd b/website/content/index.smd index 1ec15f261..3ea4eb4fd 100644 --- a/website/content/index.smd +++ b/website/content/index.smd @@ -28,7 +28,7 @@ Zig is an excellent programming language for embedded systems. explicit and even verbose at times. Nullable pointers, pointer casting, integer conversions, etc. -To learn more: [The Zig Language Reference](https://ziglang.org/documentation/0.15.1/) +To learn more: [The Zig Language Reference](https://ziglang.org/documentation/master/) ## Why MicroZig? From 2c500aa2c1b5c26d9f32995576d094ffcb641873 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 15 Jan 2026 10:47:04 -0800 Subject: [PATCH 3/3] Fix regz for targetdb --- tools/regz/src/Database.zig | 2 +- tools/regz/src/targetdb.zig | 38 ++++++++++++++++++------------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/regz/src/Database.zig b/tools/regz/src/Database.zig index ebbe12306..53afb9543 100644 --- a/tools/regz/src/Database.zig +++ b/tools/regz/src/Database.zig @@ -630,7 +630,7 @@ pub fn create_from_path(io: std.Io, allocator: Allocator, format: Format, path: db.destroy(); } - try targetdb.load_into_db(db, path, device); + try targetdb.load_into_db(io, db, path, device); break :blk db; }, .svd, .atdf => blk: { diff --git a/tools/regz/src/targetdb.zig b/tools/regz/src/targetdb.zig index c0013c935..82e384547 100644 --- a/tools/regz/src/targetdb.zig +++ b/tools/regz/src/targetdb.zig @@ -8,15 +8,15 @@ const RegisterID = Database.RegisterID; const StructID = Database.StructID; const EnumID = Database.EnumID; -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(io: std.Io, db: *Database, 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 it = devices_dir.iterate(); - while (try it.next()) |entry| { + while (try it.next(io)) |entry| { if (entry.kind != .file) continue; @@ -26,22 +26,19 @@ 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); + try load_device(io, db, devices_dir, entry.name); return; } } else { - try load_device(db, devices_dir, entry.name); + try load_device(io, db, devices_dir, entry.name); } } else if (device != null) { return error.DeviceMissing; } } -fn load_device(db: *Database, devices_dir: std.fs.Dir, filename: []const u8) !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(io: std.Io, db: *Database, devices_dir: std.Io.Dir, filename: []const u8) !void { + const device_text = try devices_dir.readFileAlloc(io, filename, db.gpa, .unlimited); defer db.gpa.free(device_text); var doc = try xml.Doc.from_memory(device_text); @@ -66,21 +63,24 @@ fn load_device(db: *Database, devices_dir: std.fs.Dir, filename: []const u8) !vo var instance_it = cpu_node.iterate(&.{}, &.{"instance"}); while (instance_it.next()) |instance_node| { - try load_instance(db, device_id, devices_dir, instance_node); + try load_instance(io, db, device_id, devices_dir, instance_node); } } -fn load_instance(db: *Database, device_id: DeviceID, devices_dir: std.fs.Dir, node: xml.Node) !void { +fn load_instance( + io: std.Io, + db: *Database, + device_id: DeviceID, + devices_dir: std.Io.Dir, + node: xml.Node, +) !void { const name = node.get_attribute("id") orelse return error.MissingField; const href = node.get_attribute("href") orelse return error.MissingField; const baseaddr_str = node.get_attribute("baseaddr") orelse return error.MissingField; const baseaddr = try std.fmt.parseInt(u64, baseaddr_str, 0); - 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, .unlimited); defer db.gpa.free(module_text); var doc = try xml.Doc.from_memory(module_text);