Skip to content
Merged
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
69 changes: 29 additions & 40 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -476,47 +476,39 @@ pub fn MicroBuild(port_select: PortSelect) type {
core_mod.addImport("board", board_mod);
}

const app_mod = mb.builder.createModule(.{
const root_mod = mb.builder.createModule(.{
.root_source_file = options.root_source_file,
.imports = options.imports,
.target = zig_resolved_target,
.optimize = options.optimize,
.single_threaded = options.single_threaded orelse target.single_threaded,
.strip = options.strip,
.unwind_tables = options.unwind_tables,
.error_tracing = options.error_tracing,
.dwarf_format = options.dwarf_format,
});
app_mod.addImport("microzig", core_mod);
core_mod.addImport("app", app_mod);
root_mod.addImport("microzig", core_mod);

const fw = mb.builder.allocator.create(Firmware) catch @panic("out of memory");
fw.* = .{
.mb = mb,
.core_mod = core_mod,
.artifact = mb.builder.addExecutable(.{
.exe = mb.builder.addExecutable(.{
.name = options.name,
.root_module = b.createModule(.{
.optimize = options.optimize,
.target = zig_resolved_target,
.root_source_file = mb.core_dep.path("src/start.zig"),
.single_threaded = options.single_threaded orelse target.single_threaded,
.strip = options.strip,
.unwind_tables = options.unwind_tables,
.error_tracing = options.error_tracing,
.dwarf_format = options.dwarf_format,
}),
.root_module = root_mod,
.linkage = .static,
}),
.app_mod = app_mod,
.target = target,
.emitted_files = Firmware.EmittedFiles.init(mb.builder.allocator),
};

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

fw.artifact.link_gc_sections = options.strip_unused_symbols;
fw.artifact.link_function_sections = options.strip_unused_symbols;
fw.artifact.link_data_sections = options.strip_unused_symbols;
fw.artifact.entry = options.entry orelse target.entry orelse .default;

fw.artifact.root_module.addImport("microzig", core_mod);
fw.artifact.root_module.addImport("app", app_mod);
fw.exe.link_gc_sections = options.strip_unused_symbols;
fw.exe.link_function_sections = options.strip_unused_symbols;
fw.exe.link_data_sections = options.strip_unused_symbols;
fw.exe.entry = options.entry orelse target.entry orelse .default;

const linker_script_options = options.linker_script orelse target.linker_script;
const linker_script = blk: {
Expand Down Expand Up @@ -551,7 +543,7 @@ pub fn MicroBuild(port_select: PortSelect) type {
}
break :blk output;
};
fw.artifact.setLinkerScript(linker_script);
fw.exe.setLinkerScript(linker_script);

return fw;
}
Expand Down Expand Up @@ -579,7 +571,7 @@ pub fn MicroBuild(port_select: PortSelect) type {
const format = options.format orelse fw.target.preferred_binary_format orelse .elf;

const basename = mb.builder.fmt("{s}{s}", .{
fw.artifact.name,
fw.exe.name,
format.get_extension(),
});

Expand All @@ -593,10 +585,7 @@ pub fn MicroBuild(port_select: PortSelect) type {
mb: *Self,

/// The artifact that is built by MicroZig.
artifact: *Build.Step.Compile,

/// The app module that is built by Zig.
app_mod: *Build.Module,
exe: *Build.Step.Compile,

// The @import("microzig") module
core_mod: *Build.Module,
Expand All @@ -615,7 +604,7 @@ pub fn MicroBuild(port_select: PortSelect) type {
/// not include post processing of the ELF files necessary by certain targets.
pub fn get_emitted_elf(fw: *Firmware) LazyPath {
if (fw.emitted_elf == null) {
const raw_elf = fw.artifact.getEmittedBin();
const raw_elf = fw.exe.getEmittedBin();
fw.emitted_elf = if (fw.target.patch_elf) |patch_elf|
patch_elf(fw.target.dep, raw_elf)
else
Expand All @@ -636,7 +625,7 @@ pub fn MicroBuild(port_select: PortSelect) type {
const elf_file = fw.get_emitted_elf();

const basename = fw.mb.builder.fmt("{s}{s}", .{
fw.artifact.name,
fw.exe.name,
resolved_format.get_extension(),
});

Expand Down Expand Up @@ -708,8 +697,8 @@ pub fn MicroBuild(port_select: PortSelect) type {
pub fn get_emitted_docs(fw: *Firmware) LazyPath {
if (fw.emitted_docs == null) {
const docs_test = fw.mb.builder.addTest(.{
.name = fw.artifact.name,
.root_module = fw.app_mod,
.name = fw.exe.name,
.root_module = fw.exe.root_module,
});

fw.emitted_docs = docs_test.getEmittedDocs();
Expand All @@ -727,32 +716,32 @@ pub fn MicroBuild(port_select: PortSelect) type {
if (options.depend_on_microzig) {
module.addImport("microzig", fw.core_mod);
}
fw.app_mod.addImport(name, module);
fw.exe.root_module.addImport(name, module);
}

/// Adds an include path to the firmware.
pub fn add_include_path(fw: *Firmware, path: LazyPath) void {
fw.artifact.addIncludePath(path);
fw.exe.addIncludePath(path);
}

/// Adds a system include path to the firmware.
pub fn add_system_include_path(fw: *Firmware, path: LazyPath) void {
fw.artifact.addSystemIncludePath(path);
fw.exe.addSystemIncludePath(path);
}

/// Adds a c source file to the firmware.
pub fn add_c_source_file(fw: *Firmware, source: Build.Module.CSourceFile) void {
fw.artifact.addCSourceFile(source);
fw.exe.addCSourceFile(source);
}

/// Adds options to your application.
pub fn add_options(fw: *Firmware, module_name: []const u8, options: *Build.Step.Options) void {
fw.app_mod.addOptions(module_name, options);
fw.exe.root_module.addOptions(module_name, options);
}

/// Adds an object file to the firmware.
pub fn add_object_file(fw: *Firmware, source: LazyPath) void {
fw.artifact.addObjectFile(source);
fw.exe.addObjectFile(source);
}
};

Expand Down
3 changes: 0 additions & 3 deletions core/src/cpus/cortex_m.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ const std = @import("std");
const builtin = @import("builtin");
const microzig = @import("microzig");
const mmio = microzig.mmio;
const app = microzig.app;
const shared = @import("cortex_m/shared_types.zig");
const VectorTable = microzig.chip.VectorTable;

const Core = enum {
Expand Down Expand Up @@ -1026,7 +1024,6 @@ pub fn export_startup_logic() void {

const scs_base = 0xE000E000;
const itm_base = 0xE0000000;
const dwt_base = 0xE0001000;
const tpi_base = 0xE0040000;

const coredebug_base = 0xE000EDF0;
Expand Down
117 changes: 92 additions & 25 deletions core/src/microzig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@

const std = @import("std");
const root = @import("root");
const builtin = @import("builtin");

/// The app that is currently built.
pub const app = @import("app");

/// Contains build-time generated configuration options for microzig.
/// Contains a CPU target description, chip, board and cpu information
Expand Down Expand Up @@ -67,26 +63,6 @@ pub const CPU_Options = if (@hasDecl(cpu, "CPU_Options")) cpu.CPU_Options else s
pub const HAL_Options = if (config.has_hal and @hasDecl(hal, "HAL_Options")) hal.HAL_Options else struct {};

pub const Options = struct {
log_level: std.log.Level = std.log.default_level,
log_scope_levels: []const std.log.ScopeLevel = &.{},
logFn: fn (
comptime message_level: std.log.Level,
comptime scope: @TypeOf(.enum_literal),
comptime format: []const u8,
args: anytype,
) void = struct {
fn log(
comptime message_level: std.log.Level,
comptime scope: @Type(.enum_literal),
comptime format: []const u8,
args: anytype,
) void {
_ = message_level;
_ = scope;
_ = format;
_ = args;
}
}.log,
interrupts: InterruptOptions = .{},
overwrite_hal_interrupts: bool = false, //force overwrite the Hal default interrupts
cpu: CPU_Options = .{},
Expand All @@ -103,7 +79,41 @@ pub const Options = struct {
simple_panic_if_main_errors: bool = false,
};

pub const options: Options = if (@hasDecl(app, "microzig_options")) app.microzig_options else .{};
pub const options: Options = if (@hasDecl(root, "microzig_options")) root.microzig_options else .{};

pub const StdOptions = struct {
/// Control verbosity of `std.log` calls
log_level: std.log.Level = std.log.default_level,
/// Per-scope filtering for fine-grained logging
log_scope_levels: []const std.log.ScopeLevel = &.{},
/// The logging callback function, you'll need to provide to be able to log
/// to UART for example. The default is to do nothing, which is very
/// portable.
logFn: fn (
comptime message_level: std.log.Level,
comptime scope: @TypeOf(.enum_literal),
comptime format: []const u8,
args: anytype,
) void = no_op_log,
};

/// Helper for setting std_options relevant to embedded systems and freestanding
/// targets. Makes fewer assumptions about your system that the stdlib, and will
/// compile by default. You can set you own values using the overrides parameter.
pub fn std_options(comptime overrides: StdOptions) std.Options {
return .{
.log_level = overrides.log_level,
.log_scope_levels = overrides.log_scope_levels,
.logFn = overrides.logFn,
};
}

fn no_op_log(
comptime _: std.log.Level,
comptime _: @TypeOf(.enum_literal),
comptime _: []const u8,
_: anytype,
) void {}

/// Hangs the processor and will stop doing anything useful. Use with caution!
pub fn hang() noreturn {
Expand All @@ -114,6 +124,63 @@ pub fn hang() noreturn {
}
}

/// Call this in the root of your application to ensure that startup code is
/// linked correctly:
///
/// ```zig
/// comptime { _ = microzig.export_startup(); }
/// ```
///
/// Different systems require different startup procedures, and MicroZig will
/// select the right one for your system.
pub fn export_startup() void {
cpu.export_startup_logic();
@export(&microzig_main, .{ .name = "microzig_main" });
}

fn microzig_main() callconv(.c) noreturn {
// A HAL may define `init` (e.g. clocks, PLL) that runs before main. The
// user's root source file may define its own `init` to override the HAL
// default.
if (@hasDecl(root, "init"))
root.init()
else if (hal != void and @hasDecl(hal, "init"))
hal.init();

const main = @field(root, "main");
const return_type = @typeInfo(@TypeOf(main)).@"fn".return_type orelse
@compileError("microzig: `main` must have a return type");

if (@typeInfo(return_type) == .error_union) {
main() catch |err| {
const msg_base = "main() returned error.";

if (!options.simple_panic_if_main_errors) {
const max_error_size = comptime blk: {
var max: usize = 0;
const err_type = @typeInfo(return_type).error_union.error_set;
if (@typeInfo(err_type).error_set) |err_set| {
for (err_set) |current_err| {
max = @max(max, current_err.name.len);
}
}
break :blk max;
};

var buf: [msg_base.len + max_error_size]u8 = undefined;
const msg = std.fmt.bufPrint(&buf, "{s}{s}", .{ msg_base, @errorName(err) }) catch @panic(msg_base);
@panic(msg);
} else {
@panic(msg_base);
}
};
} else {
main();
}

hang();
}

test {
_ = utilities;
_ = Allocator;
Expand Down
Loading
Loading