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
7 changes: 0 additions & 7 deletions core/src/cpus/riscv32.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const std = @import("std");
const microzig = @import("microzig");

const riscv32_common = @import("riscv32-common");
Expand All @@ -8,12 +7,6 @@ pub const interrupt = riscv32_common.interrupt;
pub const nop = riscv32_common.nop;
pub const wfi = riscv32_common.wfi;

pub fn wfe() void {
asm volatile ("csrs 0x810, 0x1");
wfi();
asm volatile ("csrs 0x810, 0x1");
}

pub const startup_logic = struct {
extern fn microzig_main() noreturn;

Expand Down
1 change: 1 addition & 0 deletions examples/wch/ch32v/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub fn build(b: *std.Build) void {
.{ .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.nano_ch32v203, .name = "nano_ch32v203_blinky_wfe", .file = "src/blinky_wfe.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" },
Expand Down
57 changes: 57 additions & 0 deletions examples/wch/ch32v/src/blinky_wfe.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const microzig = @import("microzig");
const hal = microzig.hal;
const cpu = microzig.cpu;
const board = microzig.board;
const peripherals = microzig.chip.peripherals;

const Pins = hal.pins.Pins(board.pin_config);
var pins: Pins = undefined;

pub const panic = microzig.panic;

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

comptime {
_ = microzig.export_startup();
}

pub const microzig_options: microzig.Options = .{
.overwrite_hal_interrupts = true,
.interrupts = .{
.SysTick = sys_tick_handler,
},
};

fn sys_tick_handler() callconv(cpu.riscv_calling_convention) void {
pins.led.toggle();
peripherals.PFIC.STK_SR.modify(.{ .CNTIF = 0 });
}

pub fn main() !void {
board.init();
pins = board.pin_config.apply();

// Configure SysTick for 1 Hz interrupt.
const PFIC = peripherals.PFIC;
// Reset configuration.
PFIC.STK_CTLR.raw = 0;
// Reset the Count Register.
PFIC.STK_CNTL.raw = 0;
// Set the compare register to trigger once per second.
PFIC.STK_CMPLR.raw = board.cpu_frequency - 1;
// Set the SysTick Configuration.
PFIC.STK_CTLR.modify(.{
.STE = 1,
.STIE = 1,
.STCLK = 1,
.STRE = 1,
});
// Clear the trigger state for the next interrupt.
PFIC.STK_SR.modify(.{ .CNTIF = 0 });

cpu.interrupt.enable(.SysTick);

while (true) {
cpu.wfe();
}
}
9 changes: 2 additions & 7 deletions port/wch/ch32v/src/cpus/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,11 @@ pub const interrupt = struct {
};

pub inline fn wfi() void {
PFIC.SCTLR.modify(.{ .WFITOWFE = 0 });
asm volatile ("wfi");
cpu_impl.wfi(microzig.chip);
}

pub inline fn wfe() void {
// We SETEVENT so the wfe immediately wakes and clears any pending events.
// This ensures the second one actually stays asleep.
PFIC.SCTLR.modify(.{ .WFITOWFE = 1 });
asm volatile ("wfi");
asm volatile ("wfi");
cpu_impl.wfe(microzig.chip);
}

pub fn unhandled() callconv(riscv_calling_convention) void {
Expand Down
24 changes: 24 additions & 0 deletions port/wch/ch32v/src/cpus/qingkev2-rv32ec.zig
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,30 @@ pub inline fn system_init(comptime chip: anytype) void {
RCC.CTLR.modify(.{ .HSITRIM = 0x10 });
}

/// Wait for interrupt. Clears WFITOWFE so the wfi instruction behaves as
/// a true wait-for-interrupt (not wait-for-event).
pub inline fn wfi(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .WFITOWFE = 0 });
asm volatile ("wfi");
}

/// Wait for event. Sets SETEVENT to clear any stale event latch, enables
/// WFITOWFE so the wfi instruction acts as wfe, then executes wfi twice:
/// the first clears the just-set event, the second sleeps until a real event.
///
/// NOTE: OpenWCH's CH32V003 reference implementation has a more complex WFE
/// that handles deep sleep (SLEEPDEEP) mode by manipulating EXTI.EVENR and
/// EXTI.INTENR registers, and the non-deep-sleep path sets SEVONPEND.
/// This simplified version does not handle those cases. See:
/// https://github.com/openwch/ch32v003/blob/main/EVT/EXAM/SRC/Core/core_riscv.h
pub inline fn wfe(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .SETEVENT = 1, .WFITOWFE = 1 });
asm volatile ("wfi");
asm volatile ("wfi");
}

pub const csr_types = struct {
pub const intsyscr = packed struct(u32) {
/// [0] Hardware Prologue/Epilogue (HPE) enable
Expand Down
19 changes: 19 additions & 0 deletions port/wch/ch32v/src/cpus/qingkev3-rv32imac.zig
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,25 @@ pub inline fn system_init(comptime chip: anytype) void {
});
}

/// Wait for interrupt. Clears WFITOWFE so the wfi instruction behaves as
/// a true wait-for-interrupt.
pub inline fn wfi(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .WFITOWFE = 0 });
asm volatile ("wfi");
}

/// Wait for event. Sets SETEVENT to clear any stale event latch, enables
/// WFITOWFE so the wfi instruction acts as wfe, then executes wfi twice:
/// the first clears the just-set event, the second sleeps until a real event.
/// Matches OpenWCH reference: _SEV() + _WFE() + _WFE().
pub inline fn wfe(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .SETEVENT = 1, .WFITOWFE = 1 });
asm volatile ("wfi");
asm volatile ("wfi");
}

pub const csr_types = struct {
pub const intsyscr = packed struct(u32) {
/// [0] Hardware stack enable
Expand Down
19 changes: 19 additions & 0 deletions port/wch/ch32v/src/cpus/qingkev4-rv32imac.zig
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,25 @@ pub inline fn system_init(comptime chip: anytype) void {
});
}

/// Wait for interrupt. Clears WFITOWFE so the wfi instruction behaves as
/// a true wait-for-interrupt.
pub inline fn wfi(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .WFITOWFE = 0 });
asm volatile ("wfi");
}

/// Wait for event. Sets SETEVENT to clear any stale event latch, enables
/// WFITOWFE so the wfi instruction acts as wfe, then executes wfi twice:
/// the first clears the just-set event, the second sleeps until a real event.
/// Matches OpenWCH reference: _SEV() + _WFE() + _WFE().
pub inline fn wfe(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .SETEVENT = 1, .WFITOWFE = 1 });
asm volatile ("wfi");
asm volatile ("wfi");
}

pub const csr_types = struct {
pub const intsyscr = packed struct(u32) {
/// [0] Hardware Prologue/Epilogue (HPE) enable
Expand Down
19 changes: 19 additions & 0 deletions port/wch/ch32v/src/cpus/qingkev4-rv32imacf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,25 @@ pub inline fn system_init(comptime chip: anytype) void {
RCC.CFGR2.raw = 0;
}

/// Wait for interrupt. Clears WFITOWFE so the wfi instruction behaves as
/// a true wait-for-interrupt.
pub inline fn wfi(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .WFITOWFE = 0 });
asm volatile ("wfi");
}

/// Wait for event. Sets SETEVENT to clear any stale event latch, enables
/// WFITOWFE so the wfi instruction acts as wfe, then executes wfi twice:
/// the first clears the just-set event, the second sleeps until a real event.
/// Matches OpenWCH reference: _SEV() + _WFE() + _WFE().
pub inline fn wfe(comptime chip: anytype) void {
const PFIC = chip.peripherals.PFIC;
PFIC.SCTLR.modify(.{ .SETEVENT = 1, .WFITOWFE = 1 });
asm volatile ("wfi");
asm volatile ("wfi");
}

pub const csr_types = struct {
pub const intsyscr = packed struct(u32) {
/// [0] Hardware Prologue/Epilogue (HPE) enable
Expand Down
Loading