Skip to content
Draft
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
46 changes: 46 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub const MemoryRegion = internals.MemoryRegion;

const regz = @import("tools/regz");

pub const tusb = @import("modules/tinyusb");

// If more ports are available, the error "error: evaluation exceeded 1000 backwards branches" may occur.
// In such cases, consider increasing the argument value for @setEvalBranchQuota().
const port_list: []const struct {
Expand Down Expand Up @@ -860,6 +862,50 @@ pub fn MicroBuild(port_select: PortSelect) type {
.{target.cpu.model.name},
);
}
/// Adds build step for tinyUSB and adds a c translate module to app "tinyusb_api" which can be imported
/// input includes and c sources need to include tusb_descriptors.c (or equivalent)
/// and tusb_config.h at a minimum (see) tinyusb documentation for details
/// The api can be imported into a project: `const tinyusb = @import("tinyusb_api");`
/// it's contents is dependant on the configuration in tusb_config.h
pub fn addTinyUsbLib(
root_build: *Build,
fw: *Firmware,
c_sources: []const LazyPath,
includes: []const LazyPath,
) void {
const tusb_dep = fw.mb.dep.builder.dependency("modules/tinyusb", .{});
const tusb_mod = tusb_dep.module("tinyusb");
const target = root_build.resolveTargetQuery(fw.target.zig_target);

tusb_mod.resolved_target = target;
for (c_sources) |source| {
tusb_mod.addCSourceFile(.{ .file = source });
}
for (includes) |path| {
tusb_mod.addIncludePath(path);
}
tusb.addChip(tusb_mod.owner, tusb_mod, fw.target.chip.name);

const tinyusb = root_build.addLibrary(.{
.linkage = .static,
.name = "tinyusb",
.root_module = tusb_mod,
.use_llvm = true,
});
const lib_step = root_build.addInstallArtifact(tinyusb, .{});
root_build.getInstallStep().dependOn(&lib_step.step);
fw.add_object_file(lib_step.emitted_bin.?);

const tusb_api_c = tusb.getTinyUsbCTranslate(
tusb_mod.owner,
target,
);

for (includes) |path| {
tusb_api_c.addIncludePath(path);
}
fw.app_mod.addImport("tinyusb", tusb_api_c.addModule("tinyusb_api"));
}
};
}

Expand Down
1 change: 1 addition & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
.@"modules/foundation-libc" = .{ .path = "modules/foundation-libc" },
.@"modules/riscv32-common" = .{ .path = "modules/riscv32-common" },
.@"modules/rtt" = .{ .path = "modules/rtt" },
.@"modules/tinyusb" = .{ .path = "modules/tinyusb" },

// simulators
.@"sim/aviron" = .{ .path = "sim/aviron", .lazy = true },
Expand Down
146 changes: 146 additions & 0 deletions modules/tinyusb/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
const std = @import("std");
const Build = std.Build;

// TODO: Switch to lazy dependencies?

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

pub fn addTinyUSBLib(b: *Build) void {
const tusb_dep = b.dependency("tusb", .{});
const tusb_src = tusb_dep.path("src");
const module = b.addModule("tinyusb", .{
.link_libc = false,
// seems important to release fast to avoid some extra dependencies
.optimize = .ReleaseFast,
});

module.addIncludePath(b.path("cfiles"));
module.addCSourceFile(.{ .file = b.path("cfiles/printf.c") });

// TinyUSB src folder
module.addIncludePath(tusb_src);
for (tinyusb_source_files) |file| {
module.addCSourceFile(.{ .file = tusb_src.path(b, file) });
}

// Add libc for embedded
const newlib_dep = b.dependency("newlib", .{});
module.addIncludePath(newlib_dep.path("newlib/libc/include"));
}

const SupportedChips = enum {
RP2040,
};

pub fn addChip(b: *Build, module: *Build.Module, chip_name: []const u8) void {
const option = std.meta.stringToEnum(
SupportedChips,
chip_name,
) orelse {
std.debug.print("BUILD ERROR: Chip not supported: {s}\n\r", .{chip_name});
@panic("Chip not supported for TinyUSB yet");
};
switch (option) {
.RP2040 => {
module.addCMacro("CFG_TUSB_MCU", "OPT_MCU_RP2040");
module.addCMacro("CFG_TUSB_OS", "OPT_OS_NONE");
module.addCMacro("PICO_RP2040", "1");
module.addCMacro("BOARD_TUD_RHPORT", "0");
// pico-sdk headers
addPicoSdkInclude(b, module);
},
}
}

pub fn getTinyUsbCTranslate(
b: *Build,
target: Build.ResolvedTarget,
) *Build.Step.TranslateC {
// const target = b.standardTargetOptions(.{});
const tusb_dep = b.dependency("tusb", .{});
const tusb_src = tusb_dep.path("src");
const tinyusb_c = b.addTranslateC(.{
.root_source_file = tusb_src.path(b, "tusb.h"),
.target = target,
.optimize = .ReleaseFast,
.link_libc = false,
});

tinyusb_c.defineCMacro("CFG_TUSB_MCU", "OPT_MCU_NONE");
tinyusb_c.defineCMacro("CFG_TUSB_OS", "OPT_OS_NONE");

// TinyUSB src folder
tinyusb_c.addIncludePath(tusb_src);

// Add libc for embedded
const newlib_dep = b.dependency("newlib", .{});
tinyusb_c.addIncludePath(newlib_dep.path("newlib/libc/include"));

return tinyusb_c;
}

/// List of all .c files in the tinyUSB src directory less the portable directory files
/// tinyusb does a good job only compiling based on options selected.
const tinyusb_source_files = [_][]const u8{
"tusb.c",
"device/usbd.c",
"device/usbd_control.c",
"class/msc/msc_host.c",
"class/msc/msc_device.c",
"class/cdc/cdc_host.c",
"class/cdc/cdc_rndis_host.c",
"class/cdc/cdc_device.c",
"class/dfu/dfu_rt_device.c",
"class/dfu/dfu_device.c",
"class/video/video_device.c",
"class/usbtmc/usbtmc_device.c",
"class/vendor/vendor_host.c",
"class/vendor/vendor_device.c",
"class/net/ecm_rndis_device.c",
"class/net/ncm_device.c",
// "class/mtp/mtp_device.c", not available in older tinyusb compatible with sdk?
"class/audio/audio_device.c",
"class/bth/bth_device.c",
"class/midi/midi_device.c",
// "class/midi/midi_host.c", not available in older tinyusb compatible with sdk?
"class/hid/hid_device.c",
"class/hid/hid_host.c",
"host/usbh.c",
"host/hub.c",
"common/tusb_fifo.c",
"typec/usbc.c",
"portable/raspberrypi/rp2040/rp2040_usb.c",
"portable/raspberrypi/rp2040/dcd_rp2040.c",
};

fn addPicoSdkInclude(b: *std.Build, m: *std.Build.Module) void {
const pico_sdk_dep = b.dependency("pico_sdk", .{});
for (rp_2040_includes) |dir| {
m.addIncludePath(pico_sdk_dep.path(dir));
}
}

const rp_2040_includes = [_][]const u8{
"src",
"src/common/pico_base_headers/include",
"src/common/pico_time/include",
"src/rp2_common/pico_platform_compiler/include",
"src/rp2_common/pico_platform_sections/include",
"src/rp2_common/pico_platform_panic/include",
"src/rp2_common/pico_platform_common/include",
"src/rp2_common/hardware_timer/include",
"src/rp2_common/hardware_base/include",
"src/rp2350/hardware_regs/include",
"src/rp2350/hardware_structs/include",
"src/common/pico_sync/include",
"src/rp2_common/hardware_sync/include",
"src/rp2_common/hardware_sync_spin_lock/include",
"src/rp2_common/hardware_irq/include",
"src/rp2_common/hardware_resets/include",
// I think these are the only things that would need to change for RP2350
"src/rp2040/pico_platform/include",
"src/rp2040/hardware_structs/include",
"src/rp2040/hardware_regs/include",
};
32 changes: 32 additions & 0 deletions modules/tinyusb/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.{
.name = .tinyusb,
.version = "0.1.0",
.fingerprint = 0x6f11d314f5263da7, // Changing this has security and trust implications?
.minimum_zig_version = "0.15.1",
.dependencies = .{
.pico_sdk = .{
.url = "https://github.com/raspberrypi/pico-sdk/releases/download/2.2.0/pico-sdk-2.2.0.tar.gz",
.sha256 = "sha256:2678fe2b176cf64a7f71cd91749fdf9134c8cf7ff84b7199dfe5ea0d6dba6fa4",
.hash = "N-V-__8AAJZDcwFLNdIEF1wutjiH14f8fSET5jNORZIZKCaM",
},
.tusb = .{
// matches pico-sdk submodule hash
.url = "git+https://github.com/hathach/tinyusb.git#86ad6e56c1700e85f1c5678607a762cfe3aa2f47",
.hash = "N-V-__8AAGUZ_gDYqxEdexw7Rfp9YENlWbwlDPQu0bCfKxws",
},
// newlib folder of this seems to have the same licensing as the pico (not a lawyer)
.newlib = .{
.url = "https://sourceware.org/pub/newlib/newlib-4.5.0.20241231.tar.gz",
.sha256 = "sha256:8f6903f8ceb0f991490a1e34074443c2a72b14dbd",
.hash = "N-V-__8AAJH7PAM8M1Wj7e7momRRAp7hssKtI2VvX0vEz-_B",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
// For example...
//"LICENSE",
"README.md",
},
}
Empty file.
Empty file.
Loading