wires

summary refs log tree commit diff
diff options
context:
space:
mode:
authorwires <wires@noreply.wires.systems>2025-10-06 06:07:10 -0400
committerwires <wires@noreply.wires.systems>2025-10-06 06:07:10 -0400
commit2379c573da65fd13d4e5bd16619b321744ac37fe (patch)
tree9552f19b902fe9626b6c9e644f131d7bad8bdd0e
parentget building on 0.15.1 (diff)
downloadzosimos-2379c573da65fd13d4e5bd16619b321744ac37fe.tar.gz
blocking serial messages
-rw-r--r--src/board.zig20
-rw-r--r--src/gpio.zig62
-rw-r--r--src/main.zig5
-rw-r--r--src/mini_uart.zig55
-rw-r--r--src/mmio.zig9
5 files changed, 151 insertions, 0 deletions
diff --git a/src/board.zig b/src/board.zig
new file mode 100644
index 0000000..c55fb99
--- /dev/null
+++ b/src/board.zig
@@ -0,0 +1,20 @@
+pub const PERIPHERAL_BASE = 0xfe000000;
+pub const AUX_BASE = PERIPHERAL_BASE + 0x215000;
+pub const AUX_IRQ = AUX_BASE;
+pub const AUX_ENABLE = AUX_BASE + 0x4;
+
+const Auxiliary = enum(u32) {
+    mini_uart = 1,
+    spi1 = 2,
+    spi2 = 4,
+};
+
+pub fn enableAux(aux: Auxiliary) void {
+    const mmio_ptr: *volatile u32 = @ptrFromInt(AUX_ENABLE);
+    mmio_ptr.* |= @intFromEnum(aux);
+}
+
+pub fn disableAux(aux: Auxiliary) void {
+    const mmio_ptr: *volatile u32 = @ptrFromInt(AUX_ENABLE);
+    mmio_ptr.* &= ~@intFromEnum(aux);
+}
diff --git a/src/gpio.zig b/src/gpio.zig
new file mode 100644
index 0000000..ba54394
--- /dev/null
+++ b/src/gpio.zig
@@ -0,0 +1,62 @@
+const PERIPHERAL_BASE = @import("board.zig").PERIPHERAL_BASE;
+
+const FSEL = PERIPHERAL_BASE + 0x200000;
+const SET = PERIPHERAL_BASE + 0x20001c;
+const CLR = PERIPHERAL_BASE + 0x200028;
+const PULL = PERIPHERAL_BASE + 0x2000e4;
+
+const MAX_PIN = 53;
+
+fn call(
+    pin: comptime_int,
+    value: u32,
+    base: comptime_int,
+    field_size: comptime_int,
+) void {
+    const field_mask: u32 = (1 << field_size) - 1;
+
+    if (pin > MAX_PIN) @compileError("invalid pin number");
+
+    const n_fields = 32 / field_size;
+    const reg = base + (pin / n_fields) * 4;
+    const shift = (pin % n_fields) * field_size;
+
+    const mmio_ptr: *volatile u32 = @ptrFromInt(reg);
+    var reg_val = mmio_ptr.*;
+    reg_val &= ~(field_mask << shift);
+    reg_val |= value << shift;
+    mmio_ptr.* = reg_val;
+}
+
+pub fn write(pin: comptime_int, value: bool) void {
+    if (value) {
+        call(pin, 1, SET, 1);
+    } else {
+        call(pin, 1, CLR, 1);
+    }
+}
+
+pub const Pull = enum {
+    none,
+    up,
+    down,
+};
+
+pub fn setPull(pin: comptime_int, pull: Pull) void {
+    call(pin, @intFromEnum(pull), PULL, 2);
+}
+
+pub const Function = enum {
+    input,
+    output,
+    alt5,
+    alt4,
+    alt0,
+    alt1,
+    alt2,
+    alt3,
+};
+
+pub fn setFunction(pin: comptime_int, function: Function) void {
+    call(pin, @intFromEnum(function), FSEL, 3);
+}
diff --git a/src/main.zig b/src/main.zig
index 64185aa..3ef9cad 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,3 +1,8 @@
+const mini_uart = @import("mini_uart.zig");
+
 export fn main() void {
+    mini_uart.enable();
+    mini_uart.writeString(" hello, world!\n");
+
     while (true) {}
 }
diff --git a/src/mini_uart.zig b/src/mini_uart.zig
new file mode 100644
index 0000000..265268d
--- /dev/null
+++ b/src/mini_uart.zig
@@ -0,0 +1,55 @@
+const std = @import("std");
+
+const board = @import("board.zig");
+const AUX_BASE = board.AUX_BASE;
+const AUX_ENABLE = board.AUX_ENABLE;
+
+const gpio = @import("gpio.zig");
+const mmio = @import("mmio.zig");
+
+const IO = AUX_BASE + 0x40;
+const IER = AUX_BASE + 0x44;
+const IIR = AUX_BASE + 0x48;
+const LCR = AUX_BASE + 0x4c;
+const MCR = AUX_BASE + 0x50;
+const LSR = AUX_BASE + 0x54;
+const MSR = AUX_BASE + 0x58;
+const SCRATCH = AUX_BASE + 0x5c;
+const CNTL = AUX_BASE + 0x60;
+const STAT = AUX_BASE + 0x64;
+const BAUD = AUX_BASE + 0x68;
+
+pub fn enable() void {
+    board.enableAux(.mini_uart);
+
+    gpio.setPull(14, .none);
+    gpio.setFunction(14, .alt5);
+
+    gpio.setPull(15, .none);
+    gpio.setFunction(15, .alt5);
+
+    mmio.write(IER, 0); // disable interrupts
+    mmio.write(IIR, 6); // clear FIFOs
+    mmio.write(LCR, 3); // 8 bit mode
+    mmio.write(BAUD, baudRegVal(115200));
+
+    mmio.write(CNTL, 0x3);
+}
+
+fn baudRegVal(baud: comptime_int) comptime_int {
+    return 500000000 / (baud * 8) - 1;
+}
+
+fn writeByte(b: u8) void {
+    while ((mmio.read(LSR) & 0x10) != 0) {}
+    mmio.write(IO, b);
+}
+
+pub fn writeString(str: []const u8) void {
+    for (str) |b| {
+        if (b == '\n') {
+            writeByte('\r');
+        }
+        writeByte(b);
+    }
+}
diff --git a/src/mmio.zig b/src/mmio.zig
new file mode 100644
index 0000000..7233733
--- /dev/null
+++ b/src/mmio.zig
@@ -0,0 +1,9 @@
+pub fn write(reg: comptime_int, val: u32) void {
+    const mmio_ptr: *volatile u32 = @ptrFromInt(reg);
+    mmio_ptr.* = val;
+}
+
+pub fn read(reg: comptime_int) u32 {
+    const mmio_ptr: *volatile u32 = @ptrFromInt(reg);
+    return mmio_ptr.*;
+}