From dd7a87c5d4f3feea641e75e2b934ca2fc10f4ffb Mon Sep 17 00:00:00 2001 From: Piotr Fila Date: Sun, 25 Jan 2026 15:49:36 +0100 Subject: [PATCH 1/3] like this? --- port/wch/ch32v/src/cpus/main.zig | 98 +++++++++++++++----------------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/port/wch/ch32v/src/cpus/main.zig b/port/wch/ch32v/src/cpus/main.zig index cde786de7..d0c98b600 100644 --- a/port/wch/ch32v/src/cpus/main.zig +++ b/port/wch/ch32v/src/cpus/main.zig @@ -220,21 +220,61 @@ pub const startup_logic = struct { extern fn microzig_main() noreturn; pub fn _start() callconv(.naked) void { - // Set global pointer. asm volatile ( + \\ + // Set global pointer. \\.option push \\.option norelax \\la gp, __global_pointer$ \\.option pop - ); + \\ + // Set stack pointer. + \\mv sp, %[eos] + + // Initialize the system. + \\jal _system_init - // Set stack pointer. - const eos = comptime microzig.utilities.get_end_of_stack(); - asm volatile ("mv sp, %[eos]" + // Return from the interrupt. + // This changes the privilege level to mstatus.mpp, set above. In this case we are in + // machine mode and we are switching to machine mode, but normally this could switch us to + // user mode. + \\mret : - : [eos] "r" (@as(u32, @intFromPtr(eos))), + : [eos] "r" (comptime microzig.utilities.get_end_of_stack()), + ); + } + + inline fn initialize_system_memories() void { + // Clear .bss section. + asm volatile ( + \\ li a0, 0 + \\ la a1, microzig_bss_start + \\ la a2, microzig_bss_end + \\ beq a1, a2, clear_bss_done + \\clear_bss_loop: + \\ sw a0, 0(a1) + \\ addi a1, a1, 4 + \\ blt a1, a2, clear_bss_loop + \\clear_bss_done: ); + // Copy .data from FLASH to RAM. + asm volatile ( + \\ la a0, microzig_data_load_start + \\ la a1, microzig_data_start + \\ la a2, microzig_data_end + \\copy_data_loop: + \\ beq a1, a2, copy_done + \\ lw a3, 0(a0) + \\ sw a3, 0(a1) + \\ addi a0, a0, 4 + \\ addi a1, a1, 4 + \\ bne a1, a2, copy_data_loop + \\copy_done: + ); + } + + export fn _system_init() callconv(.c) void { // NOTE: this can only be called once. Otherwise, we get a linker error for duplicate symbols startup_logic.initialize_system_memories(); @@ -278,57 +318,13 @@ pub const startup_logic = struct { .mpp = 0x3, }); - // Initialize the system. - @export(&startup_logic._system_init, .{ .name = "_system_init" }); - asm volatile ( - \\jal _system_init - ); + cpu_impl.system_init(microzig.chip); // Load the address of the `microzig_main` function into the `mepc` register // and transfer control to it using the `mret` instruction. // This is necessary to ensure proper MCU startup after a power-off. // Directly calling the function from an interrupt would prevent the MCU from starting correctly. csr.mepc.write(@intFromPtr(µzig_main)); - - // Return from the interrupt. - // This changes the privilege level to mstatus.mpp, set above. In this case we are in - // machine mode and we are switching to machine mode, but normally this could switch us to - // user mode. - asm volatile ("mret"); - } - - inline fn initialize_system_memories() void { - // Clear .bss section. - asm volatile ( - \\ li a0, 0 - \\ la a1, microzig_bss_start - \\ la a2, microzig_bss_end - \\ beq a1, a2, clear_bss_done - \\clear_bss_loop: - \\ sw a0, 0(a1) - \\ addi a1, a1, 4 - \\ blt a1, a2, clear_bss_loop - \\clear_bss_done: - ); - - // Copy .data from FLASH to RAM. - asm volatile ( - \\ la a0, microzig_data_load_start - \\ la a1, microzig_data_start - \\ la a2, microzig_data_end - \\copy_data_loop: - \\ beq a1, a2, copy_done - \\ lw a3, 0(a0) - \\ sw a3, 0(a1) - \\ addi a0, a0, 4 - \\ addi a1, a1, 4 - \\ bne a1, a2, copy_data_loop - \\copy_done: - ); - } - - fn _system_init() callconv(.c) void { - cpu_impl.system_init(microzig.chip); } export fn _reset_vector() linksection("microzig_flash_start") callconv(.naked) void { From 94b30bb4e3f7d67616490e37d658fa2430660ca1 Mon Sep 17 00:00:00 2001 From: Piotr Fila Date: Sun, 25 Jan 2026 16:23:24 +0100 Subject: [PATCH 2/3] tail call _system_init --- port/wch/ch32v/src/cpus/main.zig | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/port/wch/ch32v/src/cpus/main.zig b/port/wch/ch32v/src/cpus/main.zig index d0c98b600..e79dfddaf 100644 --- a/port/wch/ch32v/src/cpus/main.zig +++ b/port/wch/ch32v/src/cpus/main.zig @@ -232,13 +232,7 @@ pub const startup_logic = struct { \\mv sp, %[eos] // Initialize the system. - \\jal _system_init - - // Return from the interrupt. - // This changes the privilege level to mstatus.mpp, set above. In this case we are in - // machine mode and we are switching to machine mode, but normally this could switch us to - // user mode. - \\mret + \\j _system_init : : [eos] "r" (comptime microzig.utilities.get_end_of_stack()), ); @@ -274,7 +268,7 @@ pub const startup_logic = struct { ); } - export fn _system_init() callconv(.c) void { + export fn _system_init() callconv(.c) noreturn { // NOTE: this can only be called once. Otherwise, we get a linker error for duplicate symbols startup_logic.initialize_system_memories(); @@ -325,6 +319,13 @@ pub const startup_logic = struct { // This is necessary to ensure proper MCU startup after a power-off. // Directly calling the function from an interrupt would prevent the MCU from starting correctly. csr.mepc.write(@intFromPtr(µzig_main)); + + // Return from the interrupt. + // This changes the privilege level to mstatus.mpp, set above. In this case we are in + // machine mode and we are switching to machine mode, but normally this could switch us to + // user mode. + asm volatile ("mret"); + unreachable; } export fn _reset_vector() linksection("microzig_flash_start") callconv(.naked) void { From 4e95302069dd62142017de74e4998efc7daf978b Mon Sep 17 00:00:00 2001 From: Piotr Fila Date: Sun, 25 Jan 2026 19:45:33 +0100 Subject: [PATCH 3/3] make diff nicer --- port/wch/ch32v/src/cpus/main.zig | 60 ++++++++++++++++---------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/port/wch/ch32v/src/cpus/main.zig b/port/wch/ch32v/src/cpus/main.zig index e79dfddaf..9b5fa6462 100644 --- a/port/wch/ch32v/src/cpus/main.zig +++ b/port/wch/ch32v/src/cpus/main.zig @@ -238,36 +238,6 @@ pub const startup_logic = struct { ); } - inline fn initialize_system_memories() void { - // Clear .bss section. - asm volatile ( - \\ li a0, 0 - \\ la a1, microzig_bss_start - \\ la a2, microzig_bss_end - \\ beq a1, a2, clear_bss_done - \\clear_bss_loop: - \\ sw a0, 0(a1) - \\ addi a1, a1, 4 - \\ blt a1, a2, clear_bss_loop - \\clear_bss_done: - ); - - // Copy .data from FLASH to RAM. - asm volatile ( - \\ la a0, microzig_data_load_start - \\ la a1, microzig_data_start - \\ la a2, microzig_data_end - \\copy_data_loop: - \\ beq a1, a2, copy_done - \\ lw a3, 0(a0) - \\ sw a3, 0(a1) - \\ addi a0, a0, 4 - \\ addi a1, a1, 4 - \\ bne a1, a2, copy_data_loop - \\copy_done: - ); - } - export fn _system_init() callconv(.c) noreturn { // NOTE: this can only be called once. Otherwise, we get a linker error for duplicate symbols startup_logic.initialize_system_memories(); @@ -328,6 +298,36 @@ pub const startup_logic = struct { unreachable; } + inline fn initialize_system_memories() void { + // Clear .bss section. + asm volatile ( + \\ li a0, 0 + \\ la a1, microzig_bss_start + \\ la a2, microzig_bss_end + \\ beq a1, a2, clear_bss_done + \\clear_bss_loop: + \\ sw a0, 0(a1) + \\ addi a1, a1, 4 + \\ blt a1, a2, clear_bss_loop + \\clear_bss_done: + ); + + // Copy .data from FLASH to RAM. + asm volatile ( + \\ la a0, microzig_data_load_start + \\ la a1, microzig_data_start + \\ la a2, microzig_data_end + \\copy_data_loop: + \\ beq a1, a2, copy_done + \\ lw a3, 0(a0) + \\ sw a3, 0(a1) + \\ addi a0, a0, 4 + \\ addi a1, a1, 4 + \\ bne a1, a2, copy_data_loop + \\copy_done: + ); + } + export fn _reset_vector() linksection("microzig_flash_start") callconv(.naked) void { asm volatile ("j _start"); }