Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: posix native targets #183

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .envrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# use_nix
use_flake
if has nix; then
use flake
fi
38 changes: 38 additions & 0 deletions bsp/posix/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const std = @import("std");
const Build = std.Build;

const MicroZig = @import("microzig/build");
const Target = MicroZig.Target;
const Firmware = MicroZig.Firmware;

fn root() []const u8 {
return comptime (std.fs.path.dirname(@src().file) orelse ".");
}
const build_root = root();

pub fn build(b: *Build) !void {
_ = b;
}

pub const chips = struct {
pub const posix = Target{
.preferred_format = .{ .elf = {} },
.chip = chip,
.hal = hal,
.linker_script = .{ .none = {} },
.board = null,
};
};
pub const boards = struct {};

const hal = .{
.root_source_file = .{ .cwd_relative = build_root ++ "/src/hal.zig" },
};

const chip = .{
.name = "POSIX",
.url = "TODO",
.cpu = .{ .name = "native-posix4", .root_source_file = .{ .path = build_root ++ "/src/startup.zig" }, .target = .{} },
.register_definition = .{ .zig = .{ .path = build_root ++ "/src/empty.zig" } },
.memory_regions = &.{},
};
12 changes: 12 additions & 0 deletions bsp/posix/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.{
.name = "bsp/posix",
.version = "0.0.0",
.dependencies = .{
.@"microzig/build" = .{
.path = "../../build",
},
},
.paths = .{
"build.zig.zon",
},
}
5 changes: 5 additions & 0 deletions bsp/posix/src/empty.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub const devices = struct {
pub const POSIX = struct {
//
};
};
4 changes: 4 additions & 0 deletions bsp/posix/src/hal.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const std = @import("std");
const microzig = @import("microzig");

pub fn init() void {}
9 changes: 9 additions & 0 deletions bsp/posix/src/startup.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub fn disable_interrupts() void {}
pub const startup_logic = struct {
extern fn microzig_main() noreturn;
pub fn _start() callconv(.C) noreturn {
microzig_main();
}
};

pub fn export_startup_logic() void {}
2 changes: 1 addition & 1 deletion bsp/raspberrypi/rp2040/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ pub const BootROM = union(enum) {
};

const linker_script = .{
.path = build_root ++ "/rp2040.ld",
.explicit = .{ .path = build_root ++ "/rp2040.ld" },
};

const hal = .{
Expand Down
10 changes: 7 additions & 3 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ const example_dep_names: []const []const u8 = &.{
"examples/nxp/lpc",
"examples/microchip/atsam",
//"examples/microchip/avr",
"examples/gigadevice/gd32",
"examples/stmicro/stm32",
// TODO: both are borked for some reasons
// "examples/gigadevice/gd32",
// "examples/stmicro/stm32",
//"examples/espressif/esp",
"examples/raspberrypi/rp2040",
"examples/posix",
};

const bsps = .{
Expand All @@ -23,6 +25,7 @@ const bsps = .{
.{ "bsp/stmicro/stm32", @import("bsp/stmicro/stm32") },
.{ "bsp/espressif/esp", @import("bsp/espressif/esp") },
.{ "bsp/raspberrypi/rp2040", @import("bsp/raspberrypi/rp2040") },
.{ "bsp/posix", @import("bsp/posix") },
};

pub fn build(b: *Build) void {
Expand Down Expand Up @@ -58,7 +61,8 @@ pub fn build(b: *Build) void {
const test_bsps_step = b.step("run-bsp-tests", "Run all platform agnostic tests for BSPs");
inline for (bsps) |bsp| {
const bsp_dep = b.dependency(bsp[0], .{});
test_bsps_step.dependOn(&bsp_dep.builder.top_level_steps.get("test").?.step);
if (bsp_dep.builder.top_level_steps.get("test")) |t|
test_bsps_step.dependOn(&t.step);
}
}

Expand Down
2 changes: 2 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
.@"bsp/stmicro/stm32" = .{ .path = "bsp/stmicro/stm32" },
.@"bsp/espressif/esp" = .{ .path = "bsp/espressif/esp" },
.@"bsp/raspberrypi/rp2040" = .{ .path = "bsp/raspberrypi/rp2040" },
.@"bsp/posix" = .{ .path = "bsp/posix" },

// examples so that we can build them all in one go
.@"examples/nordic/nrf5x" = .{ .path = "examples/nordic/nrf5x" },
Expand All @@ -26,6 +27,7 @@
.@"examples/stmicro/stm32" = .{ .path = "examples/stmicro/stm32" },
.@"examples/espressif/esp" = .{ .path = "examples/espressif/esp" },
.@"examples/raspberrypi/rp2040" = .{ .path = "examples/raspberrypi/rp2040" },
.@"examples/posix" = .{ .path = "examples/posix" },

// used for creating package tarballs
.boxzer = .{
Expand Down
59 changes: 35 additions & 24 deletions build/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ pub fn add_firmware(

// 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: {
const first_ram: defs.MemoryRegion = 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");
// for native targets create dummy ram region
} else if (chip.cpu.target.os_tag == null) break :blk .{ .kind = .ram, .offset = 0, .length = 0 } else @panic("no ram memory region found for setting the end-of-stack address");
};

// On demand, generate chip definitions via regz:
Expand Down Expand Up @@ -204,29 +205,33 @@ pub fn add_firmware(

fw.artifact.bundle_compiler_rt = options.bundle_compiler_rt orelse fw.target.bundle_compiler_rt;

if (linker_script) |ls| {
fw.artifact.setLinkerScriptPath(ls);
} else {
const target = mz.host_build.resolveTargetQuery(chip.cpu.target);
const generate_linkerscript_args = GenerateLinkerscriptArgs{
.cpu_name = target.result.cpu.model.name,
.cpu_arch = target.result.cpu.arch,
.chip_name = chip.name,
.memory_regions = chip.memory_regions,
};
switch (linker_script) {
.explicit => |ls| {
fw.artifact.setLinkerScriptPath(ls);
},
.generated => {
const target = mz.host_build.resolveTargetQuery(chip.cpu.target);
const generate_linkerscript_args = GenerateLinkerscriptArgs{
.cpu_name = target.result.cpu.model.name,
.cpu_arch = target.result.cpu.arch,
.chip_name = chip.name,
.memory_regions = chip.memory_regions,
};

const args_str = std.json.stringifyAlloc(
mz.microzig_core.builder.allocator,
generate_linkerscript_args,
.{},
) catch @panic("OOM");
const args_str = std.json.stringifyAlloc(
mz.microzig_core.builder.allocator,
generate_linkerscript_args,
.{},
) catch @panic("OOM");

const generate_linkerscript_run = mz.microzig_core.builder.addRunArtifact(mz.generate_linkerscript);
generate_linkerscript_run.addArg(args_str);
const linkerscript = generate_linkerscript_run.addOutputFileArg("linker.ld");
const generate_linkerscript_run = mz.microzig_core.builder.addRunArtifact(mz.generate_linkerscript);
generate_linkerscript_run.addArg(args_str);
const linkerscript = generate_linkerscript_run.addOutputFileArg("linker.ld");

// If not specified then generate the linker script
fw.artifact.setLinkerScript(linkerscript);
// If not specified then generate the linker script
fw.artifact.setLinkerScript(linkerscript);
},
.none => {},
}

if (options.target.configure) |configure| {
Expand Down Expand Up @@ -317,7 +322,7 @@ pub const Target = struct {
board: ?BoardDefinition = null,

/// (optional) Provide a custom linker script for the hardware or define a custom generation.
linker_script: ?LazyPath = null,
linker_script: LinkerScript = .{ .generated = {} },

/// (optional) Further configures the created firmware depending on the chip and/or board settings.
/// This can be used to set/change additional properties on the created `*Firmware` object.
Expand All @@ -327,6 +332,12 @@ pub const Target = struct {
binary_post_process: ?*const fn (host_build: *std.Build, LazyPath) std.Build.LazyPath = null,
};

pub const LinkerScript = union(enum) {
generated: void,
explicit: LazyPath,
none: void,
};

/// Options to the `add_firmware` function.
pub const FirmwareOptions = struct {
/// The name of the firmware file.
Expand Down Expand Up @@ -357,7 +368,7 @@ pub const FirmwareOptions = struct {
board: ?BoardDefinition = null,

/// If set, overrides the `linker_script` property of the target.
linker_script: ?LazyPath = null,
linker_script: ?LinkerScript = null,
};

/// Configuration options for firmware installation.
Expand Down
7 changes: 7 additions & 0 deletions core/src/start.zig
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,10 @@ pub fn initialize_system_memories() void {
@memcpy(data_start[0..data_len], data_src[0..data_len]);
}
}

// for native(for example linux/windows) targets we need to export the main function
pub usingnamespace if (@import("builtin").os.tag != .freestanding) struct {
pub fn main() void {
microzig.cpu.startup_logic._start();
}
} else struct {};
42 changes: 42 additions & 0 deletions examples/posix/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const std = @import("std");
const MicroZig = @import("microzig/build");
const posix = @import("microzig/bsp/posix");

const available_examples = [_]Example{
.{ .target = posix.chips.posix, .name = "posix_uart", .file = "src/uart.zig" },
};

pub fn build(b: *std.Build) void {
const mz = MicroZig.init(b, .{});
const optimize = b.standardOptimizeOption(.{});

for (available_examples) |example| {

// `add_firmware` 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 = mz.add_firmware(b, .{
.name = example.name,
.target = example.target,
.optimize = optimize,
.root_source_file = .{ .path = example.file },
});

// `install_firmware()` 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`.
mz.install_firmware(b, firmware, .{});

// For debugging, we also always install the firmware as an ELF file
mz.install_firmware(b, firmware, .{ .format = .elf });
}
}

const Example = struct {
target: MicroZig.Target,
name: []const u8,
file: []const u8,
};
13 changes: 13 additions & 0 deletions examples/posix/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.{
.name = "examples/posix",
.version = "0.0.0",
.dependencies = .{
.@"microzig/build" = .{ .path = "../../build" },
.@"microzig/bsp/posix" = .{ .path = "../../bsp/posix" },
},

.paths = .{
"build.zig",
"build.zig.zon",
},
}
15 changes: 15 additions & 0 deletions examples/posix/src/uart.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const std = @import("std");
const microzig = @import("microzig");

pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
std.log.err("panic: {s}", .{message});
@breakpoint();
while (true) {}
}

pub const microzig_options = .{
.log_level = .debug,
// .logFn = rp2040.uart.log,
};

pub fn main() !void {}
Loading
Loading