diff options
| author | wires <wires@noreply.wires.systems> | 2025-10-06 06:07:10 -0400 |
|---|---|---|
| committer | wires <wires@noreply.wires.systems> | 2025-10-06 06:07:10 -0400 |
| commit | 2379c573da65fd13d4e5bd16619b321744ac37fe (patch) | |
| tree | 9552f19b902fe9626b6c9e644f131d7bad8bdd0e | |
| parent | get building on 0.15.1 (diff) | |
| download | zosimos-2379c573da65fd13d4e5bd16619b321744ac37fe.tar.gz | |
blocking serial messages
| -rw-r--r-- | src/board.zig | 20 | ||||
| -rw-r--r-- | src/gpio.zig | 62 | ||||
| -rw-r--r-- | src/main.zig | 5 | ||||
| -rw-r--r-- | src/mini_uart.zig | 55 | ||||
| -rw-r--r-- | src/mmio.zig | 9 |
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.*; +} |