Makes examples/next-gen kinda build with experimental setup. Packages are now correct and microzig-build can determine all available targets and BSPs.

wch-ch32v003
Felix "xq" Queißner 8 months ago
parent 91fcc6b470
commit cadd5d1b0f

@ -27,4 +27,4 @@ Consider the version `0.11.0-abcdef-123` means that this MicroZig version has a
- validate that the table on https://github.com/ZigEmbeddedGroup is correct (in CI)
- make system build again properly
- start porting everything to 0.12/unstable
- Try to get some autodocs to build.

@ -1,4 +1,5 @@
const std = @import("std");
const MicroZig = @import("microzig-build");
fn path(comptime suffix: []const u8) std.Build.LazyPath {
return .{
@ -7,7 +8,7 @@ fn path(comptime suffix: []const u8) std.Build.LazyPath {
}
pub const chips = struct {
pub const nrf52840 = .{
pub const nrf52840 = MicroZig.Target{
.preferred_format = .elf,
.chip = .{
.name = "nrf52840",
@ -29,7 +30,7 @@ pub const chips = struct {
},
};
pub const nrf52832 = .{
pub const nrf52832 = MicroZig.Target{
.preferred_format = .elf,
.chip = .{
.name = "nrf52",
@ -48,7 +49,7 @@ pub const chips = struct {
pub const boards = struct {
pub const nordic = struct {
pub const nRF52840_Dongle = .{
pub const nRF52840_Dongle = MicroZig.Target{
.preferred_format = .elf,
.chip = chips.nrf52840.chip,
.board = .{

@ -1,4 +1,5 @@
const std = @import("std");
const MicroZig = @import("microzig-build");
fn path(comptime suffix: []const u8) std.Build.LazyPath {
return .{
@ -11,7 +12,7 @@ const hal = .{
};
pub const chips = struct {
pub const lpc176x5x = .{
pub const lpc176x5x = MicroZig.Target{
.preferred_format = .elf,
.chip = .{
// TODO: Separate over those chips, this is not generic!
@ -33,7 +34,7 @@ pub const chips = struct {
pub const boards = struct {
pub const mbed = struct {
pub const lpc1768 = .{
pub const lpc1768 = MicroZig.Target{
.preferred_format = .hex,
.chip = chips.lpc176x5x.chip,
.hal = hal,

@ -1,5 +1,5 @@
const std = @import("std");
const microzig = @import("microzig");
const microzig = @import("microzig-build");
fn root() []const u8 {
return comptime (std.fs.path.dirname(@src().file) orelse ".");
@ -17,7 +17,7 @@ pub fn build(b: *std.Build) !void {
pub const chips = struct {
// Note: This chip has no flash support defined and requires additional configuration!
pub const rp2040 = .{
pub const rp2040 = microzig.Target{
.preferred_format = .{ .uf2 = .RP2040 },
.chip = chip,
.hal = hal,
@ -28,7 +28,7 @@ pub const chips = struct {
pub const boards = struct {
pub const raspberry_pi = struct {
pub const pico = .{
pub const pico = microzig.Target{
.preferred_format = .{ .uf2 = .RP2040 },
.chip = chip,
.hal = hal,
@ -43,7 +43,7 @@ pub const boards = struct {
};
pub const waveshare = struct {
pub const rp2040_plus_4m = .{
pub const rp2040_plus_4m = microzig.Target{
.preferred_format = .{ .uf2 = .RP2040 },
.chip = chip,
.hal = hal,
@ -56,7 +56,7 @@ pub const boards = struct {
.configure = rp2040_configure(.w25q080),
};
pub const rp2040_plus_16m = .{
pub const rp2040_plus_16m = microzig.Target{
.preferred_format = .{ .uf2 = .RP2040 },
.chip = chip,
.hal = hal,
@ -69,7 +69,7 @@ pub const boards = struct {
.configure = rp2040_configure(.w25q080),
};
pub const rp2040_eth = .{
pub const rp2040_eth = microzig.Target{
.preferred_format = .{ .uf2 = .RP2040 },
.chip = chip,
.hal = hal,
@ -82,7 +82,7 @@ pub const boards = struct {
.configure = rp2040_configure(.w25q080),
};
pub const rp2040_matrix = .{
pub const rp2040_matrix = microzig.Target{
.preferred_format = .{ .uf2 = .RP2040 },
.chip = chip,
.hal = hal,

@ -1,5 +1,5 @@
const std = @import("std");
const microzig = @import("microzig");
const microzig = @import("microzig-build");
fn root() []const u8 {
return comptime (std.fs.path.dirname(@src().file) orelse ".");

@ -1,7 +1,10 @@
const std = @import("std");
// const examples = @import("examples/build.zig");
pub fn build(b: *std.Build) void {
buildTools(b);
// examples.build(b);
}
fn buildTools(b: *std.Build) void {

@ -6,5 +6,13 @@
.url = "https://github.com/ziglibs/eggzon/archive/refs/heads/master.tar.gz",
.hash = "1220cd5cec7e9d4911074a9b2dec2dabef76e1adf94d041bca068163ce7666c4be47",
},
.uf2 = .{
.url = "https://github.com/ZigEmbeddedGroup/uf2/archive/8037b439ccbac862471392b25e94a8995d784e2c.tar.gz",
.hash = "1220cc66563fc1ecefca7990968441dc9d4db717884ffa9a2de657f60ed4bb74a70a",
},
.regz = .{
.url = "https://github.com/ZigEmbeddedGroup/regz/archive/d66ffd56f51fc46c071412141b5d0c74dc83c310.tar.gz",
.hash = "122002c5f2e31c11373ede6e8a8dd9a61aabd60d38df667ec33b5f994d1f0b503823",
},
},
}

@ -5,6 +5,342 @@
const std = @import("std");
const uf2 = @import("uf2");
////////////////////////////////////////
// MicroZig Gen 3 Interface //
////////////////////////////////////////
pub const EnvironmentInfo = struct {
/// include package names of your board support packages here:
board_support: []const []const u8,
/// package name of the build package (optional)
self: []const u8 = "microzig",
/// package name of the core package (optional)
core: []const u8 = "microzig-core",
};
pub fn createBuildEnvironment(b: *std.Build, comptime info: EnvironmentInfo) *BuildEnvironment {
const be = b.allocator.create(BuildEnvironment) catch @panic("out of memory");
be.* = BuildEnvironment{
.host_build = b,
.self = undefined,
.microzig_core = undefined,
.board_support_packages = b.allocator.alloc(BoardSupportPackage, info.board_support.len) catch @panic("out of memory"),
.targets = .{},
};
be.self = b.dependency(info.self, .{});
be.microzig_core = b.dependency(info.core, .{});
for (be.board_support_packages, info.board_support) |*out, in| {
out.* = BoardSupportPackage{
.name = in,
.dep = b.dependency(in, .{}),
};
}
// Fetch and collect all supported targets:
inline for (info.board_support) |bsp_name| {
// Keep in sync with the logic from Build.zig:dependency
const build_runner = @import("root");
const deps = build_runner.dependencies;
const bsp_root = @field(deps.imports, bsp_name);
if (@hasDecl(bsp_root, "chips")) {
fetch_microzig_targets("chip:", bsp_root.chips, bsp_name, be);
}
if (@hasDecl(bsp_root, "boards")) {
fetch_microzig_targets("board:", bsp_root.boards, bsp_name, be);
}
}
return be;
}
fn fetch_microzig_targets(comptime prefix: []const u8, comptime namespace: type, comptime bsp_name: []const u8, be: *BuildEnvironment) void {
inline for (@typeInfo(namespace).Struct.decls) |decl_info| {
const decl = @field(namespace, decl_info.name);
const T = @TypeOf(decl);
const name = comptime prefix ++ decl_info.name; // board:vendor/name
const full_name = comptime name ++ "#" ++ bsp_name; // board:vendor/name#bsp-package-name
if (T == Target) {
const target: Target = decl;
be.targets.put(be.host_build.allocator, name, target) catch @panic("out of memory");
be.targets.put(be.host_build.allocator, full_name, target) catch @panic("out of memory");
} else {
const ok = blk: {
if (comptime T != type) {
// @compileLog(full_name, "check 1:", T, decl);
break :blk false;
}
const ti = @typeInfo(decl);
if (comptime ti != .Struct) {
// @compileLog(full_name, "check 2:", ti);
break :blk false;
}
if (comptime ti.Struct.fields.len > 0) {
// @compileLog(full_name, "check 3:", ti.Struct);
// @compileLog(full_name, "check 3:", ti.Struct.fields);
break :blk false;
}
fetch_microzig_targets(
comptime name ++ "/",
decl,
bsp_name,
be,
);
break :blk true;
};
if (!ok) {
std.debug.print("Bad BSP: {s} is neither namespace nor a microzig.Target\n", .{ prefix, full_name });
}
}
}
}
pub const BoardSupportPackage = struct {
dep: *std.Build.Dependency,
name: []const u8,
};
pub const BuildEnvironment = struct {
host_build: *std.Build,
self: *std.Build.Dependency,
microzig_core: *std.Build.Dependency,
board_support_packages: []BoardSupportPackage,
targets: std.StringArrayHashMapUnmanaged(Target),
pub fn findTarget(env: *const BuildEnvironment, name: []const u8) ?*const Target {
return env.targets.getPtr(name);
}
/// Declares a new MicroZig firmware file.
pub fn addFirmware(
/// The MicroZig instance that should be used to create the firmware.
env: *BuildEnvironment,
/// The instance of the `build.zig` that is calling this function.
host_build: *std.Build,
/// Options that define how the firmware is built.
options: FirmwareOptions,
) *Firmware {
const micro_build = env.self.builder;
const chip = &options.target.chip;
const cpu = chip.cpu.getDescriptor();
const maybe_hal = options.hal orelse options.target.hal;
const maybe_board = options.board orelse options.target.board;
const linker_script = options.linker_script orelse options.target.linker_script;
// TODO: let the user override which ram section to use the stack on,
// for now just using the first ram section in the memory region list
const first_ram = blk: {
for (chip.memory_regions) |region| {
if (region.kind == .ram)
break :blk region;
} else @panic("no ram memory region found for setting the end-of-stack address");
};
// On demand, generate chip definitions via regz:
const chip_source = switch (chip.register_definition) {
.json, .atdf, .svd => |file| blk: {
const regz_exe = env.dependency("regz", .{ .optimize = .ReleaseSafe }).artifact("regz");
const regz_gen = host_build.addRunArtifact(regz_exe);
regz_gen.addArg("--schema"); // Explicitly set schema type, one of: svd, atdf, json
regz_gen.addArg(@tagName(chip.register_definition));
regz_gen.addArg("--output_path"); // Write to a file
const zig_file = regz_gen.addOutputFileArg("chip.zig");
regz_gen.addFileArg(file);
break :blk zig_file;
},
.zig => |src| src,
};
const config = host_build.addOptions();
config.addOption(bool, "has_hal", (maybe_hal != null));
config.addOption(bool, "has_board", (maybe_board != null));
config.addOption(?[]const u8, "board_name", if (maybe_board) |brd| brd.name else null);
config.addOption([]const u8, "chip_name", chip.name);
config.addOption([]const u8, "cpu_name", chip.name);
config.addOption(usize, "end_of_stack", first_ram.offset + first_ram.length);
const fw: *Firmware = host_build.allocator.create(Firmware) catch @panic("out of memory");
fw.* = Firmware{
.env = env,
.host_build = host_build,
.artifact = host_build.addExecutable(.{
.name = options.name,
.optimize = options.optimize,
.target = cpu.target,
.linkage = .static,
.root_source_file = .{ .cwd_relative = env.self.builder.pathFromRoot("src/start.zig") },
}),
.target = options.target,
.output_files = Firmware.OutputFileMap.init(host_build.allocator),
.config = config,
.modules = .{
.microzig = micro_build.createModule(.{
.source_file = .{ .cwd_relative = micro_build.pathFromRoot("src/microzig.zig") },
.dependencies = &.{
.{
.name = "config",
.module = micro_build.createModule(.{ .source_file = config.getSource() }),
},
},
}),
.cpu = undefined,
.chip = undefined,
.board = null,
.hal = null,
.app = undefined,
},
};
errdefer fw.output_files.deinit();
fw.modules.chip = micro_build.createModule(.{
.source_file = chip_source,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("chip", fw.modules.chip) catch @panic("out of memory");
fw.modules.cpu = micro_build.createModule(.{
.source_file = cpu.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("cpu", fw.modules.cpu) catch @panic("out of memory");
if (maybe_hal) |hal| {
fw.modules.hal = micro_build.createModule(.{
.source_file = hal.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("hal", fw.modules.hal.?) catch @panic("out of memory");
}
if (maybe_board) |brd| {
fw.modules.board = micro_build.createModule(.{
.source_file = brd.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("board", fw.modules.board.?) catch @panic("out of memory");
}
fw.modules.app = host_build.createModule(.{
.source_file = options.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
const umm = env.dependency("umm-zig", .{}).module("umm");
fw.modules.microzig.dependencies.put("umm", umm) catch @panic("out of memory");
fw.artifact.addModule("app", fw.modules.app);
fw.artifact.addModule("microzig", fw.modules.microzig);
fw.artifact.strip = false; // we always want debug symbols, stripping brings us no benefit on embedded
fw.artifact.single_threaded = options.single_threaded orelse fw.target.single_threaded;
fw.artifact.bundle_compiler_rt = options.bundle_compiler_rt orelse fw.target.bundle_compiler_rt;
switch (linker_script) {
.generated => {
fw.artifact.setLinkerScript(
generateLinkerScript(host_build, chip.*) catch @panic("out of memory"),
);
},
.source_file => |source| {
fw.artifact.setLinkerScriptPath(source);
},
}
if (options.target.configure) |configure| {
configure(host_build, fw);
}
return fw;
}
/// Adds a new dependency to the `install` step that will install the `firmware` into the folder `$prefix/firmware`.
pub fn installFirmware(
/// The MicroZig instance that was used to create the firmware.
env: *BuildEnvironment,
/// The instance of the `build.zig` that should perform installation.
b: *std.Build,
/// The firmware that should be installed. Please make sure that this was created with the same `MicroZig` instance as `mz`.
firmware: *Firmware,
/// Optional configuration of the installation process. Pass `.{}` if you're not sure what to do here.
options: InstallFirmwareOptions,
) void {
std.debug.assert(env == firmware.env);
const install_step = addInstallFirmware(env, b, firmware, options);
b.getInstallStep().dependOn(&install_step.step);
}
/// Creates a new `std.Build.Step.InstallFile` instance that will install the given firmware to `$prefix/firmware`.
///
/// **NOTE:** This does not actually install the firmware yet. You have to add the returned step as a dependency to another step.
/// If you want to just install the firmware, use `installFirmware` instead!
pub fn addInstallFirmware(
/// The MicroZig instance that was used to create the firmware.
env: *BuildEnvironment,
/// The instance of the `build.zig` that should perform installation.
b: *std.Build,
/// The firmware that should be installed. Please make sure that this was created with the same `MicroZig` instance as `mz`.
firmware: *Firmware,
/// Optional configuration of the installation process. Pass `.{}` if you're not sure what to do here.
options: InstallFirmwareOptions,
) *std.Build.Step.InstallFile {
_ = env;
const format = firmware.resolveFormat(options.format);
const basename = b.fmt("{s}{s}", .{
firmware.artifact.name,
format.getExtension(),
});
return b.addInstallFileWithDir(firmware.getEmittedBin(format), .{ .custom = "firmware" }, basename);
}
fn dependency(env: *BuildEnvironment, name: []const u8, args: anytype) *std.Build.Dependency {
return env.self.builder.dependency(name, args);
}
};
////////////////////////////////////////
// MicroZig Gen 2 Interface //
////////////////////////////////////////
@ -372,7 +708,7 @@ pub const FirmwareOptions = struct {
name: []const u8,
/// The MicroZig target that the firmware is built for. Either a board or a chip.
target: Target,
target: *const Target,
/// The optimization level that should be used. Usually `ReleaseSmall` or `Debug` is a good choice.
/// Also using `std.Build.standardOptimizeOption` is a good idea.
@ -399,222 +735,12 @@ pub const FirmwareOptions = struct {
linker_script: ?LinkerScript = null,
};
/// Declares a new MicroZig firmware file.
pub fn addFirmware(
/// The MicroZig instance that should be used to create the firmware.
mz: *MicroZig,
/// The instance of the `build.zig` that is calling this function.
host_build: *std.Build,
/// Options that define how the firmware is built.
options: FirmwareOptions,
) *Firmware {
const micro_build = mz.self.builder;
const chip = &options.target.chip;
const cpu = chip.cpu.getDescriptor();
const maybe_hal = options.hal orelse options.target.hal;
const maybe_board = options.board orelse options.target.board;
const linker_script = options.linker_script orelse options.target.linker_script;
// TODO: let the user override which ram section to use the stack on,
// for now just using the first ram section in the memory region list
const first_ram = blk: {
for (chip.memory_regions) |region| {
if (region.kind == .ram)
break :blk region;
} else @panic("no ram memory region found for setting the end-of-stack address");
};
// On demand, generate chip definitions via regz:
const chip_source = switch (chip.register_definition) {
.json, .atdf, .svd => |file| blk: {
const regz_exe = mz.dependency("regz", .{ .optimize = .ReleaseSafe }).artifact("regz");
const regz_gen = host_build.addRunArtifact(regz_exe);
regz_gen.addArg("--schema"); // Explicitly set schema type, one of: svd, atdf, json
regz_gen.addArg(@tagName(chip.register_definition));
regz_gen.addArg("--output_path"); // Write to a file
const zig_file = regz_gen.addOutputFileArg("chip.zig");
regz_gen.addFileArg(file);
break :blk zig_file;
},
.zig => |src| src,
};
const config = host_build.addOptions();
config.addOption(bool, "has_hal", (maybe_hal != null));
config.addOption(bool, "has_board", (maybe_board != null));
config.addOption(?[]const u8, "board_name", if (maybe_board) |brd| brd.name else null);
config.addOption([]const u8, "chip_name", chip.name);
config.addOption([]const u8, "cpu_name", chip.name);
config.addOption(usize, "end_of_stack", first_ram.offset + first_ram.length);
const fw: *Firmware = host_build.allocator.create(Firmware) catch @panic("out of memory");
fw.* = Firmware{
.mz = mz,
.host_build = host_build,
.artifact = host_build.addExecutable(.{
.name = options.name,
.optimize = options.optimize,
.target = cpu.target,
.linkage = .static,
.root_source_file = .{ .cwd_relative = mz.self.builder.pathFromRoot("src/start.zig") },
}),
.target = options.target,
.output_files = Firmware.OutputFileMap.init(host_build.allocator),
.config = config,
.modules = .{
.microzig = micro_build.createModule(.{
.source_file = .{ .cwd_relative = micro_build.pathFromRoot("src/microzig.zig") },
.dependencies = &.{
.{
.name = "config",
.module = micro_build.createModule(.{ .source_file = config.getSource() }),
},
},
}),
.cpu = undefined,
.chip = undefined,
.board = null,
.hal = null,
.app = undefined,
},
};
errdefer fw.output_files.deinit();
fw.modules.chip = micro_build.createModule(.{
.source_file = chip_source,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("chip", fw.modules.chip) catch @panic("out of memory");
fw.modules.cpu = micro_build.createModule(.{
.source_file = cpu.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("cpu", fw.modules.cpu) catch @panic("out of memory");
if (maybe_hal) |hal| {
fw.modules.hal = micro_build.createModule(.{
.source_file = hal.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("hal", fw.modules.hal.?) catch @panic("out of memory");
}
if (maybe_board) |brd| {
fw.modules.board = micro_build.createModule(.{
.source_file = brd.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
fw.modules.microzig.dependencies.put("board", fw.modules.board.?) catch @panic("out of memory");
}
fw.modules.app = host_build.createModule(.{
.source_file = options.source_file,
.dependencies = &.{
.{ .name = "microzig", .module = fw.modules.microzig },
},
});
const umm = mz.dependency("umm-zig", .{}).module("umm");
fw.modules.microzig.dependencies.put("umm", umm) catch @panic("out of memory");
fw.artifact.addModule("app", fw.modules.app);
fw.artifact.addModule("microzig", fw.modules.microzig);
fw.artifact.strip = false; // we always want debug symbols, stripping brings us no benefit on embedded
fw.artifact.single_threaded = options.single_threaded orelse fw.target.single_threaded;
fw.artifact.bundle_compiler_rt = options.bundle_compiler_rt orelse fw.target.bundle_compiler_rt;
switch (linker_script) {
.generated => {
fw.artifact.setLinkerScript(
generateLinkerScript(host_build, chip.*) catch @panic("out of memory"),
);
},
.source_file => |source| {
fw.artifact.setLinkerScriptPath(source);
},
}
if (options.target.configure) |configure| {
configure(host_build, fw);
}
return fw;
}
/// Configuration options for firmware installation.
pub const InstallFirmwareOptions = struct {
/// Overrides the output format for the binary. If not set, the standard preferred file format for the firmware target is used.
format: ?BinaryFormat = null,
};
/// Adds a new dependency to the `install` step that will install the `firmware` into the folder `$prefix/firmware`.
pub fn installFirmware(
/// The MicroZig instance that was used to create the firmware.
mz: *MicroZig,
/// The instance of the `build.zig` that should perform installation.
b: *std.Build,
/// The firmware that should be installed. Please make sure that this was created with the same `MicroZig` instance as `mz`.
firmware: *Firmware,
/// Optional configuration of the installation process. Pass `.{}` if you're not sure what to do here.
options: InstallFirmwareOptions,
) void {
std.debug.assert(mz == firmware.mz);
const install_step = addInstallFirmware(mz, b, firmware, options);
b.getInstallStep().dependOn(&install_step.step);
}
/// Creates a new `std.Build.Step.InstallFile` instance that will install the given firmware to `$prefix/firmware`.
///
/// **NOTE:** This does not actually install the firmware yet. You have to add the returned step as a dependency to another step.
/// If you want to just install the firmware, use `installFirmware` instead!
pub fn addInstallFirmware(
/// The MicroZig instance that was used to create the firmware.
mz: *MicroZig,
/// The instance of the `build.zig` that should perform installation.
b: *std.Build,
/// The firmware that should be installed. Please make sure that this was created with the same `MicroZig` instance as `mz`.
firmware: *Firmware,
/// Optional configuration of the installation process. Pass `.{}` if you're not sure what to do here.
options: InstallFirmwareOptions,
) *std.Build.Step.InstallFile {
const format = firmware.resolveFormat(options.format);
const basename = b.fmt("{s}{s}", .{
firmware.artifact.name,
format.getExtension(),
});
_ = mz;
return b.addInstallFileWithDir(firmware.getEmittedBin(format), .{ .custom = "firmware" }, basename);
}
/// Declaration of a firmware build.
pub const Firmware = struct {
const OutputFileMap = std.ArrayHashMap(BinaryFormat, std.Build.LazyPath, BinaryFormat.Context, false);
@ -629,9 +755,9 @@ pub const Firmware = struct {
};
// privates:
mz: *MicroZig,
env: *BuildEnvironment,
host_build: *std.Build,
target: Target,
target: *const Target,
output_files: OutputFileMap,
// publics:
@ -702,7 +828,7 @@ pub const Firmware = struct {
},
.uf2 => |family_id| blk: {
const uf2_exe = firmware.mz.dependency("uf2", .{ .optimize = .ReleaseSafe }).artifact("elf2uf2");
const uf2_exe = firmware.env.dependency("uf2", .{ .optimize = .ReleaseSafe }).artifact("elf2uf2");
const convert = firmware.host_build.addRunArtifact(uf2_exe);
@ -847,10 +973,6 @@ fn buildConfigError(b: *std.Build, comptime fmt: []const u8, args: anytype) nore
@panic(msg);
}
fn dependency(mz: *MicroZig, name: []const u8, args: anytype) *std.Build.Dependency {
return mz.self.builder.dependency(name, args);
}
fn generateLinkerScript(b: *std.Build, chip: Chip) !std.Build.LazyPath {
const cpu = chip.cpu.getDescriptor();

File diff suppressed because it is too large Load Diff

@ -0,0 +1,28 @@
const std = @import("std");
const MicroZig = @import("../build/build.zig"); // "microzig-build"
pub fn build(b: *std.Build) void {
const microzig = MicroZig.createBuildEnvironment(b, .{
.self = "microzig", // package name of the build package (optional)
.core = "microzig-core", // package name of the core package (optional)
.board_support = &.{
// package names for BSP packages:
"microzig-bsp-nxp",
"microzig-bsp-rp2040",
},
});
const optimize = b.standardOptimizeOption(.{});
const target_name = b.option([]const u8, "target", "Select the target to build for.") orelse "board:mbed/lpc1768";
const target = microzig.findTarget(target_name).?;
const firmware = microzig.addFirmware(b, .{
.name = "blinky",
.target = target,
.optimize = optimize,
.source_file = .{ .path = "src/empty.zig" },
});
microzig.installFirmware(b, firmware, .{});
}

@ -1,5 +0,0 @@
# Examples for the BSP `nxp-lpc`
- [Blinky](src/blinky.zig) on [nRF52840 Dongle](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle)
TODO: Implement this!

@ -1,33 +0,0 @@
const std = @import("std");
const microzig_build = @import("microzig-build");
const lpc = @import("lpc");
pub fn build(b: *std.Build) void {
const microbuild = microzig_build.init(
b,
b.dependency("microzig", .{}),
);
const optimize = b.standardOptimizeOption(.{});
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microbuild.addFirmware(b, .{
.name = "blinky",
.target = lpc.boards.mbed.lpc1768,
.optimize = optimize,
.source_file = .{ .path = "src/blinky.zig" },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microbuild.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microbuild.installFirmware(b, firmware, .{ .format = .elf });
}

@ -1,14 +0,0 @@
.{
.name = "microzig-nxp-lpc-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.lpc = .{
.url = "https://github.com/ZigEmbeddedGroup/nxp-lpc/archive/130a1316c0892415e7da958a5e9548ed87bba54d.tar.gz",
.hash = "1220165879f85a1d51656d35b3963a95f3585dc665fc7414f76aa6aad4e6635536cf",
},
},
}

@ -1,56 +0,0 @@
const std = @import("std");
const microzig = @import("microzig");
const chip = microzig.chip;
// LED-1: P1.18
// LED-2: P1.20
// LED-3: P1.21
// LED-4: P1.23
const conn = chip.peripherals.PINCONNECT;
const gpio: *volatile [5]PatchedGpio = @ptrCast(@alignCast(chip.peripherals.GPIO));
const led_mask = [4]u32{
(1 << 18),
(1 << 20),
(1 << 21),
(1 << 23),
};
const all_mask = led_mask[0] | led_mask[1] | led_mask[2] | led_mask[3];
pub fn main() !void {
conn.PINSEL3.modify(.{
.P1_18 = .{ .value = .GPIO_P1 },
.P1_20 = .{ .value = .GPIO_P1 },
.P1_21 = .{ .value = .GPIO_P1 },
.P1_23 = .{ .value = .GPIO_P1 },
});
const p1 = &gpio[1];
p1.dir = all_mask;
while (true) {
for (led_mask) |mask| {
p1.pin_clr = (all_mask & ~mask);
p1.pin_set = mask;
microzig.core.experimental.debug.busy_sleep(100_000);
}
}
}
const PatchedGpio = extern struct {
dir: u32, // 0x2009 C000
__padding0: u32, // 0x2009 C004
__padding1: u32, // 0x2009 C008
__padding2: u32, // 0x2009 C00C
mask: u32, // 0x2009 C010
pin: u32, // 0x2009 C014
pin_set: u32, // 0x2009 C018
pin_clr: u32, // 0x2009 C01C
comptime {
std.debug.assert(@sizeOf(PatchedGpio) == 0x20);
}
};

@ -0,0 +1,32 @@
const std = @import("std");
const MicroZig = @import("microzig");
pub fn build(b: *std.Build) void {
const microzig = MicroZig.createBuildEnvironment(b, .{
.self = "microzig", // package name of the build package (optional)
.core = "microzig-core", // package name of the core package (optional)
.board_support = &.{
// package names for BSP packages:
"microzig-bsp-nxp",
"microzig-bsp-rp2040",
},
});
const optimize = b.standardOptimizeOption(.{});
const target_name = b.option([]const u8, "target", "Select the target to build for.") orelse "board:mbed/lpc1768";
for (microzig.targets.keys()) |listed_target_name| {
std.debug.print("- '{s}'\n", .{listed_target_name});
}
const target = microzig.findTarget(target_name).?;
const firmware = microzig.addFirmware(b, .{
.name = "blinky",
.target = target,
.optimize = optimize,
.source_file = .{ .path = "src/empty.zig" },
});
microzig.installFirmware(b, firmware, .{});
}

@ -0,0 +1,22 @@
.{
.name = "microzig-nxp-lpc-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://public.devspace.random-projects.net/microzig-build.tar.gz",
.hash = "122068db50e2a071cac3fc5b42d5cd2213ccb563986af60b941cb7af29b83df65b02",
},
.@"microzig-core" = .{
.url = "https://public.devspace.random-projects.net/microzig-core.tar.gz",
.hash = "12202df033d2b967108b25b8e66d8c8abcf690348a24baa35474a28086170ff31e54",
},
.@"microzig-bsp-nxp" = .{
.url = "https://public.devspace.random-projects.net/board-support/nxp/lpc.tar.gz",
.hash = "12201efd8d8b992caef770c87d78e6bd00bd73051bd1559bc342703f2e83650ef2f9",
},
.@"microzig-bsp-rp2040" = .{
.url = "https://public.devspace.random-projects.net/board-support/raspberrypi/rp2040.tar.gz",
.hash = "1220154cd3634d0f3286cd2fb727cce9af3f3ab166772065e3efe4f9577128f4c559",
},
},
}

@ -0,0 +1,8 @@
const std = @import("std");
const microzig = @import("microzig");
pub fn main() !void {
while (true) {
asm volatile ("" ::: "memory");
}
}

@ -46,7 +46,7 @@ pub fn main() !void {
// defer decompress.deinit();
var arc = try Archive.read_from_tar(arena, buffered.reader(), .{
.strip_components = 0,
.strip_components = 1,
});
defer arc.deinit(arena);
@ -57,7 +57,23 @@ pub fn main() !void {
try paths.appendSlice(arc.files.keys());
std.mem.sort([]const u8, paths.items, {}, Archive.path_less_than);
const calculated_hash = try arc.hash(allocator, .ignore_executable_bit);
const calculated_hash = blk: {
var arc_hasher = Hash.init(.{});
for (paths.items) |path| {
const archived_file = arc.files.getPtr(path).?;
var file_hasher = Hash.init(.{});
file_hasher.update(path);
file_hasher.update(&.{ 0, 0 }); // second part is "executable bit"
file_hasher.update(archived_file.text);
arc_hasher.update(&file_hasher.finalResult());
}
break :blk arc_hasher.finalResult();
};
var hash_buf: [4 + 2 * calculated_hash.len]u8 = undefined;
const hash_str = try std.fmt.bufPrint(&hash_buf, "1220{}", .{std.fmt.fmtSliceHexLower(&calculated_hash)});
@ -92,13 +108,13 @@ const Archive = struct {
return if (mod > 0) 512 - mod else 0;
}
pub fn entry_should_be_skipped(path: []const u8) !bool {
var it = try std.fs.path.componentIterator(path);
const first = it.next().?;
return std.mem.eql(u8, first.name, ".git") or
std.mem.eql(u8, first.name, "zig-out") or
std.mem.eql(u8, first.name, "zig-cache");
}
// pub fn entry_should_be_skipped(path: []const u8) !bool {
// var it = try std.fs.path.componentIterator(path);
// const first = it.next().?;
// return std.mem.eql(u8, first.name, ".git") or
// std.mem.eql(u8, first.name, "zig-out") or
// std.mem.eql(u8, first.name, "zig-cache");
// }
fn stripComponents(path: []const u8, count: u32) ![]const u8 {
var i: usize = 0;
@ -240,35 +256,4 @@ const Archive = struct {
return (mode & std.os.S.IXUSR) != 0;
}
}
pub fn hash(
archive: Archive,
allocator: Allocator,
executable_bit: WhatToDoWithExecutableBit,
) ![Hash.digest_length]u8 {
var paths = std.ArrayList([]const u8).init(allocator);
defer paths.deinit();
var hashes = std.ArrayList([Hash.digest_length]u8).init(allocator);
defer hashes.deinit();
try paths.appendSlice(archive.files.keys());
try hashes.appendNTimes(undefined, paths.items.len);
std.mem.sort([]const u8, paths.items, {}, path_less_than);
for (paths.items, hashes.items) |path, *result| {
const file = archive.files.get(path).?;
var hasher = Hash.init(.{});
hasher.update(path);
hasher.update(&.{ 0, @intFromBool(is_executable(file.mode, executable_bit)) });
hasher.update(file.text);
hasher.final(result);
}
var hasher = Hash.init(.{});
for (hashes.items) |file_hash|
hasher.update(&file_hash);
return hasher.finalResult();
}
};

@ -16,6 +16,8 @@ from marshmallow import fields
from enum import Enum as StrEnum
import pathspec
import stat
import tarfile
from marshmallow import fields as mm_fields
from typing import Optional, Any
@ -26,7 +28,8 @@ REQUIRED_TOOLS = [
"zig",
"git",
]
DEPLOYMENT_BASE="https://download.microzig.tech/packages"
# DEPLOYMENT_BASE="https://download.microzig.tech/packages"
DEPLOYMENT_BASE="https://public.devspace.random-projects.net"
REPO_ROOT = Path(__file__).parent.parent
assert REPO_ROOT.is_dir()
@ -300,13 +303,17 @@ def main():
pkg.package_dir = pkg_dir
if pkg.package_type == PackageType.core:
if pkg.package_type == PackageType.build:
pkg.out_rel_dir = PurePosixPath(".")
pkg.out_basename = pkg.package_name
elif pkg.package_type == PackageType.build:
elif pkg.package_type == PackageType.core:
pkg.out_rel_dir = PurePosixPath(".")
pkg.out_basename = pkg.package_name
# Implicit dependencies:
pkg.inner_dependencies.add("microzig-build") # core requires the build types
elif pkg.package_type == PackageType.board_support:
parsed_pkg_name = PurePosixPath(pkg.package_name)
@ -314,7 +321,9 @@ def main():
pkg.out_rel_dir = "board-support" / parsed_pkg_name.parent
pkg.out_basename = parsed_pkg_name.name
pkg.inner_dependencies.add("microzig-core") # BSPs implicitly depend on the core "microzig" package
# Implicit dependencies:
pkg.inner_dependencies.add("microzig-build") # BSPs also require build types
pkg.inner_dependencies.add("microzig-core") # but also the core types (?)
else:
assert False
@ -373,7 +382,7 @@ def main():
pkg_cache_dir.mkdir(exist_ok=True)
meta_path = pkg_dir / "microzig-package.json"
pkg_zon_file = pkg_cache_dir / "build.zig.zon"
pkg_zon_file = pkg_cache_dir / pkg_dir.name / "build.zig.zon"
out_rel_dir: PurePosixPath = pkg.out_rel_dir
out_basename: str = pkg.out_basename
@ -383,9 +392,9 @@ def main():
"zig", "build-exe",
f"{REPO_ROOT}/tools/extract-bsp-info.zig" ,
"--cache-dir", f"{REPO_ROOT}/zig-cache",
"--deps", "bsp,microzig",
"--mod", f"bsp:microzig:{pkg_dir}/build.zig",
"--mod", f"microzig:uf2:{REPO_ROOT}/core/build.zig",
"--deps", "bsp,microzig-build",
"--mod", f"bsp:microzig-build:{pkg_dir}/build.zig",
"--mod", f"microzig-build:uf2:{REPO_ROOT}/build/build.zig",
"--mod", f"uf2::{REPO_ROOT}/tools/lib/dummy_uf2.zig",
"--name", "extract-bsp-info",
cwd=pkg_cache_dir,
@ -440,7 +449,8 @@ def main():
print()
# tar -cf "${out_tar}" $(git ls-files -- . ':!:microzig-package.json')
execute("tar", "-cf", out_file_tar, "--hard-dereference", *package_files, cwd=pkg_dir)
execute("tar", "-cf", out_file_tar, "--hard-dereference", *( f"{pkg_dir.name}/{file}" for file in package_files), cwd=pkg_dir.parent)
zon_data = slurp(
tools["create_pkg_descriptor"],
@ -448,12 +458,14 @@ def main():
input=PackageConfigurationSchema.dumps(evaluation_ordered_packages, many=True ).encode(),
)
pkg_zon_file.parent.mkdir(exist_ok=True)
with pkg_zon_file.open("wb") as f:
f.write(zon_data)
slurp("zig", "fmt", pkg_zon_file) # slurp the message away
execute("tar", "-rf", out_file_tar, "--hard-dereference", pkg_zon_file.name, cwd=pkg_zon_file.parent)
execute("tar", "-rf", out_file_tar, "--hard-dereference", f"{pkg_zon_file.parent.name}/{pkg_zon_file.name}", cwd=pkg_zon_file.parent.parent)
# tar --list --file "${out_tar}" > "${pkg_cache_dir}/contents.list"

@ -127,7 +127,7 @@ pub fn main() !void {
try renderDep(
stdout,
"microzig",
dep_name,
dep.download_url.?,
dep.package.?.hash,
);

@ -5,7 +5,7 @@
const std = @import("std");
const bsp = @import("bsp");
const microzig = @import("microzig");
const microzig = @import("microzig-build");
const JsonTarget = struct {
id: []const u8,

@ -0,0 +1,74 @@
#!/usr/bin/env python3
#
# Hacky auto-patcher to update dependencies in examples.
#
# Receives a **formatted(!)** build.zig.zon that requires ".url" and ".hash" to be written in that order on different lines.
#
import sys
import json
from urllib.parse import urlparse, urlunparse
from urllib.request import urlopen
from pathlib import Path, PurePosixPath
import re
def main():
build_zig_zon = Path(sys.argv[1])
assert build_zig_zon.is_file()
input_lines = build_zig_zon.read_text().splitlines()
output_lines = []
last_pkg_url: urllib.parse.ParseResult = None
for line in input_lines:
stripped = line.strip()
if stripped.startswith(".url = \""):
match = re.match('\s*\.url\s*=\s*"([^"]+)",', line)
urlstr = match.group(1)
last_pkg_url = urlparse(urlstr)
output_lines.append(line)
elif stripped.startswith(".hash = \""):
try:
pkg_path = PurePosixPath(last_pkg_url.path)
assert pkg_path.suffixes == ['.tar', '.gz']
pkg_json_url = urlunparse(
# scheme, netloc, url, params, query, fragment
(
last_pkg_url.scheme, # scheme
last_pkg_url.netloc, # netloc
pkg_path.with_suffix("").with_suffix(".json").as_posix(), # url
last_pkg_url.params, # params
last_pkg_url.query, # query
last_pkg_url.fragment, # fragment
)
)
metadata = json.loads(urlopen(pkg_json_url).read())
pkg_hash = metadata["package"]["hash"]
line_prefix = re.match("^(\s*)", line).group(1)
output_lines.append(f'{line_prefix}.hash = "{pkg_hash}",')
last_pkg_url = None
except BaseException as ex:
print(ex)
output_lines.append(line)
else:
output_lines.append(line)
build_zig_zon.write_text("\n".join(output_lines))
if __name__ == "__main__":
main()
Loading…
Cancel
Save