From de5ee2a5ca110798f4a6a0f86533c0a775c31426 Mon Sep 17 00:00:00 2001 From: Grazfather Date: Sat, 10 Jan 2026 10:38:59 -0500 Subject: [PATCH 1/3] ch32v: Add nano_ch32v203 board --- examples/wch/ch32v/build.zig | 1 + port/wch/ch32v/build.zig | 10 ++++++++ port/wch/ch32v/src/boards/nanoCH32V203.zig | 30 ++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 port/wch/ch32v/src/boards/nanoCH32V203.zig diff --git a/examples/wch/ch32v/build.zig b/examples/wch/ch32v/build.zig index 43d04c258..3eccd23bc 100644 --- a/examples/wch/ch32v/build.zig +++ b/examples/wch/ch32v/build.zig @@ -30,6 +30,7 @@ pub fn build(b: *std.Build) void { .{ .target = mb.ports.ch32v.chips.ch32v203x6, .name = "empty_ch32v203", .file = "src/empty.zig" }, .{ .target = mb.ports.ch32v.chips.ch32v203x6, .name = "blinky_ch32v203", .file = "src/blinky.zig" }, .{ .target = mb.ports.ch32v.chips.ch32v203x6, .name = "blinky_systick_ch32v203", .file = "src/blinky_systick.zig" }, + .{ .target = mb.ports.ch32v.boards.ch32v203.nano_ch32v203, .name = "nano_ch32v203_blinky", .file = "src/board_blinky.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.suzuduino_uno_v1b, .name = "suzuduino_blinky", .file = "src/board_blinky.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_dma", .file = "src/dma.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_ws2812", .file = "src/ws2812.zig" }, diff --git a/port/wch/ch32v/build.zig b/port/wch/ch32v/build.zig index 64e36e81f..e2556d0a9 100644 --- a/port/wch/ch32v/build.zig +++ b/port/wch/ch32v/build.zig @@ -98,6 +98,7 @@ boards: struct { ch32v203: struct { suzuduino_uno_v1b: *const microzig.Target, lana_tny: *const microzig.Target, + nano_ch32v203: *const microzig.Target, }, ch32v305: struct { nano_ch32v305: *const microzig.Target, @@ -206,6 +207,14 @@ pub fn init(dep: *std.Build.Dependency) Self { }, }); + const board_nano_ch32v203 = chip_ch32v203x8.derive(.{ + .board = .{ + .name = "nanoCH32V203", + .url = "https://github.com/wuxx/nanoCH32V203", + .root_source_file = b.path("src/boards/nanoCH32V203.zig"), + }, + }); + return .{ .chips = .{ .ch32v003x4 = chip_ch32v003x4, @@ -231,6 +240,7 @@ pub fn init(dep: *std.Build.Dependency) Self { .ch32v203 = .{ .suzuduino_uno_v1b = board_suzuduino_uno_v1b, .lana_tny = board_lana_tny, + .nano_ch32v203 = board_nano_ch32v203, }, .ch32v305 = .{ .nano_ch32v305 = board_nano_ch32v305, diff --git a/port/wch/ch32v/src/boards/nanoCH32V203.zig b/port/wch/ch32v/src/boards/nanoCH32V203.zig new file mode 100644 index 000000000..156b294c5 --- /dev/null +++ b/port/wch/ch32v/src/boards/nanoCH32V203.zig @@ -0,0 +1,30 @@ +// nanoCH32V203 +// https://github.com/wuxx/nanoCH32V203 +// CH32V203C8T6 +pub const microzig = @import("microzig"); +pub const chip = @import("chip"); +const ch32v = microzig.hal; + +/// Clock configuration for this board +pub const clock_config: ch32v.clocks.Config = .{ + .source = .hsi, + .target_frequency = 48_000_000, +}; + +/// CPU frequency is derived from clock config +pub const cpu_frequency = clock_config.target_frequency; + +/// Board-specific init +pub fn init() void { + ch32v.clocks.init(clock_config); + ch32v.time.init(); +} + +pub const pin_config = ch32v.pins.GlobalConfiguration{ + .GPIOA = .{ + .PIN15 = .{ + .name = "led", + .mode = .{ .output = .general_purpose_push_pull }, + }, + }, +}; From 1a0b8836303b337c7fff9e745d6330225958028f Mon Sep 17 00:00:00 2001 From: Grazfather Date: Sat, 10 Jan 2026 10:44:51 -0500 Subject: [PATCH 2/3] nano has 8MHz on board. --- port/wch/ch32v/src/boards/nanoCH32V203.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/port/wch/ch32v/src/boards/nanoCH32V203.zig b/port/wch/ch32v/src/boards/nanoCH32V203.zig index 156b294c5..ecc0334c4 100644 --- a/port/wch/ch32v/src/boards/nanoCH32V203.zig +++ b/port/wch/ch32v/src/boards/nanoCH32V203.zig @@ -7,8 +7,9 @@ const ch32v = microzig.hal; /// Clock configuration for this board pub const clock_config: ch32v.clocks.Config = .{ - .source = .hsi, + .source = .hse, .target_frequency = 48_000_000, + .hse_frequency = 8_000_000, }; /// CPU frequency is derived from clock config From b47cd6a8299452de3da8229c08152f3d39d94e2c Mon Sep 17 00:00:00 2001 From: Grazfather Date: Sat, 10 Jan 2026 11:06:05 -0500 Subject: [PATCH 3/3] Support setting HSE to 144MHz --- port/wch/ch32v/src/hals/clocks.zig | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/port/wch/ch32v/src/hals/clocks.zig b/port/wch/ch32v/src/hals/clocks.zig index ec2b0d62c..8efa45fc8 100644 --- a/port/wch/ch32v/src/hals/clocks.zig +++ b/port/wch/ch32v/src/hals/clocks.zig @@ -131,7 +131,10 @@ fn validate_config(comptime config: Config) void { // Validate supported target frequencies for HSE if (config.source == .hse) { const hse_freq = config.hse_frequency.?; - if (config.target_frequency != hse_freq and config.target_frequency != 48_000_000) { + if (config.target_frequency != hse_freq and + config.target_frequency != 48_000_000 and + config.target_frequency != 144_000_000) + { @compileError("Unsupported target_frequency for HSE. Supported: HSE frequency directly, or 48 MHz with PLL"); } } @@ -245,6 +248,7 @@ fn init_from_hse(hse_freq: u32, target_freq: u32) void { // Use PLL to reach 48 MHz from HSE // Common case: 8 MHz HSE -> 48 MHz (6x multiplier) + // TODO: We don't actually ensure that HSE is 8MHz. Fix this. if (target_freq == 48_000_000) { RCC.CFGR0.modify(.{ .HPRE = 0, // AHB prescaler = 1 @@ -259,6 +263,23 @@ fn init_from_hse(hse_freq: u32, target_freq: u32) void { RCC.CTLR.modify(.{ .PLLON = 1 }); while (RCC.CTLR.read().PLLRDY == 0) {} + // Select PLL as system clock + RCC.CFGR0.modify(.{ .SW = 2 }); + while (RCC.CFGR0.read().SWS != 2) {} + } else if (target_freq == 144_000_000) { + RCC.CFGR0.modify(.{ + .HPRE = 0, // AHB prescaler = 1 + .PPRE2 = 0, // APB2 prescaler = 1 + .PPRE1 = 4, // APB1 prescaler = 2 + .PLLSRC = 1, // PLL source = HSE + .PLLXTPRE = 0, // HSE not divided before PLL + .PLLMUL = 15, // PLL multiplier = 18 + }); + + // Enable PLL + RCC.CTLR.modify(.{ .PLLON = 1 }); + while (RCC.CTLR.read().PLLRDY == 0) {} + // Select PLL as system clock RCC.CFGR0.modify(.{ .SW = 2 }); while (RCC.CFGR0.read().SWS != 2) {}