Skip to content
Open
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
2 changes: 2 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const port_list: []const struct {
.{ .name = "rp2xxx", .dep_name = "port/raspberrypi/rp2xxx" },
.{ .name = "stm32", .dep_name = "port/stmicro/stm32" },
.{ .name = "ch32v", .dep_name = "port/wch/ch32v" },
.{ .name = "ch32h", .dep_name = "port/wch/ch32h" },
.{ .name = "msp430", .dep_name = "port/texasinstruments/msp430" },
.{ .name = "mspm0", .dep_name = "port/texasinstruments/mspm0" },
.{ .name = "tm4c", .dep_name = "port/texasinstruments/tm4c" },
Expand Down Expand Up @@ -70,6 +71,7 @@ pub const PortSelect = struct {
rp2xxx: bool = false,
stm32: bool = false,
ch32v: bool = false,
ch32h: bool = false,
msp430: bool = false,
mspm0: bool = false,
tm4c: bool = false,
Expand Down
1 change: 1 addition & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
.@"port/texasinstruments/mspm0" = .{ .path = "port/texasinstruments/mspm0", .lazy = true },
.@"port/texasinstruments/tm4c" = .{ .path = "port/texasinstruments/tm4c", .lazy = true },
.@"port/wch/ch32v" = .{ .path = "port/wch/ch32v", .lazy = true },
.@"port/wch/ch32h" = .{ .path = "port/wch/ch32h", .lazy = true },

.@"modules/riscv32-common" = .{ .path = "modules/riscv32-common" },
.@"modules/rtt" = .{ .path = "modules/rtt" },
Expand Down
43 changes: 43 additions & 0 deletions examples/wch/ch32h/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const std = @import("std");
const microzig = @import("microzig");

const MicroBuild = microzig.MicroBuild(.{
.ch32h = true,
});

fn add_example(b: *std.Build, mb: anytype, comptime name: []const u8, optimize: std.builtin.OptimizeMode) void {
const v3f = mb.add_firmware(.{
.name = "v3f",
.root_source_file = b.path("src/" ++ name ++ "/v3f.zig"),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really mind this directory structure (example/board), I'd prefer at least for now if we kept the style of the other examples, e.g. flat, with a blinky_v3f.zig and a blinky_v5f.zig. Bonus points if you can get

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bonus points if you can get

Is this truncated? or did I miss something on my end?

.optimize = optimize,
.target = mb.ports.ch32h.chips.ch32h417_v3f,
});

const v5f = mb.add_firmware(.{
.name = "v5f",
.root_source_file = b.path("src/" ++ name ++ "/v5f.zig"),
.optimize = optimize,
.target = mb.ports.ch32h.chips.ch32h417_v5f,
});

const merged_bin = mb.ports.ch32h.merge(b, v3f.get_emitted_elf(), v5f.get_emitted_elf(), name ++ "_merged.bin");

const install = b.addInstallFileWithDir(merged_bin, .{ .custom = "firmware" }, name ++ ".bin");
b.getInstallStep().dependOn(&install.step);
}

const examples = [_][]const u8{
"blinky",
"interrupts",
};

pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .small });

const mz_dep = b.dependency("microzig", .{});
const mb = MicroBuild.init(b, mz_dep) orelse return;

inline for (examples) |example| {
add_example(b, mb, example, optimize);
}
}
14 changes: 14 additions & 0 deletions examples/wch/ch32h/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.{
.name = .examples_wch_ch32h,
.fingerprint = 0x98c6b66930eca2b,
.version = "0.0.0",
.dependencies = .{
.microzig = .{ .path = "../../.." },
},

.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}
42 changes: 42 additions & 0 deletions examples/wch/ch32h/src/blinky/v3f.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const microzig = @import("microzig");

pub const panic = microzig.panic;

pub const std_options = microzig.std_options(.{});

comptime {
_ = microzig.export_startup();
}

const clock = microzig.hal.clock;
const gpio = microzig.hal.gpio;

const PFIC = microzig.chip.peripherals.PFIC;

fn delay(cycles: u32) void {
for (0..cycles) |_| {
asm volatile ("nop");
}
}

pub fn main() !void {
clock.init();
clock.enable_gpio(.c);

const pc2 = gpio.Pin.init(.{
.port = .c,
.number = 2,
.mode = .{ .output = .general_purpose_open_drain },
.speed = .max_50MHz,
.pull = .disabled,
});

// Wakeup V5F
PFIC.WAKEIP1.raw = 0x10000 & ~@as(u32, 0x3FF);
PFIC.SCTLR.raw |= (1 << 5);

while (true) {
pc2.toggle();
delay(20_000_000);
}
}
35 changes: 35 additions & 0 deletions examples/wch/ch32h/src/blinky/v5f.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const microzig = @import("microzig");

pub const panic = microzig.panic;

pub const std_options = microzig.std_options(.{});

comptime {
_ = microzig.export_startup();
}

const gpio = microzig.hal.gpio;
const clock = microzig.hal.clock;

fn delay(cycles: u32) void {
for (0..cycles) |_| {
asm volatile ("nop");
}
}

pub fn main() !void {
const pc3 = gpio.Pin.init(.{
.port = .c,
.number = 3,
.mode = .{ .output = .general_purpose_open_drain },
.speed = .max_50MHz,
.pull = .disabled,
});

while (true) {
pc3.put(1);
delay(120_000_000);
pc3.put(0);
delay(120_000_000);
}
}
60 changes: 60 additions & 0 deletions examples/wch/ch32h/src/interrupts/v3f.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const microzig = @import("microzig");

pub const panic = microzig.panic;

pub const std_options = microzig.std_options(.{});

comptime {
_ = microzig.export_startup();
}

const cpu = microzig.cpu;
const clock = microzig.hal.clock;
const gpio = microzig.hal.gpio;

const PFIC = microzig.chip.peripherals.PFIC;

pub const microzig_options: microzig.Options = .{
.interrupts = .{ .SW = sw_handler },
};

var pc2: gpio.Pin = undefined;

fn sw_handler() callconv(cpu.riscv_calling_convention) void {
cpu.interrupt.clear_pending(.SW);

pc2.toggle();
}

fn delay(cycles: u32) void {
for (0..cycles) |_| {
asm volatile ("nop");
}
}

pub fn main() !void {
clock.init();
clock.enable_gpio(.c);

pc2 = gpio.Pin.init(.{
.port = .c,
.number = 2,
.mode = .{ .output = .general_purpose_open_drain },
.speed = .max_50MHz,
.pull = .disabled,
});

cpu.interrupt.enable(.SW);

if (cpu.interrupt.current_core() != .v3f)
@panic("unexpected current core");

// Wakeup V5F
PFIC.WAKEIP1.raw = 0x10000 & ~@as(u32, 0x3FF);
PFIC.SCTLR.raw |= (1 << 5);

while (true) {
cpu.interrupt.set_pending(.SW);
delay(20_000_000);
}
}
37 changes: 37 additions & 0 deletions examples/wch/ch32h/src/interrupts/v5f.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const microzig = @import("microzig");

pub const panic = microzig.panic;

pub const std_options = microzig.std_options(.{});

comptime {
_ = microzig.export_startup();
}

const cpu = microzig.cpu;
const gpio = microzig.hal.gpio;
const clock = microzig.hal.clock;

fn delay(cycles: u32) void {
for (0..cycles) |_| {
asm volatile ("nop");
}
}

pub fn main() !void {
if (cpu.interrupt.current_core() != .v5f)
@panic("unexpected current core");

const pc3 = gpio.Pin.init(.{
.port = .c,
.number = 3,
.mode = .{ .output = .general_purpose_open_drain },
.speed = .max_50MHz,
.pull = .disabled,
});

while (true) {
pc3.toggle();
delay(120_000_000);
}
}
130 changes: 130 additions & 0 deletions port/wch/ch32h/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
const std = @import("std");
const microzig = @import("microzig/build-internals");

const Self = @This();

const KiB = 1024;

pub fn build(b: *std.Build) void {
_ = b;
}

pub const v5f_image_offset: u64 = 0x10000;
pub const flash_size: u64 = 960 * KiB;

chips: struct {
ch32h417_v3f: *const microzig.Target,
ch32h417_v5f: *const microzig.Target,
},

boards: struct {},

merge_exe: *std.Build.Step.Compile,

fn create_core(
dep: *std.Build.Dependency,
cpu_name: []const u8,
cpu_impl_file: std.Build.LazyPath,
linker_script_file: std.Build.LazyPath,
memory_regions: []const microzig.MemoryRegion,
) *microzig.Target {
const b = dep.builder;

const cpu_imports = b.allocator.dupe(std.Build.Module.Import, &.{
.{
.name = "riscv32-common",
.module = b.dependency("microzig/modules/riscv32-common", .{}).module("riscv32-common"),
},
.{
.name = "cpu_impl",
.module = std.Build.Module.create(b, .{ .root_source_file = cpu_impl_file }),
},
}) catch @panic("out of memory");

const core = b.allocator.create(microzig.Target) catch @panic("out of memory");
core.* = .{
.dep = dep,
.preferred_binary_format = .binary,
.zig_target = .{
.cpu_arch = .riscv32,
.cpu_model = .{ .explicit = &std.Target.riscv.cpu.generic_rv32 },
.cpu_features_add = cpu_common_features,
.os_tag = .freestanding,
.abi = .eabi,
},
.cpu = .{
.name = cpu_name,
.root_source_file = dep.path("src/cpus/main.zig"),
.imports = cpu_imports,
},
.chip = .{
.name = "CH32H417",
.url = "https://www.wch-ic.com/products/CH32H417.html",
.register_definition = .{ .svd = b.path("src/chips/ch32h417.svd") },
.memory_regions = memory_regions,
},
.hal = .{
.root_source_file = dep.path("src/hals/ch32h417.zig"),
},
.linker_script = .{
.generate = .memory_regions,
.file = linker_script_file,
},
};

return core;
}

const cpu_common_features = std.Target.riscv.featureSet(&.{
.i, .m, .a, .f, .c, .b, .xwchc, .zicsr, .zifencei,
});

pub fn init(dep: *std.Build.Dependency) ?Self {
const b = dep.builder;

// TODO: Combine loader files. These two .ld files have a lot in common.
const chip_v3f = create_core(dep, "qingkev3f", dep.path("src/cpus/qingkev3f.zig"), dep.path("src/chips/ch32h417_v3f.ld"), &.{
.{ .name = "FLASH", .tag = .flash, .offset = 0x0000_0000, .length = v5f_image_offset, .access = .rx },
.{ .name = "SRAM", .tag = .ram, .offset = 0x2010_0000, .length = 512 * KiB, .access = .rwx },
});
const chip_v5f = create_core(dep, "qingkev5f", dep.path("src/cpus/qingkev5f.zig"), dep.path("src/chips/ch32h417_v5f.ld"), &.{
.{ .name = "FLASH", .tag = .flash, .offset = v5f_image_offset, .length = flash_size - v5f_image_offset, .access = .rx },
.{ .name = "DTCM", .tag = .ram, .offset = 0x200C_0000, .length = 256 * KiB, .access = .rw },
.{ .name = "ITCM", .tag = .ram, .offset = 0x200A_0000, .length = 128 * KiB, .access = .rwx },
});

const merge_exe = b.addExecutable(.{
.name = "ch32h417-merge",
.root_module = b.addModule("ch32h417-merge", .{
.root_source_file = dep.path("tools/merge.zig"),
.target = b.graph.host,
}),
});

return .{
.chips = .{
.ch32h417_v3f = chip_v3f,
.ch32h417_v5f = chip_v5f,
},
.boards = .{},
.merge_exe = merge_exe,
};
}

pub fn merge(
self: @This(),
b: *std.Build,
v3f_elf: std.Build.LazyPath,
v5f_elf: std.Build.LazyPath,
merged_bin_path: []const u8,
) std.Build.LazyPath {
const merge_step = b.addRunArtifact(self.merge_exe);

merge_step.addFileArg(v3f_elf);
merge_step.addFileArg(v5f_elf);
const merged_bin = merge_step.addOutputFileArg2(merged_bin_path, .{});

b.getInstallStep().dependOn(&merge_step.step);

return merged_bin;
}
Loading
Loading