diff --git a/examples/raspberrypi/rp2xxx/src/uart_echo.zig b/examples/raspberrypi/rp2xxx/src/uart_echo.zig index 35f1b9ad7..ae817b4ad 100644 --- a/examples/raspberrypi/rp2xxx/src/uart_echo.zig +++ b/examples/raspberrypi/rp2xxx/src/uart_echo.zig @@ -38,7 +38,7 @@ pub fn main() !void { continue; }; - //tries to write one byte with 100ms timeout + // Try to write one byte with 100ms timeout _ = uart.write_blocking(&data, time.deadline_in_ms(100)) catch { uart.clear_errors(); }; diff --git a/examples/wch/ch32v/build.zig b/examples/wch/ch32v/build.zig index c8f28688b..995f2de11 100644 --- a/examples/wch/ch32v/build.zig +++ b/examples/wch/ch32v/build.zig @@ -37,11 +37,14 @@ pub fn build(b: *std.Build) void { .{ .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.nano_ch32v203, .name = "nano_ch32v203_uart_echo", .file = "src/uart_echo.zig" }, + .{ .target = mb.ports.ch32v.boards.ch32v203.nano_ch32v203, .name = "nano_ch32v203_uart_log", .file = "src/uart_log.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.nano_ch32v203, .name = "nano_ch32v203_usb_cdc", .file = "src/usb_cdc.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.suzuduino_uno_v1b, .name = "suzuduino_blinky", .file = "src/board_blinky.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.suzuduino_uno_v1b, .name = "suzuduino_usb_cdc", .file = "src/usb_cdc.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" }, + .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_uart_echo", .file = "src/uart_echo.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_uart_log", .file = "src/uart_log.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_i2c_bus_scan", .file = "src/i2c_bus_scan.zig" }, .{ .target = mb.ports.ch32v.boards.ch32v203.lana_tny, .name = "lana_tny_i2c_eeprom", .file = "src/i2c_eeprom.zig" }, diff --git a/examples/wch/ch32v/src/uart_echo.zig b/examples/wch/ch32v/src/uart_echo.zig new file mode 100644 index 000000000..d41298496 --- /dev/null +++ b/examples/wch/ch32v/src/uart_echo.zig @@ -0,0 +1,31 @@ +const microzig = @import("microzig"); + +const hal = microzig.hal; +const board = microzig.board; +const time = hal.time; + +const uart = board.uart_setup; + +pub const panic = microzig.panic; + +pub const std_options = microzig.std_options(.{}); + +comptime { + _ = microzig.export_startup(); +} + +pub fn main() !void { + board.init(); + + uart.apply(.{ .baud_rate = 115200 }); + + const usart = uart.instance; + + var data: [1]u8 = .{0}; + while (true) { + usart.read_blocking(&data, .no_deadline) catch { + continue; + }; + _ = usart.write_blocking(&data, time.deadline_in_ms(100)) catch {}; + } +} diff --git a/examples/wch/ch32v/src/uart_log.zig b/examples/wch/ch32v/src/uart_log.zig index 3d5328ac9..09b1ba843 100644 --- a/examples/wch/ch32v/src/uart_log.zig +++ b/examples/wch/ch32v/src/uart_log.zig @@ -4,7 +4,7 @@ const hal = microzig.hal; const board = microzig.board; const time = hal.time; -const uart_cfg: hal.usart.UartConfig = if (@hasDecl(board, "uart_config")) board.uart_config else .{}; +const uart_setup = board.uart_setup; pub const panic = microzig.panic; @@ -20,8 +20,8 @@ comptime { pub fn main() !void { board.init(); - hal.usart.setup_uart(uart_cfg); - hal.usart.init_logger(uart_cfg.instance); + uart_setup.apply(.{ .baud_rate = 115200 }); + hal.usart.init_logger(uart_setup.instance); var i: u32 = 0; while (true) : (i += 1) { diff --git a/port/wch/ch32v/src/boards/LANA_TNY.zig b/port/wch/ch32v/src/boards/LANA_TNY.zig index 832767d1e..96333ee6a 100644 --- a/port/wch/ch32v/src/boards/LANA_TNY.zig +++ b/port/wch/ch32v/src/boards/LANA_TNY.zig @@ -21,9 +21,10 @@ pub fn init() void { } /// Default UART: USART2 on PA2 (exposed on the board header) -pub const uart_config: ch32v.usart.UartConfig = .{ +pub const uart_setup: ch32v.usart.Setup = .{ .instance = .USART2, .tx_pin = ch32v.gpio.Pin.init(0, 2), // PA2 + .rx_pin = ch32v.gpio.Pin.init(0, 3), // PA3 }; pub const pin_config = ch32v.pins.GlobalConfiguration{ diff --git a/port/wch/ch32v/src/boards/nanoCH32V203.zig b/port/wch/ch32v/src/boards/nanoCH32V203.zig index c69aa5481..5a1109406 100644 --- a/port/wch/ch32v/src/boards/nanoCH32V203.zig +++ b/port/wch/ch32v/src/boards/nanoCH32V203.zig @@ -25,7 +25,11 @@ pub fn init() void { } /// Default UART: USART1 on PA9 -pub const uart_config: ch32v.usart.UartConfig = .{}; +pub const uart_setup: ch32v.usart.Setup = .{ + .instance = .USART1, + .tx_pin = ch32v.gpio.Pin.init(0, 9), // PA9 + .rx_pin = ch32v.gpio.Pin.init(0, 10), // PA10 +}; pub const pin_config = ch32v.pins.GlobalConfiguration{ .GPIOA = .{ diff --git a/port/wch/ch32v/src/hals/time.zig b/port/wch/ch32v/src/hals/time.zig index e416616b0..1f14767d4 100644 --- a/port/wch/ch32v/src/hals/time.zig +++ b/port/wch/ch32v/src/hals/time.zig @@ -176,3 +176,11 @@ pub fn delay_us(us: u32) void { asm volatile ("" ::: .{ .memory = true }); } } + +pub fn deadline_in_ms(time_ms: u32) microzig.drivers.time.Deadline { + return .init_relative(get_time_since_boot(), .from_ms(time_ms)); +} + +pub fn deadline_in_us(time_us: u64) microzig.drivers.time.Deadline { + return .init_relative(get_time_since_boot(), .from_us(time_us)); +} diff --git a/port/wch/ch32v/src/hals/usart.zig b/port/wch/ch32v/src/hals/usart.zig index d10cb4282..c3118cee9 100644 --- a/port/wch/ch32v/src/hals/usart.zig +++ b/port/wch/ch32v/src/hals/usart.zig @@ -92,24 +92,26 @@ pub const ReceiveError = error{ const gpio = hal.gpio; -/// Configuration for board-level UART defaults. -/// Boards export a `uart_config` const of this type with their preferred -/// USART instance, TX pin, and serial settings. Examples can use these -/// defaults directly or construct their own `UartConfig`. -pub const UartConfig = struct { - instance: USART = .USART1, - tx_pin: gpio.Pin = gpio.Pin.init(0, 9), // PA9 (USART1 default TX) - config: Config = .{ .baud_rate = 115200 }, +/// Physical-layer UART setup: which USART instance and pins to use. +/// Boards export a `uart_setup` const of this type. Application-level +/// settings (baud rate, parity, etc.) are passed separately via `Config`. +pub const Setup = struct { + instance: USART, + tx_pin: ?gpio.Pin = null, + rx_pin: ?gpio.Pin = null, + + /// Apply settings: configure whichever pins are present, then apply + /// the USART peripheral config (clock, baud rate, etc.). + pub fn apply(comptime self: Setup, comptime config: Config) void { + if (self.tx_pin) |tx| tx.configure_alternate_function(.push_pull, .max_50MHz); + if (self.rx_pin) |rx| { + rx.enable_clock(); + rx.set_input_mode(.floating); + } + self.instance.apply(config); + } }; -/// Configure a UART from a `UartConfig`: sets up the TX pin as alternate -/// function push-pull, then applies the USART peripheral configuration -/// (clock enable, AFIO remap, baud rate, etc.). -pub fn setup_uart(comptime cfg: UartConfig) void { - cfg.tx_pin.configure_alternate_function(.push_pull, .max_50MHz); - cfg.instance.apply(cfg.config); -} - pub const instance = struct { pub const USART1: USART = .USART1; pub const USART2: USART = .USART2;