sylveos

Toy Operating System
Log | Files | Refs

commit 09706d2cb7559581198b024d80e25c83fec32ee2
parent c80b2f6fe21d52e11336b80d92ddfd336758bd37
Author: Sylvia Ivory <git@sivory.net>
Date:   Tue, 20 Jan 2026 18:07:33 -0800

Fix UART

Diffstat:
Mbuild.zig | 2+-
Mpi/mem.zig | 5++---
Mpi/root.zig | 1+
Msrc/devices/gpio.zig | 2--
Msrc/devices/mini-uart.zig | 55+++++++++++++++++++++++++++----------------------------
Mstart.s | 14--------------
6 files changed, 31 insertions(+), 48 deletions(-)

diff --git a/build.zig b/build.zig @@ -68,7 +68,7 @@ fn add_exe_real(exe_name: []const u8, path: std.Build.LazyPath, b: *std.Build) ! const boot = b.createModule(.{ .root_source_file = path, .target = b.resolveTargetQuery(target), - .optimize = .ReleaseSafe, + .optimize = .ReleaseSmall, .unwind_tables = .none, .single_threaded = true, .error_tracing = false, diff --git a/pi/mem.zig b/pi/mem.zig @@ -25,13 +25,12 @@ const BarrierKind = enum { const Operation = enum { Read, Write, - General, }; pub inline fn barrier(op: Operation) void { switch (op) { .Write => dmb(), - .General | .Read => dsb(), + .Read => dsb(), } } @@ -52,7 +51,7 @@ pub inline fn put_u32_barrier( } pub inline fn get_u32(address: *u32) u32 { - return asm volatile ("str %[result], [%[address]]" + return asm volatile ("ldr %[result], [%[address]]" : [result] "=r" (-> u32), : [address] "r" (address), ); diff --git a/pi/root.zig b/pi/root.zig @@ -1 +1,2 @@ pub const mem = @import("./mem.zig"); +pub extern fn nop() void; diff --git a/src/devices/gpio.zig b/src/devices/gpio.zig @@ -120,8 +120,6 @@ fn wait(count: usize) void { var c = count; while (c != 0) { c -= 1; - // does this cook us? - std.atomic.spinLoopHint(); } } diff --git a/src/devices/mini-uart.zig b/src/devices/mini-uart.zig @@ -9,17 +9,17 @@ pub const Error = error{AlreadyInitialized} || gpio.Error; // Page 8: Auxiliary peripherals Register Map const BASE_ADDRESS: usize = mem.BASE_ADDRESS + 0x0021_5000; const AUX_ENABLES: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_IO_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_IER_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_IIR_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_LCR_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_MCR_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_LSR_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_MSR_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_SCRATCH: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_CNTL_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_STAT_REG: usize = BASE_ADDRESS + 0x0004; -const AUX_MU_BAUD_REG: usize = BASE_ADDRESS + 0x0004; +const AUX_MU_IO_REG: usize = BASE_ADDRESS + 0x0040; +const AUX_MU_IER_REG: usize = BASE_ADDRESS + 0x0044; +const AUX_MU_IIR_REG: usize = BASE_ADDRESS + 0x0048; +const AUX_MU_LCR_REG: usize = BASE_ADDRESS + 0x004C; +const AUX_MU_MCR_REG: usize = BASE_ADDRESS + 0x0050; +const AUX_MU_LSR_REG: usize = BASE_ADDRESS + 0x0054; +const AUX_MU_MSR_REG: usize = BASE_ADDRESS + 0x0058; +const AUX_MU_SCRATCH: usize = BASE_ADDRESS + 0x005C; +const AUX_MU_CNTL_REG: usize = BASE_ADDRESS + 0x0060; +const AUX_MU_STAT_REG: usize = BASE_ADDRESS + 0x0064; +const AUX_MU_BAUD_REG: usize = BASE_ADDRESS + 0x0068; const CLOCK_FREQ = 250_000_000; @@ -34,20 +34,20 @@ const RxPin = enum(u8) { Gpio37 = 37, }; -var is_initialized = false; +// var is_initialized = false; pub fn initialize(baud: u32, tx_pin: TxPin, rx_pin: RxPin) Error!void { - if (is_initialized) return Error.AlreadyInitialized; + // if (is_initialized) return Error.AlreadyInitialized; // Set GPIO pins first (as specified by manual) // Page 102 specifies which alt mode const tx_fn: gpio.FunctionSelect = switch (tx_pin) { - .Gpio14 => .alt_fn_0, + .Gpio14 => .alt_fn_5, .Gpio32 => .alt_fn_3, .Gpio36 => .alt_fn_2, }; const rx_fn: gpio.FunctionSelect = switch (rx_pin) { - .Gpio15 => .alt_fn_0, + .Gpio15 => .alt_fn_5, .Gpio33 => .alt_fn_3, .Gpio37 => .alt_fn_2, }; @@ -75,7 +75,8 @@ pub fn initialize(baud: u32, tx_pin: TxPin, rx_pin: RxPin) Error!void { // Set data size to 8 bits // Page 14: AUX_MU_LCR_REG Register // When bit 0 is 1, UART is in 8-bit mode, else 7-bit - mem.put_u32(@ptrFromInt(AUX_MU_LCR_REG), 1); + // mem.put_u32(@ptrFromInt(AUX_MU_LCR_REG), 1); + mem.put_u32(@ptrFromInt(AUX_MU_LCR_REG), 3); // Put RTS high (indicate request to send) // Page 14: AUX_MU_MCR_REG Register @@ -85,52 +86,50 @@ pub fn initialize(baud: u32, tx_pin: TxPin, rx_pin: RxPin) Error!void { // Clear FIFO // Page 12: AUX_MU_IER_REG Register (yes the page is mislabeled) // When bit 1/2 is 1, receive/transmit will be cleared - mem.put_u32(@ptrFromInt(AUX_MU_IIR_REG), 0x6); + mem.put_u32(@ptrFromInt(AUX_MU_IIR_REG), 0x06); + // mem.put_u32(@ptrFromInt(AUX_MU_IIR_REG), 0xC6); // Set baud rate // Page 11: 2.2.1 Mini UART Implementation Details // The baudrate formula is given as (system_clock_freq)/(8 * (baudrate_reg + 1)) - mem.put_u32(@ptrFromInt(AUX_MU_BAUD_REG), CLOCK_FREQ / (8 * (baud + 1))); + mem.put_u32(@ptrFromInt(AUX_MU_BAUD_REG), CLOCK_FREQ / (8 * baud) - 1); // Enable RX/TX again // Page 17: AUX_MU_CNTL_REG Register // When bit 0/1 is 1, UART receiver/transmitter is enabled mem.put_u32(@ptrFromInt(AUX_MU_CNTL_REG), 0x3); + // mem.put_u32(@ptrFromInt(AUX_MU_CNTL_REG), 2); - is_initialized = true; + // is_initialized = true; } fn can_write() bool { // Check if FIFO can accept data // Page 15: AUX_MU_LSR_REG Register // Bit 5 is set when FIFO can accept at least 1 byte - return mem.get_u32(@ptrFromInt(AUX_MU_LSR_REG)) & 0x20 != 0; + return (mem.get_u32(@ptrFromInt(AUX_MU_LSR_REG)) & 0x20) != 0; } fn can_read() bool { // Check if FIFO has data // Page 15: AUX_MU_LSR_REG Register // Bit 1 is set when FIFO holds at least 1 byte - return mem.get_u32(@ptrFromInt(AUX_MU_LSR_REG)) & 1; + return (mem.get_u32(@ptrFromInt(AUX_MU_LSR_REG)) & 1) == 1; } pub fn write_byte(byte: u8) void { // TODO; support timeout - while (!can_write()) { - std.atomic.spinLoopHint(); - } + while (!can_write()) {} // Write into FIFO // Page 11: AUX_MU_IO_REG Register // Bits 7:0 holds data from the FIFO - mem.put_u32(@ptrFromInt(AUX_MU_IO_REG), @as(u32, byte)); + mem.put_u32(@ptrFromInt(AUX_MU_IO_REG), @as(u32, byte) & 0xFF); } pub fn read_byte() u8 { // TODO; support timeout - while (!can_read()) { - std.atomic.spinLoopHint(); - } + while (!can_read()) {} // Read from FIFO // Page 11: AUX_MU_IO_REG Register diff --git a/start.s b/start.s @@ -11,17 +11,3 @@ _start: .align 8 nop: bx lr - -.global put_u32 -.type put_u32, function -.align 8 -put_u32: - str r1,[r0] - bx lr - -.global get_u32 -.type get_u32, function -.align 8 -get_u32: - ldr r0,[r0] - bx lr