diff --git a/port/raspberrypi/rp2xxx/src/hal/uart.zig b/port/raspberrypi/rp2xxx/src/hal/uart.zig index 359f55a69..6117eefa7 100644 --- a/port/raspberrypi/rp2xxx/src/hal/uart.zig +++ b/port/raspberrypi/rp2xxx/src/hal/uart.zig @@ -135,6 +135,8 @@ pub const instance = struct { } }; +pub const TimeFrontier = union(enum) { timeout_us: u64, deadline: mdf.time.Deadline }; + /// An API for interacting with the RP2040's UART driver. /// /// Note: Assumes proper GPIO configuration, does NOT configure GPIO pins. @@ -148,20 +150,28 @@ pub const UART = enum(u1) { pub const Writer = struct { uart: UART, - deadline: mdf.time.Deadline, + timeFrontier: TimeFrontier, interface: std.Io.Writer, + + pub fn set_deadline(self: *Writer, deadline: mdf.time.Deadline) void { + self.*.timeFrontier = TimeFrontier{.deadline = deadline}; + } }; pub const Reader = struct { uart: UART, - deadline: mdf.time.Deadline, + timeFrontier: TimeFrontier, interface: std.Io.Reader, + + pub fn set_deadline(self: *Reader, deadline: mdf.time.Deadline) void { + self.*.timeFrontier = TimeFrontier{.deadline = deadline}; + } }; - pub fn writer(uart: UART, deadline: mdf.time.Deadline, buffer: []u8) Writer { + pub fn writer(uart: UART, timeFrontier: TimeFrontier, buffer: []u8) Writer { return .{ .uart = uart, - .deadline = deadline, + .timeFrontier = timeFrontier, .interface = .{ .buffer = buffer, .vtable = &.{ @@ -171,10 +181,10 @@ pub const UART = enum(u1) { }; } - pub fn reader(uart: UART, deadline: mdf.time.Deadline, buffer: []u8) Reader { + pub fn reader(uart: UART, timeFrontier: TimeFrontier, buffer: []u8) Reader { return .{ .uart = uart, - .deadline = deadline, + .timeFrontier = timeFrontier, .interface = .{ .buffer = buffer, .seek = 0, @@ -190,18 +200,24 @@ pub const UART = enum(u1) { const uart_writer: *Writer = @alignCast(@fieldParentPtr("interface", w)); const uart = uart_writer.uart; + var deadline: mdf.time.Deadline = undefined; + switch (uart_writer.timeFrontier) { + .deadline => |d| deadline = d, + .timeout_us => |t| deadline = time.deadline_in_us(t) + } + // bytes from buffer are not included in count. - w.end -= uart.write_blocking(w.buffer[0..w.end], uart_writer.deadline) catch |err| switch (err) { + w.end -= uart.write_blocking(w.buffer[0..w.end], deadline) catch |err| switch (err) { error.Timeout => unreachable, }; assert(w.end == 0); var n: usize = 0; - n += uart.writev_blocking(data[0 .. data.len - 1], uart_writer.deadline) catch |err| switch (err) { + n += uart.writev_blocking(data[0 .. data.len - 1], deadline) catch |err| switch (err) { error.Timeout => unreachable, }; for (0..splat) |_| - n += uart.write_blocking(data[data.len - 1], uart_writer.deadline) catch |err| switch (err) { + n += uart.write_blocking(data[data.len - 1], deadline) catch |err| switch (err) { error.Timeout => unreachable, }; @@ -211,10 +227,17 @@ pub const UART = enum(u1) { fn stream(r: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { const uart_reader: *Reader = @alignCast(@fieldParentPtr("interface", r)); const uart = uart_reader.uart; + + var deadline: mdf.time.Deadline = undefined; + switch (uart_reader.timeFrontier) { + .deadline => |d| deadline = d, + .timeout_us => |t| deadline = time.deadline_in_us(t) + } + return switch (limit) { .nothing => 0, else => { - const b = uart.read_word_blocking(uart_reader.deadline) catch return error.ReadFailed; + const b = uart.read_word_blocking(deadline) catch return error.ReadFailed; try w.writeByte(b); return 1; }, @@ -559,7 +582,7 @@ var uart_logger: ?UART.Writer = null; /// .logFn = hal.uart.log, /// }; pub fn init_logger(uart: UART) void { - uart_logger = uart.writer(.no_deadline, &.{}); + uart_logger = uart.writer(.{.deadline = .no_deadline}, &.{}); uart_logger.?.interface.writeAll("\r\n================ STARTING NEW LOGGER ================\r\n") catch {}; }