From a34327746302b3c89bbe59b3c3d265e3b0c4e75a Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Sun, 3 Mar 2024 13:39:51 -0800 Subject: [PATCH] fix up packaging --- README.md | 79 +------ bsp/espressif/esp/build.zig.zon | 2 +- bsp/gigadevice/gd32/build.zig.zon | 2 +- bsp/microchip/atsam/build.zig.zon | 2 +- bsp/microchip/avr/build.zig.zon | 2 +- bsp/nordic/nrf5x/build.zig.zon | 2 +- bsp/nxp/lpc/build.zig.zon | 2 +- bsp/raspberrypi/rp2040/build.zig.zon | 2 +- bsp/stmicro/stm32/build.zig.zon | 2 +- build.zig | 16 +- build.zig.zon | 45 ++-- build/build.zig | 266 +++++++++------------- build/build.zig.zon | 9 +- build/definitions/LICENSE | 21 ++ build/definitions/build.zig | 112 +++++++++ build/definitions/build.zig.zon | 9 + build/src/generate_linkerscript.zig | 41 +--- core/build.zig | 2 +- core/build.zig.zon | 4 +- examples/espressif/esp/build.zig.zon | 2 +- examples/gigadevice/gd32/build.zig.zon | 2 +- examples/microchip/atsam/build.zig.zon | 2 +- examples/microchip/avr/build.zig.zon | 2 +- examples/nordic/nrf5x/build.zig.zon | 2 +- examples/nxp/lpc/build.zig.zon | 2 +- examples/raspberrypi/rp2040/build.zig.zon | 2 +- examples/stmicro/stm32/build.zig.zon | 2 +- tools/regz/build.zig.zon | 2 +- tools/uf2/build.zig.zon | 2 +- 29 files changed, 308 insertions(+), 332 deletions(-) create mode 100644 build/definitions/LICENSE create mode 100644 build/definitions/build.zig create mode 100644 build/definitions/build.zig.zon diff --git a/README.md b/README.md index 1f55fa0..a0ebeaf 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## What version of Zig to use -0.11.0 +Zig master/nightly ## Getting Started With MicroZig @@ -26,8 +26,6 @@ Right now, you gotta figure out how to flash the MCU yourself, but as people say ### I Want To Contribute To MicroZig -**IMPORTANT:** Developer experience is degraded right now, and not really good. Windows isn't really a supported dev target and you got to expect some friction. [There's a project for improving DX, feel free to grab tasks from there!](https://github.com/orgs/ZigEmbeddedGroup/projects/4) - Please see the [project page](https://github.com/orgs/ZigEmbeddedGroup/projects/1/views/1), it’s used as a place to brainstorm and organize work in ZEG. There will be issues marked as good first issue or drafts for larger ideas that need scoping/breaking ground on. More words on contribution and development on MicroZig are [further down below](#developing). @@ -47,84 +45,11 @@ This repo contains the infrastructure for getting started in an embedded Zig pro For MicroZig internals please see the [Design Document](docs/design.adoc). -## Developing - -Right now, the developer experience is not optimal due to 0.11 not really supporting what we're doing at all. - -If you want to test your changes, you gotta to the following: - -**Step 1:** Install required python packages, either systemwide or via a [virtual environment](https://docs.python.org/3/library/venv.html): - -```sh-session -# systemwide: -[user@host] microzig-monorepo/ $ pip install -r tools/requirements.txt -[user@host] microzig-monorepo/ $ - -# using virtual environments: -[user@host] microzig-monorepo/ $ python3 -m venv .venv -[user@host] microzig-monorepo/ $ . .venv/bin/activate # on linux, macos -[user@host] microzig-monorepo/ $ . .venv/Scripts/activate # on windows -[user@host] microzig-monorepo/ $ pip3 install -r tools/requirements.txt -[user@host] microzig-monorepo/ $ -``` - -**Step 2:** Create a deployment for local usage: - -```sh-session -[user@host] microzig-monorepo/ $ python3 ./tools/bundle.py --debug -preparing environment... -validating packages... -loaded packages: - * microzig-build - * examples:microchip/avr - * examples:... - * microzig-core - * microchip/avr - * ... -resolving inner dependencies... -creating packages... -bundling microzig-build... -bundling microzig-core... -bundling microchip/avr... -... -[user@host] microzig-monorepo/ $ -``` - -This command yields output in `./microzig-deploy` that is meant to be fetched via `http://localhost:8080/`. - -**Step 3:** To serve the files on this port, you can start a pre-bundled web server: - -```sh-session -[user@host] microzig-monorepo/ $ python3 ./tools/demo-server.py -... -``` - -This way, you spawn a local HTTP server that will serve `./microzig-deploy` on port 8080 on your machine, and you can then -start fetching packages from this. - -Now you can use curl to fetch the packages, or you can just create a local development project. - -**Step 4:** Create a local test environment - -This is basically done by unpacking an example from the `./microzig-deploy/examples` folder, and starting to test changes. -As the `build.zig.zon` has to be updated after running `./tools/bundle.py` again, there's a script that helps here: -`tools/patch-build-zon.py` can be used to patch/upgrade your development project inplace based on what it finds in `./microzig-deploy`: - -```sh-session -[user@host] microzig-monorepo/ $ python3 ./tools/patch-build-zon.py /tmp/dev-project/build.zig.zon -Updating hash of http://localhost:8080/packages/microzig-build.tar.gz to 12200040a36bbbb2fe09809861f565fcda9a10ec3064d70357aa40ad0a61596c16fb -Updating hash of http://localhost:8080/packages/microzig-core.tar.gz to 122013a37ce9ac295303f26057c203e722b9ceaefa5b4403fe5a18ab065f03079e7d -Updating hash of http://localhost:8080/packages/board-support/stmicro/stm32.tar.gz to 12207c278b78c5aeb08cd7889647d7d0d9a359cb28fe68105d2e43f85dabb3865981 -[user@host] microzig-monorepo/ $ -``` - -Both compiling the local example and updating the `build.zig.zon` requires running the local development server. - ## Repository structure * `build/` contains the build components of MicroZig. * `core/` contains the shared components of MicroZig. -* `board-support/` contains all official board support package. +* `bsp/` contains all official board support package. * `examples/` contains examples that can be used with the board support packages. * `tools/` contains tooling to work *on* MicroZig itself, so deployment, testing, ... * `design/` contains images and logos diff --git a/bsp/espressif/esp/build.zig.zon b/bsp/espressif/esp/build.zig.zon index 38be14f..0616e86 100644 --- a/bsp/espressif/esp/build.zig.zon +++ b/bsp/espressif/esp/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/espressif/esp", + .name = "bsp/espressif/esp", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/bsp/gigadevice/gd32/build.zig.zon b/bsp/gigadevice/gd32/build.zig.zon index 2736dab..78c8b94 100644 --- a/bsp/gigadevice/gd32/build.zig.zon +++ b/bsp/gigadevice/gd32/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/gigadevice/gd32", + .name = "bsp/gigadevice/gd32", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/bsp/microchip/atsam/build.zig.zon b/bsp/microchip/atsam/build.zig.zon index 2f0e8d4..ff82b9b 100644 --- a/bsp/microchip/atsam/build.zig.zon +++ b/bsp/microchip/atsam/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/microchip/atsam", + .name = "bsp/microchip/atsam", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/bsp/microchip/avr/build.zig.zon b/bsp/microchip/avr/build.zig.zon index 6c64e77..e8ed026 100644 --- a/bsp/microchip/avr/build.zig.zon +++ b/bsp/microchip/avr/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/microchip/avr", + .name = "bsp/microchip/avr", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/bsp/nordic/nrf5x/build.zig.zon b/bsp/nordic/nrf5x/build.zig.zon index 815d0b9..8cbd9ef 100644 --- a/bsp/nordic/nrf5x/build.zig.zon +++ b/bsp/nordic/nrf5x/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/nordic/nrf5x", + .name = "bsp/nordic/nrf5x", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/bsp/nxp/lpc/build.zig.zon b/bsp/nxp/lpc/build.zig.zon index ef685ea..e32c046 100644 --- a/bsp/nxp/lpc/build.zig.zon +++ b/bsp/nxp/lpc/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/nxp/lpc", + .name = "bsp/nxp/lpc", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/bsp/raspberrypi/rp2040/build.zig.zon b/bsp/raspberrypi/rp2040/build.zig.zon index 7c09047..d69d440 100644 --- a/bsp/raspberrypi/rp2040/build.zig.zon +++ b/bsp/raspberrypi/rp2040/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/raspberrypi/rp2040", + .name = "bsp/raspberrypi/rp2040", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ diff --git a/bsp/stmicro/stm32/build.zig.zon b/bsp/stmicro/stm32/build.zig.zon index e0ada83..480a7eb 100644 --- a/bsp/stmicro/stm32/build.zig.zon +++ b/bsp/stmicro/stm32/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/bsp/stmicro/stm32", + .name = "bsp/stmicro/stm32", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/build.zig b/build.zig index aaceafd..0ce4319 100644 --- a/build.zig +++ b/build.zig @@ -16,14 +16,14 @@ const std = @import("std"); // assert(@alignOf(i16) == 2); // ~~~~~~^~~~~~~~~~~~~~~~~~~~ const example_dep_names: []const []const u8 = &.{ - "microzig/examples/nordic/nrf5x", - "microzig/examples/nxp/lpc", - "microzig/examples/microchip/atsam", - //"microzig/examples/microchip/avr", - "microzig/examples/gigadevice/gd32", - "microzig/examples/stmicro/stm32", - "microzig/examples/espressif/esp", - "microzig/examples/raspberrypi/rp2040", + "examples/nordic/nrf5x", + "examples/nxp/lpc", + "examples/microchip/atsam", + //"examples/microchip/avr", + "examples/gigadevice/gd32", + "examples/stmicro/stm32", + "examples/espressif/esp", + "examples/raspberrypi/rp2040", }; pub fn build(b: *std.Build) void { diff --git a/build.zig.zon b/build.zig.zon index 9261582..538badd 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -3,33 +3,34 @@ .version = "0.0.0", .dependencies = .{ // packages within the monorepo so that others can reach them - .@"microzig/build" = .{ .path = "build" }, - .@"microzig/core" = .{ .path = "core" }, - .@"microzig/tools/regz" = .{ .path = "tools/regz" }, - .@"microzig/tools/uf2" = .{ .path = "tools/uf2" }, - .@"microzig/bsp/nordic/nrf5x" = .{ .path = "bsp/nordic/nrf5x" }, - .@"microzig/bsp/nxp/lpc" = .{ .path = "bsp/nxp/lpc" }, - .@"microzig/bsp/microchip/atsam" = .{ .path = "bsp/microchip/atsam" }, - .@"microzig/bsp/microchip/avr" = .{ .path = "bsp/microchip/avr" }, - .@"microzig/bsp/gigadevice/gd32" = .{ .path = "bsp/gigadevice/gd32" }, - .@"microzig/bsp/stmicro/stm32" = .{ .path = "bsp/stmicro/stm32" }, - .@"microzig/bsp/espressif/esp" = .{ .path = "bsp/espressif/esp" }, - .@"microzig/bsp/raspberrypi/rp2040" = .{ .path = "bsp/raspberrypi/rp2040" }, + .@"build" = .{ .path = "build" }, + .@"build/definitions" = .{ .path = "build/definitions" }, + .@"core" = .{ .path = "core" }, + .@"tools/regz" = .{ .path = "tools/regz" }, + .@"tools/uf2" = .{ .path = "tools/uf2" }, + .@"bsp/nordic/nrf5x" = .{ .path = "bsp/nordic/nrf5x" }, + .@"bsp/nxp/lpc" = .{ .path = "bsp/nxp/lpc" }, + .@"bsp/microchip/atsam" = .{ .path = "bsp/microchip/atsam" }, + .@"bsp/microchip/avr" = .{ .path = "bsp/microchip/avr" }, + .@"bsp/gigadevice/gd32" = .{ .path = "bsp/gigadevice/gd32" }, + .@"bsp/stmicro/stm32" = .{ .path = "bsp/stmicro/stm32" }, + .@"bsp/espressif/esp" = .{ .path = "bsp/espressif/esp" }, + .@"bsp/raspberrypi/rp2040" = .{ .path = "bsp/raspberrypi/rp2040" }, // examples so that we can build them all in one go - .@"microzig/examples/nordic/nrf5x" = .{ .path = "examples/nordic/nrf5x" }, - .@"microzig/examples/nxp/lpc" = .{ .path = "examples/nxp/lpc" }, - .@"microzig/examples/microchip/atsam" = .{ .path = "examples/microchip/atsam" }, - .@"microzig/examples/microchip/avr" = .{ .path = "examples/microchip/avr" }, - .@"microzig/examples/gigadevice/gd32" = .{ .path = "examples/gigadevice/gd32" }, - .@"microzig/examples/stmicro/stm32" = .{ .path = "examples/stmicro/stm32" }, - .@"microzig/examples/espressif/esp" = .{ .path = "examples/espressif/esp" }, - .@"microzig/examples/raspberrypi/rp2040" = .{ .path = "examples/raspberrypi/rp2040" }, + .@"examples/nordic/nrf5x" = .{ .path = "examples/nordic/nrf5x" }, + .@"examples/nxp/lpc" = .{ .path = "examples/nxp/lpc" }, + .@"examples/microchip/atsam" = .{ .path = "examples/microchip/atsam" }, + .@"examples/microchip/avr" = .{ .path = "examples/microchip/avr" }, + .@"examples/gigadevice/gd32" = .{ .path = "examples/gigadevice/gd32" }, + .@"examples/stmicro/stm32" = .{ .path = "examples/stmicro/stm32" }, + .@"examples/espressif/esp" = .{ .path = "examples/espressif/esp" }, + .@"examples/raspberrypi/rp2040" = .{ .path = "examples/raspberrypi/rp2040" }, // used for creating package tarballs .boxzer = .{ - .url = "https://github.com/mattnite/boxzer/archive/44183569cb4418f3b127711a989ded8822869a91.tar.gz", - .hash = "1220f6fc705e2d658644c96c093ed7907f2c3091252058d6bdfdc0334965dd25d6c4", + .url = "https://github.com/mattnite/boxzer/archive/b9f08b4c9b1db709af03763ace69761a6482238c.tar.gz", + .hash = "12204fdd9914a6d99abb55366b3a664395a6038d7e6308178c0664158eff9418e188", }, }, diff --git a/build/build.zig b/build/build.zig index 4d42046..4951e1a 100644 --- a/build/build.zig +++ b/build/build.zig @@ -8,14 +8,19 @@ const std = @import("std"); const Build = std.Build; const LazyPath = Build.LazyPath; +const uf2 = @import("microzig/tools/uf2"); const core = @import("microzig/core"); +const defs = @import("microzig/build/definitions"); +pub const Chip = defs.Chip; +pub const Cpu = defs.Cpu; +pub const HardwareAbstractionLayer = defs.HardwareAbstractionLayer; +pub const BoardDefinition = defs.BoardDefinition; const MicroZig = @This(); -const uf2 = @import("uf2"); /// This build script validates usage patterns we expect from MicroZig pub fn build(b: *Build) !void { - const uf2_dep = b.dependency("uf2", .{}); + const uf2_dep = b.dependency("microzig/tools/uf2", .{}); const build_test = b.addTest(.{ .root_source_file = .{ .path = "build.zig" }, @@ -53,6 +58,9 @@ pub fn init(b: *Build, opts: struct { }), }; + const defs_dep = mz_dep.builder.dependency("microzig/build/definitions", .{}); + ret.generate_linkerscript.root_module.addImport("microzig/build/definitions", defs_dep.module("definitions")); + return ret; } @@ -84,7 +92,7 @@ pub fn add_firmware( // 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_exe = mz.dependency("microzig/tools/regz", .{ .optimize = .ReleaseSafe }).artifact("regz"); const regz_gen = host_build.addRunArtifact(regz_exe); @@ -280,166 +288,8 @@ fn dependency(env: *MicroZig, name: []const u8, args: anytype) *Build.Dependency return env.self.builder.dependency(name, args); } -/// The resulting binary format for the firmware file. -/// A lot of embedded systems don't use plain ELF files, thus we provide means -/// to convert the resulting ELF into other common formats. -pub const BinaryFormat = union(enum) { - /// [Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format), the standard output from the compiler. - elf, - - /// A flat binary, contains only the loaded portions of the firmware with an unspecified base offset. - bin, - - /// The [Intel HEX](https://en.wikipedia.org/wiki/Intel_HEX) format, contains - /// an ASCII description of what memory to load where. - hex, - - /// A [Device Firmware Upgrade](https://www.usb.org/sites/default/files/DFU_1.1.pdf) file. - dfu, - - /// The [USB Flashing Format (UF2)](https://github.com/microsoft/uf2) designed by Microsoft. - uf2: uf2.FamilyId, - - /// The [firmware format](https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/firmware-image-format.html) used by the [esptool](https://github.com/espressif/esptool) bootloader. - esp, - - /// Custom option for non-standard formats. - custom: *Custom, - - /// Returns the standard extension for the resulting binary file. - pub fn get_extension(format: BinaryFormat) []const u8 { - return switch (format) { - .elf => ".elf", - .bin => ".bin", - .hex => ".hex", - .dfu => ".dfu", - .uf2 => ".uf2", - .esp => ".bin", - - .custom => |c| c.extension, - }; - } - - pub const Custom = struct { - /// The standard extension of the format. - extension: []const u8, - - /// A function that will convert a given `elf` file into the custom output format. - /// - /// The `*Custom` format is passed so contextual information can be obtained by using - /// `@fieldParentPtr` to provide access to tooling. - convert: *const fn (*Custom, elf: Build.LazyPath) Build.LazyPath, - }; - - const Enum = std.meta.Tag(BinaryFormat); - - const Context = struct { - pub fn hash(self: @This(), fmt: BinaryFormat) u32 { - _ = self; - - var hasher = std.hash.XxHash32.init(0x1337_42_21); - - hasher.update(@tagName(fmt)); - - switch (fmt) { - .elf, .bin, .hex, .dfu, .esp => |val| { - if (@TypeOf(val) != void) @compileError("Missing update: Context.hash now requires special care!"); - }, - - .uf2 => |family_id| hasher.update(@tagName(family_id)), - .custom => |custom| hasher.update(std.mem.asBytes(custom)), - } - - return hasher.final(); - } - - pub fn eql(self: @This(), fmt_a: BinaryFormat, fmt_b: BinaryFormat, index: usize) bool { - _ = self; - _ = index; - if (@as(BinaryFormat.Enum, fmt_a) != @as(BinaryFormat.Enum, fmt_b)) - return false; - - return switch (fmt_a) { - .elf, .bin, .hex, .dfu, .esp => |val| { - if (@TypeOf(val) != void) @compileError("Missing update: Context.eql now requires special care!"); - return true; - }, - - .uf2 => |a| (a == fmt_b.uf2), - .custom => |a| (a == fmt_b.custom), - }; - } - }; -}; - pub const cpus = core.cpus; -/// A cpu descriptor. -pub const Cpu = struct { - /// Display name of the CPU. - name: []const u8, - - /// Source file providing startup code and memory initialization routines. - source_file: LazyPath, - - /// The compiler target we use to compile all the code. - target: std.Target.Query, -}; - -pub const MemoryRegion = @import("src/generate_linkerscript.zig").MemoryRegion; - -/// Defines a custom microcontroller. -pub const Chip = struct { - /// The display name of the controller. - name: []const u8, - - /// (optional) link to the documentation/vendor page of the controller. - url: ?[]const u8 = null, - - /// The cpu model this controller uses. - cpu: Cpu, - - /// The provider for register definitions. - register_definition: union(enum) { - /// Use `regz` to create a zig file from a JSON schema. - json: LazyPath, - - /// Use `regz` to create a json file from a SVD schema. - svd: LazyPath, - - /// Use `regz` to create a zig file from an ATDF schema. - atdf: LazyPath, - - /// Use the provided file directly as the chip file. - zig: LazyPath, - }, - - /// The memory regions that are present in this chip. - memory_regions: []const MemoryRegion, -}; - -/// Defines a hardware abstraction layer. -pub const HardwareAbstractionLayer = struct { - /// Root source file for this HAL. - source_file: LazyPath, -}; - -/// Provides a description of a board. -/// -/// Boards provide additional information to a chip and HAL package. -/// For example, they can list attached peripherials, external crystal frequencies, -/// flash sizes, ... -pub const BoardDefinition = struct { - /// Display name of the board - name: []const u8, - - /// (optional) link to the documentation/vendor page of the board. - url: ?[]const u8 = null, - - /// Provides the root file for the board definition. - source_file: LazyPath, -}; - /// A compilation target for MicroZig. Provides information about the chip, /// hal, board and so on. /// @@ -608,7 +458,7 @@ pub const Firmware = struct { }, .uf2 => |family_id| blk: { - const uf2_exe = firmware.mz.dependency("uf2", .{ .optimize = .ReleaseSafe }).artifact("elf2uf2"); + const uf2_exe = firmware.mz.dependency("microzig/tools/uf2", .{ .optimize = .ReleaseSafe }).artifact("elf2uf2"); const convert = firmware.host_build.addRunArtifact(uf2_exe); @@ -684,3 +534,95 @@ fn build_config_error(b: *std.Build, comptime fmt: []const u8, args: anytype) no const msg = b.fmt(fmt, args); @panic(msg); } + +/// The resulting binary format for the firmware file. +/// A lot of embedded systems don't use plain ELF files, thus we provide means +/// to convert the resulting ELF into other common formats. +pub const BinaryFormat = union(enum) { + /// [Executable and Linkable Format](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format), the standard output from the compiler. + elf, + + /// A flat binary, contains only the loaded portions of the firmware with an unspecified base offset. + bin, + + /// The [Intel HEX](https://en.wikipedia.org/wiki/Intel_HEX) format, contains + /// an ASCII description of what memory to load where. + hex, + + /// A [Device Firmware Upgrade](https://www.usb.org/sites/default/files/DFU_1.1.pdf) file. + dfu, + + /// The [USB Flashing Format (UF2)](https://github.com/microsoft/uf2) designed by Microsoft. + uf2: uf2.FamilyId, + + /// The [firmware format](https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/firmware-image-format.html) used by the [esptool](https://github.com/espressif/esptool) bootloader. + esp, + + /// Custom option for non-standard formats. + custom: *Custom, + + /// Returns the standard extension for the resulting binary file. + pub fn get_extension(format: BinaryFormat) []const u8 { + return switch (format) { + .elf => ".elf", + .bin => ".bin", + .hex => ".hex", + .dfu => ".dfu", + .uf2 => ".uf2", + .esp => ".bin", + + .custom => |c| c.extension, + }; + } + + pub const Custom = struct { + /// The standard extension of the format. + extension: []const u8, + + /// A function that will convert a given `elf` file into the custom output format. + /// + /// The `*Custom` format is passed so contextual information can be obtained by using + /// `@fieldParentPtr` to provide access to tooling. + convert: *const fn (*Custom, elf: Build.LazyPath) Build.LazyPath, + }; + + const Enum = std.meta.Tag(BinaryFormat); + + pub const Context = struct { + pub fn hash(self: @This(), fmt: BinaryFormat) u32 { + _ = self; + + var hasher = std.hash.XxHash32.init(0x1337_42_21); + + hasher.update(@tagName(fmt)); + + switch (fmt) { + .elf, .bin, .hex, .dfu, .esp => |val| { + if (@TypeOf(val) != void) @compileError("Missing update: Context.hash now requires special care!"); + }, + + .uf2 => |family_id| hasher.update(@tagName(family_id)), + .custom => |custom| hasher.update(std.mem.asBytes(custom)), + } + + return hasher.final(); + } + + pub fn eql(self: @This(), fmt_a: BinaryFormat, fmt_b: BinaryFormat, index: usize) bool { + _ = self; + _ = index; + if (@as(BinaryFormat.Enum, fmt_a) != @as(BinaryFormat.Enum, fmt_b)) + return false; + + return switch (fmt_a) { + .elf, .bin, .hex, .dfu, .esp => |val| { + if (@TypeOf(val) != void) @compileError("Missing update: Context.eql now requires special care!"); + return true; + }, + + .uf2 => |a| (a == fmt_b.uf2), + .custom => |a| (a == fmt_b.custom), + }; + } + }; +}; diff --git a/build/build.zig.zon b/build/build.zig.zon index 7fee10e..3330643 100644 --- a/build/build.zig.zon +++ b/build/build.zig.zon @@ -1,16 +1,19 @@ .{ - .name = "microzig/build", + .name = "build", .version = "0.0.0", .dependencies = .{ - .uf2 = .{ + .@"microzig/tools/uf2" = .{ .path = "../tools/uf2", }, - .regz = .{ + .@"microzig/tools/regz" = .{ .path = "../tools/regz", }, .@"microzig/core" = .{ .path = "../core", }, + .@"microzig/build/definitions" = .{ + .path = "definitions", + }, }, .paths = .{ diff --git a/build/definitions/LICENSE b/build/definitions/LICENSE new file mode 100644 index 0000000..4818f98 --- /dev/null +++ b/build/definitions/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Zig Embedded Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/build/definitions/build.zig b/build/definitions/build.zig new file mode 100644 index 0000000..5b14136 --- /dev/null +++ b/build/definitions/build.zig @@ -0,0 +1,112 @@ +const std = @import("std"); +const Build = std.Build; +const LazyPath = Build.LazyPath; + +pub fn build(b: *Build) void { + _ = b.addModule("definitions", .{ + .root_source_file = .{ .path = "build.zig" }, + }); +} + +/// A cpu descriptor. +pub const Cpu = struct { + /// Display name of the CPU. + name: []const u8, + + /// Source file providing startup code and memory initialization routines. + source_file: LazyPath, + + /// The compiler target we use to compile all the code. + target: std.Target.Query, +}; + +/// Defines a custom microcontroller. +pub const Chip = struct { + /// The display name of the controller. + name: []const u8, + + /// (optional) link to the documentation/vendor page of the controller. + url: ?[]const u8 = null, + + /// The cpu model this controller uses. + cpu: Cpu, + + /// The provider for register definitions. + register_definition: union(enum) { + /// Use `regz` to create a zig file from a JSON schema. + json: LazyPath, + + /// Use `regz` to create a json file from a SVD schema. + svd: LazyPath, + + /// Use `regz` to create a zig file from an ATDF schema. + atdf: LazyPath, + + /// Use the provided file directly as the chip file. + zig: LazyPath, + }, + + /// The memory regions that are present in this chip. + memory_regions: []const MemoryRegion, +}; + +/// Defines a hardware abstraction layer. +pub const HardwareAbstractionLayer = struct { + /// Root source file for this HAL. + source_file: LazyPath, +}; + +/// Provides a description of a board. +/// +/// Boards provide additional information to a chip and HAL package. +/// For example, they can list attached peripherials, external crystal frequencies, +/// flash sizes, ... +pub const BoardDefinition = struct { + /// Display name of the board + name: []const u8, + + /// (optional) link to the documentation/vendor page of the board. + url: ?[]const u8 = null, + + /// Provides the root file for the board definition. + source_file: LazyPath, +}; + +/// A descriptor for memory regions in a microcontroller. +pub const MemoryRegion = struct { + /// The type of the memory region for generating a proper linker script. + kind: Kind, + offset: u64, + length: u64, + + pub const Kind = union(enum) { + /// This is a (normally) immutable memory region where the code is stored. + flash, + + /// This is a mutable memory region for data storage. + ram, + + /// This is a memory region that maps MMIO devices. + io, + + /// This is a memory region that exists, but is reserved and must not be used. + reserved, + + /// This is a memory region used for internal linking tasks required by the board support package. + private: PrivateRegion, + }; + + pub const PrivateRegion = struct { + /// The name of the memory region. Will not have an automatic numeric counter and must be unique. + name: []const u8, + + /// Is the memory region executable? + executable: bool, + + /// Is the memory region readable? + readable: bool, + + /// Is the memory region writable? + writeable: bool, + }; +}; diff --git a/build/definitions/build.zig.zon b/build/definitions/build.zig.zon new file mode 100644 index 0000000..aa88dfd --- /dev/null +++ b/build/definitions/build.zig.zon @@ -0,0 +1,9 @@ +.{ + .name = "build/definitions", + .version = "0.0.0", + .paths = .{ + "LICENSE", + "build.zig", + "build.zig.zon", + }, +} diff --git a/build/src/generate_linkerscript.zig b/build/src/generate_linkerscript.zig index 74bc659..0e66a5d 100644 --- a/build/src/generate_linkerscript.zig +++ b/build/src/generate_linkerscript.zig @@ -1,43 +1,6 @@ const std = @import("std"); - -/// A descriptor for memory regions in a microcontroller. -pub const MemoryRegion = struct { - /// The type of the memory region for generating a proper linker script. - kind: Kind, - offset: u64, - length: u64, - - pub const Kind = union(enum) { - /// This is a (normally) immutable memory region where the code is stored. - flash, - - /// This is a mutable memory region for data storage. - ram, - - /// This is a memory region that maps MMIO devices. - io, - - /// This is a memory region that exists, but is reserved and must not be used. - reserved, - - /// This is a memory region used for internal linking tasks required by the board support package. - private: PrivateRegion, - }; - - pub const PrivateRegion = struct { - /// The name of the memory region. Will not have an automatic numeric counter and must be unique. - name: []const u8, - - /// Is the memory region executable? - executable: bool, - - /// Is the memory region readable? - readable: bool, - - /// Is the memory region writable? - writeable: bool, - }; -}; +const defs = @import("microzig/build/definitions"); +const MemoryRegion = defs.MemoryRegion; pub const Args = struct { cpu_name: []const u8, diff --git a/core/build.zig b/core/build.zig index f9c61b5..fa955d9 100644 --- a/core/build.zig +++ b/core/build.zig @@ -3,7 +3,7 @@ //! This means we need to use addExecutable() instead of using const std = @import("std"); -const MicroZig = @import("microzig/build"); +const MicroZig = @import("microzig/build/definitions"); fn root() []const u8 { return comptime (std.fs.path.dirname(@src().file) orelse "."); diff --git a/core/build.zig.zon b/core/build.zig.zon index 56e4c72..32cfbfe 100644 --- a/core/build.zig.zon +++ b/core/build.zig.zon @@ -1,8 +1,8 @@ .{ - .name = "microzig/core", + .name = "core", .version = "0.0.0", .dependencies = .{ - .@"microzig/build" = .{ .path = "../build" }, + .@"microzig/build/definitions" = .{ .path = "../build/definitions" }, }, .paths = .{ "build.zig", diff --git a/examples/espressif/esp/build.zig.zon b/examples/espressif/esp/build.zig.zon index c995d0f..4eb3596 100644 --- a/examples/espressif/esp/build.zig.zon +++ b/examples/espressif/esp/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/espressif/esp", + .name = "examples/espressif/esp", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/examples/gigadevice/gd32/build.zig.zon b/examples/gigadevice/gd32/build.zig.zon index b4b409c..9edad4f 100644 --- a/examples/gigadevice/gd32/build.zig.zon +++ b/examples/gigadevice/gd32/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/gigadevice/gd32", + .name = "examples/gigadevice/gd32", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/examples/microchip/atsam/build.zig.zon b/examples/microchip/atsam/build.zig.zon index d18fc41..6be5af9 100644 --- a/examples/microchip/atsam/build.zig.zon +++ b/examples/microchip/atsam/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/microchip/atsam", + .name = "examples/microchip/atsam", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/examples/microchip/avr/build.zig.zon b/examples/microchip/avr/build.zig.zon index e320e17..0e88b4d 100644 --- a/examples/microchip/avr/build.zig.zon +++ b/examples/microchip/avr/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/microchip/avr", + .name = "examples/microchip/avr", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/examples/nordic/nrf5x/build.zig.zon b/examples/nordic/nrf5x/build.zig.zon index 3a2fed9..3a6b6c4 100644 --- a/examples/nordic/nrf5x/build.zig.zon +++ b/examples/nordic/nrf5x/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/nordic/nrf5x", + .name = "examples/nordic/nrf5x", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/examples/nxp/lpc/build.zig.zon b/examples/nxp/lpc/build.zig.zon index 12f77a2..4bff1f2 100644 --- a/examples/nxp/lpc/build.zig.zon +++ b/examples/nxp/lpc/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/nxp/lpc", + .name = "examples/nxp/lpc", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/examples/raspberrypi/rp2040/build.zig.zon b/examples/raspberrypi/rp2040/build.zig.zon index 9755cbd..f44eaa6 100644 --- a/examples/raspberrypi/rp2040/build.zig.zon +++ b/examples/raspberrypi/rp2040/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/raspberrypi/rp2040", + .name = "examples/raspberrypi/rp2040", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/examples/stmicro/stm32/build.zig.zon b/examples/stmicro/stm32/build.zig.zon index f26dcae..0508375 100644 --- a/examples/stmicro/stm32/build.zig.zon +++ b/examples/stmicro/stm32/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/examples/stmicro/stm32", + .name = "examples/stmicro/stm32", .version = "0.0.0", .dependencies = .{ .@"microzig/build" = .{ .path = "../../../build" }, diff --git a/tools/regz/build.zig.zon b/tools/regz/build.zig.zon index 1b1f5e0..1ec9098 100644 --- a/tools/regz/build.zig.zon +++ b/tools/regz/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/tools/regz", + .name = "tools/regz", .version = "0.0.0", .paths = .{ "LICENSE", diff --git a/tools/uf2/build.zig.zon b/tools/uf2/build.zig.zon index 4101c29..30ac4de 100644 --- a/tools/uf2/build.zig.zon +++ b/tools/uf2/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "microzig/tools/uf2", + .name = "tools/uf2", .version = "0.0.0", .paths = .{ "build.zig",