From f46c2e4ea9a3594a8f2c699611f3251bb676a8b1 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sat, 8 Jan 2022 12:48:20 -0800 Subject: [PATCH] Microzig as pkg (#10) * works as a package * run zig fmt on all files --- src/core/clock.zig | 2 +- src/core/microzig.zig | 41 ---------- src/core/start.zig | 46 +++++++++++ src/main.zig | 95 +++++++++++++++-------- src/modules/chips/lpc1768/registers.zig | 1 - src/modules/chips/stm32f103/registers.zig | 1 - src/modules/chips/stm32f103/stm32f103.zig | 7 -- src/modules/cpus/avr/avr5.zig | 12 +-- 8 files changed, 114 insertions(+), 91 deletions(-) create mode 100644 src/core/start.zig diff --git a/src/core/clock.zig b/src/core/clock.zig index 11fbbd0..ee7b408 100644 --- a/src/core/clock.zig +++ b/src/core/clock.zig @@ -35,7 +35,7 @@ pub fn ensure() void { } /// Returns the current cpu frequency in hertz. -pub fn get() callconv(.Inline) u32 { +pub inline fn get() u32 { ensure(); return @field(clock_source_type, freq_decl_name); } diff --git a/src/core/microzig.zig b/src/core/microzig.zig index 4664fc5..893a8ab 100644 --- a/src/core/microzig.zig +++ b/src/core/microzig.zig @@ -66,47 +66,6 @@ pub fn hang() noreturn { } } -/// This is the logical entry point for microzig. -/// It will invoke the main function from the root source file -/// and provides error return handling as well as a event loop if requested. -/// -/// Why is this function exported? -/// This is due to the modular design of microzig to allow the "chip" dependency of microzig -/// to call into our main function here. If we would use a normal function call, we'd have a -/// circular dependency between the `microzig` and `chip` package. This function is also likely -/// to be invoked from assembly, so it's also convenient in that regard. -export fn microzig_main() noreturn { - if (!@hasDecl(root, "main")) - @compileError("The root source file must provide a public function main!"); - - const main = @field(root, "main"); - const info: std.builtin.TypeInfo = @typeInfo(@TypeOf(main)); - - const invalid_main_msg = "main must be either 'pub fn main() void' or 'pub fn main() !void'."; - if (info != .Fn or info.Fn.args.len > 0) - @compileError(invalid_main_msg); - - const return_type = info.Fn.return_type orelse @compileError(invalid_main_msg); - - if (info.Fn.calling_convention == .Async) - @compileError("TODO: Embedded event loop not supported yet. Please try again later."); - - if (@typeInfo(return_type) == .ErrorUnion) { - main() catch |err| { - // TODO: - // - Compute maximum size on the type of "err" - // - Do not emit error names when std.builtin.strip is set. - var msg: [64]u8 = undefined; - @panic(std.fmt.bufPrint(&msg, "main() returned error {s}", .{@errorName(err)}) catch @panic("main() returned error.")); - }; - } else { - main(); - } - - // main returned, just hang around here a bit - hang(); -} - comptime { _ = cpu.startup_logic; } diff --git a/src/core/start.zig b/src/core/start.zig new file mode 100644 index 0000000..b84c395 --- /dev/null +++ b/src/core/start.zig @@ -0,0 +1,46 @@ +const std = @import("std"); +const app = @import("app"); +const microzig = @import("microzig"); + +pub usingnamespace app; + +/// This is the logical entry point for microzig. +/// It will invoke the main function from the root source file +/// and provides error return handling as well as a event loop if requested. +/// +/// Why is this function exported? +/// This is due to the modular design of microzig to allow the "chip" dependency of microzig +/// to call into our main function here. If we would use a normal function call, we'd have a +/// circular dependency between the `microzig` and `chip` package. This function is also likely +/// to be invoked from assembly, so it's also convenient in that regard. +export fn microzig_main() noreturn { + if (!@hasDecl(app, "main")) + @compileError("The root source file must provide a public function main!"); + + const main = @field(app, "main"); + const info: std.builtin.TypeInfo = @typeInfo(@TypeOf(main)); + + const invalid_main_msg = "main must be either 'pub fn main() void' or 'pub fn main() !void'."; + if (info != .Fn or info.Fn.args.len > 0) + @compileError(invalid_main_msg); + + const return_type = info.Fn.return_type orelse @compileError(invalid_main_msg); + + if (info.Fn.calling_convention == .Async) + @compileError("TODO: Embedded event loop not supported yet. Please try again later."); + + if (@typeInfo(return_type) == .ErrorUnion) { + main() catch |err| { + // TODO: + // - Compute maximum size on the type of "err" + // - Do not emit error names when std.builtin.strip is set. + var msg: [64]u8 = undefined; + @panic(std.fmt.bufPrint(&msg, "main() returned error {s}", .{@errorName(err)}) catch @panic("main() returned error.")); + }; + } else { + main(); + } + + // main returned, just hang around here a bit + microzig.hang(); +} diff --git a/src/main.zig b/src/main.zig index 7a0ee96..0141522 100644 --- a/src/main.zig +++ b/src/main.zig @@ -12,6 +12,7 @@ pub const Backing = union(enum) { chip: Chip, }; +const Pkg = std.build.Pkg; const root_path = root() ++ "/"; fn root() []const u8 { return std.fs.path.dirname(@src().file) orelse unreachable; @@ -23,34 +24,12 @@ pub fn addEmbeddedExecutable( source: []const u8, backing: Backing, ) !*std.build.LibExeObjStep { - const Pkg = std.build.Pkg; - - const microzig_base = Pkg{ - .name = "microzig", - .path = .{ .path = root_path ++ "core/microzig.zig" }, - }; - + const has_board = (backing == .board); const chip = switch (backing) { .chip => |c| c, .board => |b| b.chip, }; - const has_board = (backing == .board); - - const chip_package = Pkg{ - .name = "chip", - .path = .{ .path = chip.path }, - .dependencies = &[_]Pkg{ - microzig_base, - pkgs.mmio, - Pkg{ - .name = "cpu", - .path = .{ .path = chip.cpu.path }, - .dependencies = &[_]Pkg{ microzig_base, pkgs.mmio }, - }, - }, - }; - const config_file_name = blk: { const hash = hash_blk: { var hasher = std.hash.SipHash128(1, 2).init("abcdefhijklmnopq"); @@ -97,47 +76,95 @@ pub fn addEmbeddedExecutable( try writer.print("pub const cpu_name = .@\"{}\";\n", .{std.fmt.fmtSliceEscapeUpper(chip.cpu.name)}); } + const microzig_pkg = Pkg{ + .name = "microzig", + .path = .{ .path = root_path ++ "core/microzig.zig" }, + }; + + const chip_pkg = Pkg{ + .name = "chip", + .path = .{ .path = chip.path }, + .dependencies = &[_]Pkg{ + microzig_pkg, + pkgs.mmio, + Pkg{ + .name = "cpu", + .path = .{ .path = chip.cpu.path }, + .dependencies = &[_]Pkg{ microzig_pkg, pkgs.mmio }, + }, + }, + }; + const config_pkg = Pkg{ .name = "microzig-config", .path = .{ .path = config_file_name }, }; - const linkerscript = try LinkerScriptStep.create(builder, chip); - const exe = builder.addExecutable(name, source); + const exe = builder.addExecutable(name, root_path ++ "core/start.zig"); // might not be true for all machines (Pi Pico), but // for the HAL it's true (it doesn't know the concept of threading) exe.single_threaded = true; exe.setTarget(chip.cpu.target); + const linkerscript = try LinkerScriptStep.create(builder, chip); exe.setLinkerScriptPath(.{ .generated = &linkerscript.generated_file }); // TODO: // - Generate the linker scripts from the "chip" or "board" package instead of using hardcoded ones. // - This requires building another tool that runs on the host that compiles those files and emits the linker script. // - src/tools/linkerscript-gen.zig is the source file for this - exe.bundle_compiler_rt = false; - switch (backing) { .chip => { exe.addPackage(Pkg{ - .name = microzig_base.name, - .path = microzig_base.path, - .dependencies = &[_]Pkg{ config_pkg, chip_package }, + .name = "app", + .path = .{ .path = source }, + .dependencies = &[_]Pkg{ + Pkg{ + .name = microzig_pkg.name, + .path = microzig_pkg.path, + .dependencies = &[_]Pkg{ config_pkg, chip_pkg }, + }, + }, + }); + exe.addPackage(Pkg{ + .name = microzig_pkg.name, + .path = microzig_pkg.path, + .dependencies = &[_]Pkg{ config_pkg, chip_pkg }, }); }, .board => |board| { exe.addPackage(Pkg{ - .name = microzig_base.name, - .path = microzig_base.path, + .name = "app", + .path = .{ .path = source }, + .dependencies = &[_]Pkg{ + Pkg{ + .name = microzig_pkg.name, + .path = microzig_pkg.path, + .dependencies = &[_]Pkg{ + config_pkg, + chip_pkg, + Pkg{ + .name = "board", + .path = .{ .path = board.path }, + .dependencies = &[_]Pkg{ microzig_pkg, chip_pkg, pkgs.mmio }, + }, + }, + }, + }, + }); + + exe.addPackage(Pkg{ + .name = microzig_pkg.name, + .path = microzig_pkg.path, .dependencies = &[_]Pkg{ config_pkg, - chip_package, + chip_pkg, Pkg{ .name = "board", .path = .{ .path = board.path }, - .dependencies = &[_]Pkg{ microzig_base, chip_package, pkgs.mmio }, + .dependencies = &[_]Pkg{ microzig_pkg, chip_pkg, pkgs.mmio }, }, }, }); diff --git a/src/modules/chips/lpc1768/registers.zig b/src/modules/chips/lpc1768/registers.zig index e950a28..807b7a4 100644 --- a/src/modules/chips/lpc1768/registers.zig +++ b/src/modules/chips/lpc1768/registers.zig @@ -21724,4 +21724,3 @@ pub const GPIO = extern struct { PINCLR31: u1, // bit offset: 31 desc: Fast GPIO output value Clear bits. Bit 0 in CLRx controls pin Px[0], bit 31 in CLRx controls pin Px[31]. 0 = Controlled pin output is unchanged. 1 = Controlled pin output is set to LOW. }); }; - diff --git a/src/modules/chips/stm32f103/registers.zig b/src/modules/chips/stm32f103/registers.zig index 2fb9d71..8f26813 100644 --- a/src/modules/chips/stm32f103/registers.zig +++ b/src/modules/chips/stm32f103/registers.zig @@ -17770,4 +17770,3 @@ pub const USB = extern struct { padding1: u1 = 0, }); }; - diff --git a/src/modules/chips/stm32f103/stm32f103.zig b/src/modules/chips/stm32f103/stm32f103.zig index 7f6e072..6ede441 100644 --- a/src/modules/chips/stm32f103/stm32f103.zig +++ b/src/modules/chips/stm32f103/stm32f103.zig @@ -1,11 +1,4 @@ const std = @import("std"); -const micro = @import("microzig"); -const micro_linker = @import("microzig-linker"); pub const cpu = @import("cpu"); pub const registers = @import("registers.zig"); - -pub const memory_regions = [_]micro_linker.MemoryRegion{ - micro_linker.MemoryRegion{ .offset = 0x00000000, .length = 64 * 1024, .kind = .flash }, - micro_linker.MemoryRegion{ .offset = 0x10000000, .length = 20 * 1024, .kind = .ram }, -}; diff --git a/src/modules/cpus/avr/avr5.zig b/src/modules/cpus/avr/avr5.zig index baa0093..d53fd3a 100644 --- a/src/modules/cpus/avr/avr5.zig +++ b/src/modules/cpus/avr/avr5.zig @@ -1,26 +1,26 @@ const std = @import("std"); -pub fn sei() callconv(.Inline) void { +pub inline fn sei() void { asm volatile ("sei"); } -pub fn cli() callconv(.Inline) void { +pub inline fn cli() void { asm volatile ("cli"); } -pub fn sbi(comptime reg: u5, comptime bit: u3) callconv(.Inline) void { +pub inline fn sbi(comptime reg: u5, comptime bit: u3) void { asm volatile ("sbi %[reg], %[bit]" : : [reg] "I" (reg), - [bit] "I" (bit) + [bit] "I" (bit), ); } -pub fn cbi(comptime reg: u5, comptime bit: u3) callconv(.Inline) void { +pub inline fn cbi(comptime reg: u5, comptime bit: u3) void { asm volatile ("cbi %[reg], %[bit]" : : [reg] "I" (reg), - [bit] "I" (bit) + [bit] "I" (bit), ); }