You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
microzig/build.zig

218 lines
6.7 KiB
Zig

const std = @import("std");
const Build = std.Build;
const comptimePrint = std.fmt.comptimePrint;
const microzig = @import("microzig");
pub const chips = @import("src/chips.zig");
pub const boards = @import("src/boards.zig");
const build_root = root();
const linkerscript_path = build_root ++ "/rp2040.ld";
pub const BootROM = union(enum) {
artifact: *std.build.CompileStep, // provide a custom startup code
blob: std.build.LazyPath, // just include a binary blob
// Pre-shipped ones:
at25sf128a,
generic_03h,
is25lp080,
w25q080,
w25x10cl,
// Use the old stage2 bootloader vendored with MicroZig till 2023-09-13
legacy,
};
pub const PicoExecutableOptions = struct {
name: []const u8,
source_file: std.Build.LazyPath,
optimize: std.builtin.OptimizeMode = .Debug,
board: boards.Board = boards.raspberry_pi_pico,
bootrom: ?BootROM = null,
};
pub const addPiPicoExecutable = addExecutable; // Deprecated, use addExecutable!
pub const Stage2Bootloader = struct {
bin: std.Build.LazyPath,
elf: ?std.Build.LazyPath,
};
pub fn getBootrom(b: *Build, rom: BootROM) Stage2Bootloader {
const rom_exe = switch (rom) {
.artifact => |artifact| artifact,
.blob => |blob| return Stage2Bootloader{
.bin = blob,
.elf = null,
},
else => blk: {
var target = chips.rp2040.cpu.target;
target.abi = .eabi;
const rom_path = b.pathFromRoot(b.fmt("{s}/src/bootroms/{s}.S", .{ build_root, @tagName(rom) }));
const rom_exe = b.addExecutable(.{
.name = b.fmt("stage2-{s}", .{@tagName(rom)}),
.optimize = .ReleaseSmall,
.target = target,
.root_source_file = null,
});
rom_exe.linkage = .static;
// rom_exe.pie = false;
// rom_exe.force_pic = false;
rom_exe.setLinkerScript(.{ .path = build_root ++ "/src/bootroms/shared/stage2.ld" });
rom_exe.addAssemblyFile(.{ .path = rom_path });
break :blk rom_exe;
},
};
const rom_objcopy = b.addObjCopy(rom_exe.getEmittedBin(), .{
.basename = b.fmt("{s}.bin", .{@tagName(rom)}),
.format = .bin,
});
return Stage2Bootloader{
.bin = rom_objcopy.getOutput(),
.elf = rom_exe.getEmittedBin(),
};
}
pub fn addExecutable(
b: *Build,
opts: PicoExecutableOptions,
) *microzig.EmbeddedExecutable {
var exe = microzig.addEmbeddedExecutable(b, .{
.name = opts.name,
.source_file = opts.source_file,
.backing = .{ .board = opts.board.inner },
.optimize = opts.optimize,
.linkerscript_source_file = .{ .path = linkerscript_path },
});
const i: *std.Build.CompileStep = exe.inner;
const bootrom_file = getBootrom(b, opts.bootrom orelse opts.board.bootrom);
// HACK: Inject the file as a dependency to MicroZig.board
i.modules.get("microzig").?.dependencies.get("board").?.dependencies.put(
"bootloader",
b.createModule(.{
.source_file = bootrom_file.bin,
}),
) catch @panic("oom");
bootrom_file.bin.addStepDependencies(&i.step);
return exe;
}
// this build script is mostly for testing and verification of this
// package. In an attempt to modularize -- designing for a case where a
// project requires multiple HALs, it accepts microzig as a param
pub fn build(b: *Build) !void {
const optimize = b.standardOptimizeOption(.{});
const args_dep = b.dependency("args", .{});
const args_mod = args_dep.module("args");
var examples = Examples.init(b, optimize);
examples.install(b);
const pio_tests = b.addTest(.{
.root_source_file = .{
.path = "src/hal.zig",
},
.optimize = optimize,
});
pio_tests.addIncludePath(.{ .path = "src/hal/pio/assembler" });
const test_step = b.step("test", "run unit tests");
test_step.dependOn(&b.addRunArtifact(pio_tests).step);
{
const flash_tool = b.addExecutable(.{
.name = "rp2040-flash",
.optimize = .Debug,
.target = .{},
.root_source_file = .{ .path = "tools/rp2040-flash.zig" },
});
flash_tool.addModule("args", args_mod);
b.installArtifact(flash_tool);
}
// Install all bootroms for debugging and CI
inline for (comptime std.enums.values(std.meta.Tag(BootROM))) |rom| {
if (rom == .artifact or rom == .blob) {
continue;
}
if (rom == .is25lp080) {
// TODO: https://github.com/ZigEmbeddedGroup/raspberrypi-rp2040/issues/79
// is25lp080.o:(text+0x16): has non-ABS relocation R_ARM_THM_CALL against symbol 'read_flash_sreg'
continue;
}
const files = getBootrom(b, rom);
if (files.elf) |elf| {
b.getInstallStep().dependOn(
&b.addInstallFileWithDir(elf, .{ .custom = "stage2" }, b.fmt("{s}.elf", .{@tagName(rom)})).step,
);
}
b.getInstallStep().dependOn(
&b.addInstallFileWithDir(files.bin, .{ .custom = "stage2" }, b.fmt("{s}.bin", .{@tagName(rom)})).step,
);
}
}
fn root() []const u8 {
return comptime (std.fs.path.dirname(@src().file) orelse ".") ++ "/";
}
pub const Examples = struct {
adc: *microzig.EmbeddedExecutable,
blinky: *microzig.EmbeddedExecutable,
blinky_core1: *microzig.EmbeddedExecutable,
gpio_clk: *microzig.EmbeddedExecutable,
i2c_bus_scan: *microzig.EmbeddedExecutable,
pwm: *microzig.EmbeddedExecutable,
spi_master: *microzig.EmbeddedExecutable,
uart: *microzig.EmbeddedExecutable,
squarewave: *microzig.EmbeddedExecutable,
//uart_pins: microzig.EmbeddedExecutable,
flash_program: *microzig.EmbeddedExecutable,
usb_device: *microzig.EmbeddedExecutable,
usb_hid: *microzig.EmbeddedExecutable,
ws2812: *microzig.EmbeddedExecutable,
random: *microzig.EmbeddedExecutable,
pub fn init(b: *Build, optimize: std.builtin.OptimizeMode) Examples {
var ret: Examples = undefined;
inline for (@typeInfo(Examples).Struct.fields) |field| {
const path = comptime root() ++ "examples/" ++ field.name ++ ".zig";
@field(ret, field.name) = addExecutable(b, .{
.name = field.name,
.source_file = .{ .path = path },
.optimize = optimize,
});
}
return ret;
}
pub fn install(examples: *Examples, b: *Build) void {
inline for (@typeInfo(Examples).Struct.fields) |field| {
b.getInstallStep().dependOn(
&b.addInstallFileWithDir(@field(examples, field.name).inner.getEmittedBin(), .{ .custom = "firmware" }, field.name ++ ".elf").step,
);
}
}
};