Skip to content

Commit 97131a0

Browse files
committed
ch32v: Add time and clocks config (#742)
1 parent 65ddeef commit 97131a0

File tree

17 files changed

+368
-33
lines changed

17 files changed

+368
-33
lines changed

examples/wch/ch32v/src/blinky_systick.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ else
1010
hal.gpio.Pin.init(0, 3); // PA3
1111

1212
pub const microzig_options: microzig.Options = .{
13+
.overwrite_hal_interrupts = true,
1314
.interrupts = .{
1415
.SysTick = sys_tick_handler,
1516
},
Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const microzig = @import("microzig");
2+
const hal = microzig.hal;
23
const board = microzig.board;
34

45
// Can define in the board file.
@@ -12,6 +13,9 @@ const board = microzig.board;
1213
// };
1314

1415
pub fn main() !void {
16+
// Board brings up clocks and time
17+
board.init();
18+
1519
const pins = board.pin_config.apply();
1620

1721
while (true) {
@@ -22,18 +26,6 @@ pub fn main() !void {
2226
// }
2327
pins.led.toggle();
2428

25-
busy_delay(1000);
26-
}
27-
}
28-
29-
inline fn busy_delay(comptime ms: u32) void {
30-
const cpu_frequency = board.cpu_frequency;
31-
const cycles_per_ms = cpu_frequency / 1_000;
32-
const loop_cycles = 3;
33-
const limit = cycles_per_ms * ms / loop_cycles;
34-
35-
var i: u32 = 0;
36-
while (i < limit) : (i += 1) {
37-
asm volatile ("" ::: .{ .memory = true });
29+
hal.time.sleep_ms(1000);
3830
}
3931
}

port/wch/ch32v/build.zig

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const std = @import("std");
22
const microzig = @import("microzig/build-internals");
33
const CpuName = @import("src/cpus/main.zig").CpuName;
44

5+
// Technical reference manuals:
6+
// 003: https://ch32-riscv-ug.github.io/CH32V003/datasheet_en/CH32V003RM.PDF
7+
// 20x, 30x, 31x: https://static.chipdip.ru/lib/820/DOC059820997.pdf
58
const Self = @This();
69

710
const KiB = 1024;
@@ -67,7 +70,10 @@ const BaseChip = struct {
6770
};
6871

6972
// Generated with:
70-
// curl 'https://www.wch-ic.com/api/product_tables/47?page=1&limit=100' | jq -r '.data[] | select(.["Part NO."] | startswith("CH32V")) | [ " ", (.["Part NO."] | ascii_downcase), ": *const microzig.Target, // ", .Flash, " / ", .SRAM, " / ", .Freq ] | join("")' | awk 'match($0, / ch32v/) { $0 = substr($0, 1, RSTART+11) "x" substr($0, RSTART+13, 1) substr($0, RSTART+16) }; {print}' | sort -n | uniq
73+
// curl 'https://www.wch-ic.com/api/product_tables/47?page=1&limit=100' |
74+
// jq -r '.data[] | select(.["Part NO."] | startswith("CH32V")) | [ " ", (.["Part NO."] | ascii_downcase), ": *const microzig.Target, // ", .Flash, " / ", .SRAM, " / ", .Freq ] | join("")' |
75+
// awk 'match($0, / ch32v/) { $0 = substr($0, 1, RSTART+11) "x" substr($0, RSTART+13, 1) substr($0, RSTART+16) }; {print}' |
76+
// sort -n | uniq
7177
chips: struct {
7278
ch32v003x4: *const microzig.Target, // 16K / 2K / 48MHz
7379
ch32v103x6: *const microzig.Target, // 32K / 10K / 80MHz
@@ -91,6 +97,7 @@ boards: struct {
9197
},
9298
ch32v203: struct {
9399
suzuduino_uno_v1b: *const microzig.Target,
100+
lana_tny: *const microzig.Target,
94101
},
95102
ch32v305: struct {
96103
nano_ch32v305: *const microzig.Target,
@@ -191,6 +198,14 @@ pub fn init(dep: *std.Build.Dependency) Self {
191198
},
192199
});
193200

201+
const board_lana_tny = chip_ch32v203x6.derive(.{
202+
.board = .{
203+
.name = "LANA TNY",
204+
.url = "https://phyx.be/LANA_TNY/",
205+
.root_source_file = b.path("src/boards/LANA_TNY.zig"),
206+
},
207+
});
208+
194209
return .{
195210
.chips = .{
196211
.ch32v003x4 = chip_ch32v003x4,
@@ -215,6 +230,7 @@ pub fn init(dep: *std.Build.Dependency) Self {
215230
},
216231
.ch32v203 = .{
217232
.suzuduino_uno_v1b = board_suzuduino_uno_v1b,
233+
.lana_tny = board_lana_tny,
218234
},
219235
.ch32v305 = .{
220236
.nano_ch32v305 = board_nano_ch32v305,

port/wch/ch32v/src/boards/CH32V103-R1-1v1.zig

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,12 @@
22
// CH32V103
33
pub const chip = @import("chip");
44
pub const microzig = @import("microzig");
5+
const ch32v = microzig.hal;
56

6-
pub const cpu_frequency = 8_000_000; // 8 MHz
7+
pub const cpu_frequency = 48_000_000; // 48 MHz
8+
9+
/// Board-specific init: set 48 MHz clock, enable SysTick time
10+
pub fn init() void {
11+
ch32v.clocks.init_48mhz_hsi();
12+
ch32v.time.init();
13+
}
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
// CH32V307V_MINI
22
// CH32V307
3+
pub const microzig = @import("microzig");
34
pub const chip = @import("chip");
5+
const ch32v = microzig.hal;
46

5-
pub const cpu_frequency = 8_000_000; // 8 MHz
7+
pub const cpu_frequency = 48_000_000; // 48 MHz
8+
9+
/// Board-specific init: set 48 MHz clock, enable SysTick time
10+
pub fn init() void {
11+
ch32v.clocks.init_48mhz_hsi();
12+
ch32v.time.init();
13+
}
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
// CH32Vx03C_MINI
22
// CH32V203
3+
pub const microzig = @import("microzig");
34
pub const chip = @import("chip");
5+
const ch32v = microzig.hal;
46

5-
pub const cpu_frequency = 8_000_000; // 8 MHz
7+
pub const cpu_frequency = 48_000_000; // 48 MHz
8+
9+
/// Board-specific init: set 48 MHz clock, enable SysTick time
10+
pub fn init() void {
11+
ch32v.clocks.init_48mhz_hsi();
12+
ch32v.time.init();
13+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// LANA TNY Board
2+
// https://learn.adafruit.com/phyx-lana-tny-ch32v203/pinouts
3+
// CH32V203
4+
pub const microzig = @import("microzig");
5+
pub const chip = @import("chip");
6+
const ch32v = microzig.hal;
7+
8+
pub const cpu_frequency = 48_000_000; // 48 MHz
9+
10+
/// Board-specific init: set 48 MHz clock, enable SysTick time
11+
pub fn init() void {
12+
ch32v.clocks.init_48mhz_hsi();
13+
ch32v.time.init();
14+
}
15+
16+
pub const pin_config = ch32v.pins.GlobalConfiguration{
17+
.GPIOD = .{
18+
.PIN0 = .{
19+
.name = "ws2812",
20+
.mode = .{ .output = .general_purpose_push_pull },
21+
.speed = .max_50MHz,
22+
},
23+
},
24+
};
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Suzuduino Uno V1b
22
// https://github.com/verylowfreq/suzuduino-uno-v1
33
// CH32V203
4-
pub const chip = @import("chip");
54
pub const microzig = @import("microzig");
5+
pub const chip = @import("chip");
66
const ch32v = microzig.hal;
77

8-
pub const cpu_frequency = 8_000_000; // 8 MHz
8+
pub const cpu_frequency = 48_000_000; // 48 MHz
99

1010
pub const pin_config = ch32v.pins.GlobalConfiguration{
1111
.GPIOA = .{
@@ -15,3 +15,9 @@ pub const pin_config = ch32v.pins.GlobalConfiguration{
1515
},
1616
},
1717
};
18+
19+
/// Board-specific init: set 48 MHz clock, enable SysTick time
20+
pub fn init() void {
21+
ch32v.clocks.init_48mhz_hsi();
22+
ch32v.time.init();
23+
}

port/wch/ch32v/src/boards/nanoCH32V305.zig

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub const chip = @import("chip");
55
pub const microzig = @import("microzig");
66
const ch32v = microzig.hal;
77

8-
pub const cpu_frequency = 8_000_000; // 8 MHz
8+
pub const cpu_frequency = 48_000_000; // 48 MHz
99

1010
pub const pin_config = ch32v.pins.GlobalConfiguration{
1111
.GPIOA = .{
@@ -15,3 +15,9 @@ pub const pin_config = ch32v.pins.GlobalConfiguration{
1515
},
1616
},
1717
};
18+
19+
/// Board-specific init: set 48 MHz clock, enable SysTick time
20+
pub fn init() void {
21+
ch32v.clocks.init_48mhz_hsi();
22+
ch32v.time.init();
23+
}

port/wch/ch32v/src/cpus/main.zig

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub const InterruptOptions = microzig.utilities.GenerateInterruptOptions(&.{
3838
.{ .InterruptEnum = enum { Exception }, .HandlerFn = InterruptHandler },
3939
.{ .InterruptEnum = Interrupt, .HandlerFn = InterruptHandler },
4040
});
41+
const VectorTable = [vector_table_size()]InterruptHandler;
4142

4243
pub const interrupt = struct {
4344
pub inline fn globally_enabled() bool {
@@ -69,7 +70,12 @@ pub const interrupt = struct {
6970
pub inline fn enable(irq: Interrupt) void {
7071
comptime {
7172
const irq_name = @tagName(irq);
72-
if (@field(microzig.options.interrupts, irq_name) == null) {
73+
const app_has = @field(microzig.options.interrupts, irq_name) != null;
74+
const hal_has = if (microzig.config.has_hal and @hasDecl(microzig.hal, "default_interrupts"))
75+
@field(microzig.hal.default_interrupts, irq_name) != null
76+
else
77+
false;
78+
if (!app_has and !hal_has) {
7379
@compileError(
7480
irq_name ++ " interrupt handler should be defined.\n" ++
7581
"Add to your main file:\n" ++
@@ -327,14 +333,15 @@ fn vector_table_size() usize {
327333
return last_interrupt_idx + 1 - vector_table_offset;
328334
}
329335

330-
pub fn generate_vector_table() [vector_table_size()]InterruptHandler {
336+
pub fn generate_vector_table() VectorTable {
331337
@setEvalBranchQuota(100_000);
338+
var tmp: VectorTable = @splat(microzig.options.interrupts.Exception orelse unhandled);
332339

333340
const type_info = @typeInfo(Interrupt);
334341
const interrupts_list = type_info.@"enum".fields;
335342

336-
var temp: [vector_table_size()]InterruptHandler = @splat(microzig.options.interrupts.Exception orelse unhandled);
337-
for (&temp, vector_table_offset..) |_, idx| {
343+
// Apply interrupts
344+
for (&tmp, vector_table_offset..) |_, idx| {
338345
// Find name of the interrupt by its number.
339346
var name: ?[:0]const u8 = null;
340347
for (interrupts_list) |decl| {
@@ -345,13 +352,33 @@ pub fn generate_vector_table() [vector_table_size()]InterruptHandler {
345352
}
346353

347354
if (name) |n| {
348-
if (@field(microzig.options.interrupts, n)) |h| {
349-
temp[idx - vector_table_offset] = h;
350-
}
355+
const maybe_handler = @field(microzig.options.interrupts, n);
356+
const maybe_default = get_hal_default_handler(n);
357+
358+
tmp[idx - vector_table_offset] = blk: {
359+
if (maybe_handler) |handler| {
360+
if (!microzig.options.overwrite_hal_interrupts and maybe_default != null)
361+
@compileError(std.fmt.comptimePrint(
362+
\\Interrupt {s} is used internally by the HAL; overriding it may cause malfunction.
363+
\\If you are sure of what you are doing, set "overwrite_hal_interrupts" to true in: "microzig_options".
364+
\\
365+
, .{n}));
366+
break :blk handler;
367+
} else break :blk maybe_default orelse unhandled;
368+
};
351369
}
352370
}
353371

354-
return temp;
372+
return tmp;
373+
}
374+
375+
fn get_hal_default_handler(comptime handler_name: []const u8) ?InterruptHandler {
376+
if (microzig.config.has_hal) {
377+
if (@hasDecl(microzig.hal, "default_interrupts")) {
378+
return @field(microzig.hal.default_interrupts, handler_name);
379+
}
380+
}
381+
return null;
355382
}
356383

357384
const vector_table = generate_vector_table();
@@ -452,4 +479,9 @@ pub const csr = struct {
452479
pub const cpmpocr = Csr(0xBC3, u32);
453480
pub const cmcr = Csr(0xBD0, u32);
454481
pub const cinfor = Csr(0xFC0, u32);
482+
483+
// Cycle counters
484+
pub const cycle = riscv32_common.csr.cycle;
485+
pub const cycleh = riscv32_common.csr.cycleh;
486+
pub const mcountinhibit = riscv32_common.csr.mcountinhibit;
455487
};

0 commit comments

Comments
 (0)