diff --git a/core/src/cpus/cortex_m.zig b/core/src/cpus/cortex_m.zig index 2d1acf289..0650f6ed4 100644 --- a/core/src/cpus/cortex_m.zig +++ b/core/src/cpus/cortex_m.zig @@ -107,6 +107,46 @@ pub const Exception = blk: { break :blk @Enum(u4, .exhaustive, &field_names, &field_values); }; +// Maybe consolidate this and `exception_ppb_pending_field`? +// Also, could be better to check for field presence in ppb +// instead of hard-coding which processors have which faults. +pub fn exception_ppb_enable_field(comptime excpt: Exception) []const u8 { + return sw: switch (cortex_m) { + .cortex_m3, .cortex_m4, .cortex_m7 => switch (excpt) { + .UsageFault => "USGFAULTENA", + .BusFault => "BUSFAULTENA", + .MemManageFault => "MEMFAULTENA", + else => @compileError("not supported on this platform"), + }, + .cortex_m33, .cortex_m55 => switch (excpt) { + .SecureFault => "SECUREFAULTENA", + else => continue :sw .cortex_m3, + }, + else => @compileError("not supported on this platform"), + }; +} + +pub fn exception_ppb_pending_field(comptime excpt: Exception) []const u8 { + return sw: switch (cortex_m) { + .cortex_m0plus => switch (excpt) { + .SVCALL => "SVCALLPENDED", + else => @compileError("not supported on this platform"), + }, + .cortex_m3, .cortex_m4, .cortex_m7 => switch (excpt) { + .UsageFault => "USGFAULTPENDED", + .BusFault => "BUSFAULTPENDED", + .MemManageFault => "MEMFAULTPENDED", + else => continue :sw .cortex_m0plus, + }, + .cortex_m33, .cortex_m55 => switch (excpt) { + .SecureFault => "SECUREFAULTPENDED", + .HardFault => "HARDFAULTPENDED", + else => continue :sw .cortex_m3, + }, + else => @compileError("not supported on this platform"), + }; +} + pub const interrupt = struct { /// The priority of an interrupt. /// Cortex-M uses a reversed priority scheme so the lowest priority is 15 and the highest is 0. @@ -147,181 +187,27 @@ pub const interrupt = struct { }; pub fn is_enabled(comptime excpt: Exception) bool { - switch (cortex_m) { - .cortex_m3, .cortex_m4, .cortex_m7 => { - const raw = ppb.SHCSR.raw; - switch (excpt) { - .UsageFault => return (raw & 0x0004_0000) != 0, - .BusFault => return (raw & 0x0002_0000) != 0, - .MemManageFault => return (raw & 0x0001_0000) != 0, - else => @compileError("not supported on this platform"), - } - }, - .cortex_m33, - .cortex_m55, - => { - const raw = ppb.SHCSR.raw; - switch (excpt) { - .SecureFault => return (raw & 0x0008_0000) != 0, - .UsageFault => return (raw & 0x0004_0000) != 0, - .BusFault => return (raw & 0x0002_0000) != 0, - .MemManageFault => return (raw & 0x0001_0000) != 0, - else => @compileError("not supported on this platform"), - } - }, - else => @compileError("not supported on this platform"), - } + return @field(ppb.SHCSR.read(), exception_ppb_enable_field(excpt)) != 0; } pub fn enable(comptime excpt: Exception) void { - switch (cortex_m) { - .cortex_m3, .cortex_m4, .cortex_m7 => { - switch (excpt) { - .UsageFault => ppb.SHCSR.raw |= 0x0004_0000, - .BusFault => ppb.SHCSR.raw |= 0x0002_0000, - .MemManageFault => ppb.SHCSR.raw |= 0x0001_0000, - else => @compileError("not supported on this platform"), - } - }, - .cortex_m33, - .cortex_m55, - => { - switch (excpt) { - .SecureFault => ppb.SHCSR.raw |= 0x0008_0000, - .UsageFault => ppb.SHCSR.raw |= 0x0004_0000, - .BusFault => ppb.SHCSR.raw |= 0x0002_0000, - .MemManageFault => ppb.SHCSR.raw |= 0x0001_0000, - else => @compileError("not supported on this platform"), - } - }, - else => @compileError("not supported on this platform"), - } + return ppb.SHCSR.modify_one(exception_ppb_enable_field(excpt), 1); } pub fn disable(comptime excpt: Exception) void { - switch (cortex_m) { - .cortex_m3, .cortex_m4, .cortex_m7 => { - switch (excpt) { - .UsageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0004_0000), - .BusFault => ppb.SHCSR.raw &= ~@as(u32, 0x0002_0000), - .MemManageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0001_0000), - else => @compileError("not supported on this platform"), - } - }, - .cortex_m33, - .cortex_m55, - => { - switch (excpt) { - .SecureFault => ppb.SHCSR.raw &= ~@as(u32, 0x0008_0000), - .UsageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0004_0000), - .BusFault => ppb.SHCSR.raw &= ~@as(u32, 0x0002_0000), - .MemManageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0001_0000), - else => @compileError("not supported on this platform"), - } - }, - else => @compileError("not supported on this platform"), - } + return ppb.SHCSR.modify_one(exception_ppb_enable_field(excpt), 0); } pub fn is_pending(comptime excpt: Exception) bool { - switch (cortex_m) { - .cortex_m0plus, - => { - if (excpt == .SVCALL) return (ppb.SHCSR.raw & 0x0000_8000) != 0; - @compileError("not supported on this platform"); - }, - .cortex_m3, .cortex_m4, .cortex_m7 => { - const raw = ppb.SHCSR.raw; - switch (excpt) { - .SVCall => return (raw & 0x0000_8000) != 0, - .BusFault => return (raw & 0x0000_4000) != 0, - .MemManageFault => return (raw & 0x0000_2000) != 0, - .UsageFault => return (raw & 0x0000_1000) != 0, - else => @compileError("not supported on this platform"), - } - }, - .cortex_m33, - .cortex_m55, - => { - const raw = ppb.SHCSR.raw; - switch (excpt) { - .HardFault => return (raw & 0x0020_0000) != 0, - .SecureFault => return (raw & 0x0010_0000) != 0, - .SVCall => return (raw & 0x0000_8000) != 0, - .BusFault => return (raw & 0x0000_4000) != 0, - .MemManageFault => return (raw & 0x0000_2000) != 0, - .UsageFault => return (raw & 0x0000_1000) != 0, - else => @compileError("not supported on this platform"), - } - }, - else => @compileError("not supported on this platform"), - } + return @field(ppb.SHCSR.read(), exception_ppb_pending_field(excpt)) != 0; } pub fn set_pending(comptime excpt: Exception) void { - switch (cortex_m) { - .cortex_m0plus, - => { - if (excpt == .SVCALL) ppb.SHCSR.raw |= 0x0000_8000; - @compileError("not supported on this platform"); - }, - .cortex_m3, .cortex_m4, .cortex_m7 => { - switch (excpt) { - .SVCall => ppb.SHCSR.raw |= 0x0000_8000, - .BusFault => ppb.SHCSR.raw |= 0x0000_4000, - .MemManageFault => ppb.SHCSR.raw |= 0x0000_2000, - .UsageFault => ppb.SHCSR.raw |= 0x0000_1000, - else => @compileError("not supported on this platform"), - } - }, - .cortex_m33, - .cortex_m55, - => { - switch (excpt) { - .HardFault => ppb.SHCSR.raw |= 0x0020_0000, - .SecureFault => ppb.SHCSR.raw |= 0x0010_0000, - .SVCall => ppb.SHCSR.raw |= 0x0000_8000, - .BusFault => ppb.SHCSR.raw |= 0x0000_4000, - .MemManageFault => ppb.SHCSR.raw |= 0x0000_2000, - .UsageFault => ppb.SHCSR.raw |= 0x0000_1000, - else => @compileError("not supported on this platform"), - } - }, - else => @compileError("not supported on this platform"), - } + return ppb.SHCSR.modify_one(exception_ppb_pending_field(excpt), 1); } pub fn clear_pending(comptime excpt: Exception) void { - switch (cortex_m) { - .cortex_m0plus, - => { - if (excpt == .SVCALL) ppb.SHCSR.raw &= ~@as(u32, 0x0000_8000); - @compileError("not supported on this platform"); - }, - .cortex_m3, .cortex_m4, .cortex_m7 => { - switch (excpt) { - .SVCall => ppb.SHCSR.raw &= ~@as(u32, 0x0000_8000), - .BusFault => ppb.SHCSR.raw &= ~@as(u32, 0x0000_4000), - .MemManageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0000_2000), - .UsageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0000_1000), - else => @compileError("not supported on this platform"), - } - }, - .cortex_m33, - .cortex_m55, - => { - switch (excpt) { - .HardFault => ppb.SHCSR.raw &= ~@as(u32, 0x0020_0000), - .SecureFault => ppb.SHCSR.raw &= ~@as(u32, 0x0010_0000), - .SVCall => ppb.SHCSR.raw &= ~@as(u32, 0x0000_8000), - .BusFault => ppb.SHCSR.raw &= ~@as(u32, 0x0000_4000), - .MemManageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0000_2000), - .UsageFault => ppb.SHCSR.raw &= ~@as(u32, 0x0000_1000), - else => @compileError("not supported on this platform"), - } - }, - else => @compileError("not supported on this platform"), - } + return ppb.SHCSR.modify_one(exception_ppb_pending_field(excpt), 0); } /// Note: Although the Priority values are 0 - 15, some platforms may @@ -334,37 +220,28 @@ pub const interrupt = struct { // The any SHPRn register which is unavailable on a platform will // not be accessed as no matching `Exception` will be exist. - switch (num) { - 0 => { - @compileError("Cannot set the priority for the exception"); - }, - 1 => { - ppb.SHPR1.raw &= ~(@as(u32, 0xFF) << shift); - ppb.SHPR1.raw |= @as(u32, @intFromEnum(priority)) << shift; - }, - 2 => { - ppb.SHPR2.raw &= ~(@as(u32, 0xFF) << shift); - ppb.SHPR2.raw |= @as(u32, @intFromEnum(priority)) << shift; - }, - 3 => { - ppb.SHPR3.raw &= ~(@as(u32, 0xFF) << shift); - ppb.SHPR3.raw |= @as(u32, @intFromEnum(priority)) << shift; - }, - } + const reg = switch (num) { + 0 => @compileError("Cannot set the priority for the exception"), + 1 => &ppb.SHPR1, + 2 => &ppb.SHPR2, + 3 => &ppb.SHPR3, + }; + + reg.raw.modify(@as(u32, 0xFF) << shift, @as(u32, @intFromEnum(priority)) << shift); } pub fn get_priority(comptime excpt: Exception) Priority { const num: u2 = @intCast(@intFromEnum(excpt) / 4); const shift: u5 = @as(u5, @intCast(@intFromEnum(excpt))) % 4 * 8; - const raw: u8 = (switch (num) { + const reg: u8 = (switch (num) { 0 => @compileError("Cannot get the priority for the exception"), - 1 => ppb.SHPR1.raw, - 2 => ppb.SHPR2.raw, - 3 => ppb.SHPR3.raw, + 1 => &ppb.SHPR1, + 2 => &ppb.SHPR2, + 3 => &ppb.SHPR3, } >> shift) & 0xFF; - return @enumFromInt(raw); + return @enumFromInt(reg.raw.read()); } }; diff --git a/core/src/cpus/cortex_m/m7_utils.zig b/core/src/cpus/cortex_m/m7_utils.zig index acfbdab44..a997f0b43 100644 --- a/core/src/cpus/cortex_m/m7_utils.zig +++ b/core/src/cpus/cortex_m/m7_utils.zig @@ -48,7 +48,7 @@ pub fn write_byte_itm(ch: u8, stim_port: u5) void { while (peripherals.itm.STIM[stim_port].read().READ.FIFOREADY == 0) {} // Write character - const stim: *volatile u8 = @ptrCast(&peripherals.itm.STIM[stim_port].raw); + const stim: *volatile u8 = @ptrCast(&peripherals.itm.STIM[stim_port]); stim.* = ch; } diff --git a/core/src/mmio.zig b/core/src/mmio.zig index 641d75a50..5394d22aa 100644 --- a/core/src/mmio.zig +++ b/core/src/mmio.zig @@ -1,46 +1,133 @@ const std = @import("std"); -const assert = std.debug.assert; - -pub fn Mmio(comptime Packed: type) type { - @setEvalBranchQuota(2_000); - - const size = @bitSizeOf(Packed); - if ((size % 8) != 0) - @compileError("size must be divisible by 8!"); - - if (!std.math.isPowerOfTwo(size / 8)) - @compileError("size must encode a power of two number of bytes!"); - - const Int = @Int(.unsigned, size); - - if (@sizeOf(Packed) != (size / 8)) - @compileError(std.fmt.comptimePrint("Int and Packed must have the same size!, they are {} and {} bytes respectively", .{ size / 8, @sizeOf(Packed) })); - - return packed struct(Int) { - const Self = @This(); - - raw: Int, - - pub const underlying_type = Packed; +const FieldAttributes = std.builtin.Type.Struct.FieldAttributes; + +pub fn MmioRaw(T: type) type { + @setEvalBranchQuota(10_000); + + if (@typeInfo(T) != .int) + @compileError("Expected an integer, got " ++ @typeName(T)); + + if (@bitSizeOf(T) != @sizeOf(T) * 8) + @compileError(std.fmt.comptimePrint( + "Bitsize of {s} ({}) must be 8 times its size ({}).", + .{ @typeName(T), @bitSizeOf(T), @sizeOf(T) }, + )); + + if (!std.math.isPowerOfTwo(@sizeOf(T))) + @compileError(std.fmt.comptimePrint( + "Size of {s} ({}) must be a power of two.", + .{ @typeName(T), @bitSizeOf(T), @sizeOf(T) }, + )); + + return extern struct { + /// Backing integer + pub const Int = T; + /// Naturally aligned volatile pointer + pub const MmioPtr = *align(@sizeOf(Int)) volatile @This(); + /// MmioRaw of the backing integer + pub const Raw = MmioBacking(Int); + + /// Unstable API. Use read/write functions instead. + raw: Raw, + }; +} - pub inline fn read(addr: *volatile Self) Packed { - return @bitCast(addr.raw); +pub fn Mmio(T: type) type { + @setEvalBranchQuota(10_000); + + const info = @typeInfo(T); + if (info != .@"struct" or info.@"struct".layout != .@"packed") + @compileError("Expected a packed struct, got " ++ @typeName(T)); + + if (@bitSizeOf(T) != @sizeOf(T) * 8) + @compileError(std.fmt.comptimePrint( + "Bitsize of {s} ({}) must be 8 times its size ({}).", + .{ @typeName(T), @bitSizeOf(T), @sizeOf(T) }, + )); + + if (!std.math.isPowerOfTwo(@sizeOf(T))) + @compileError(std.fmt.comptimePrint( + "Size of {s} ({}) must be a power of two.", + .{ @typeName(T), @bitSizeOf(T), @sizeOf(T) }, + )); + + return extern struct { + const field_names = info.@"struct".field_names; + const field_types = info.@"struct".field_types[0..field_names.len].*; + + /// Struct defining register field layout + pub const Fields = T; + /// Backing integer + pub const Int = @Int(.unsigned, @bitSizeOf(Fields)); + /// MmioRaw of the backing integer + pub const Raw = MmioBacking(Int); + /// Naturally aligned volatile pointer + pub const MmioPtr = *align(@sizeOf(Int)) volatile @This(); + /// Like `Fields`, but all fields are optional and default to `null` + pub const FieldsOpt = @Struct( + .auto, + null, + field_names, + blk: { + var ret: [field_names.len]type = undefined; + for (0..field_names.len) |i| + ret[i] = ?field_types[i]; + break :blk &ret; + }, + blk: { + var ret: [field_names.len]FieldAttributes = undefined; + for (0..field_names.len) |i| { + const default: ?field_types[i] = null; + ret[i] = .{ .default_value_ptr = &default }; + } + break :blk &ret; + }, + ); + /// Identical struct to `Fields`, but all fields without + /// default values are given a default value of zero. + pub const FieldsZero = @Struct( + .@"packed", + Int, + field_names, + &field_types, + blk: { + var ret: [field_names.len]FieldAttributes = undefined; + for (0..field_names.len) |i| { + ret[i] = info.@"struct".field_attrs[i]; + if (ret[i].default_value_ptr == null) { + const default = std.mem.zeroes(field_types[i]); + ret[i].default_value_ptr = &default; + } + } + break :blk &ret; + }, + ); + + raw: Raw, + + pub inline fn read(mmio: MmioPtr) Fields { + return @bitCast(mmio.raw.read()); } - pub inline fn write(addr: *volatile Self, val: Packed) void { - comptime { - assert(@bitSizeOf(Packed) == @bitSizeOf(Int)); - } - addr.write_raw(@bitCast(val)); + pub inline fn write(mmio: MmioPtr, val: Fields) void { + mmio.raw.write(@bitCast(val)); } - pub inline fn write_raw(addr: *volatile Self, val: Int) void { - addr.raw = val; + /// For each `.Field = value` entry of `fields`: + /// Set field `Field` of this register to `value`. + /// All unspecified fields are initialized to zero. + /// Particularily useful for registers with atomic set/clear/xor + pub inline fn write_default_zero(mmio: MmioPtr, fields: FieldsZero) void { + mmio.write(@bitCast(fields)); } /// Set field `field_name` of this register to `value`. /// A one-field version of modify(), more helpful if `field_name` is comptime calculated. - pub inline fn modify_one(addr: *volatile Self, comptime field_name: []const u8, value: @FieldType(underlying_type, field_name)) void { + pub inline fn modify_one( + addr: MmioPtr, + comptime field_name: []const u8, + value: @FieldType(Fields, field_name), + ) void { var val = read(addr); @field(val, field_name) = value; write(addr, val); @@ -48,50 +135,66 @@ pub fn Mmio(comptime Packed: type) type { /// For each `.Field = value` entry of `fields`: /// Set field `Field` of this register to `value`. - pub inline fn modify(addr: *volatile Self, fields: anytype) void { - var val = read(addr); - inline for (@typeInfo(@TypeOf(fields)).@"struct".field_names) |field_name| { - @field(val, field_name) = @field(fields, field_name); + /// Operiation done by read-modify-write. + pub inline fn modify(mmio: MmioPtr, fields: FieldsOpt) void { + var val = mmio.read(); + inline for (field_names) |field_name| { + if (@field(fields, field_name)) |value| + @field(val, field_name) = value; } - write(addr, val); + mmio.write(val); + } + }; +} + +fn MmioBacking(Int: type) type { + return extern struct { + /// Naturally aligned volatile pointer + pub const MmioPtr = *align(@sizeOf(Int)) volatile @This(); + + /// Do not access directly. Use read/write functions instead. + backing: Int, + + pub inline fn read(mmio: MmioPtr) Int { + return mmio.backing; } - /// In field `field_name` of struct `val`, toggle (only) all bits that are set in `value`. - inline fn toggle_field(val: anytype, comptime field_name: []const u8, value: anytype) void { - const FieldType = @TypeOf(@field(val, field_name)); - switch (@typeInfo(FieldType)) { - .int => { - @field(val, field_name) = @field(val, field_name) ^ value; - }, - .@"enum" => |enum_info| { - // same as for the .Int case, but casting to and from the u... tag type U of the enum FieldType - const U = enum_info.tag_type; - @field(val, field_name) = - @as(FieldType, @enumFromInt(@as(U, @intFromEnum(@field(val, field_name))) ^ - @as(U, @intFromEnum(@as(FieldType, value))))); - }, - else => |T| { - @compileError("unsupported register field type '" ++ @typeName(T) ++ "'"); - }, - } + pub inline fn write(mmio: MmioPtr, val: Int) void { + mmio.backing = val; } - /// In field `field_name` of this register, toggle (only) all bits that are set in `value`. - /// A one-field version of toggle(), more helpful if `field_name` is comptime calculated. - pub inline fn toggle_one(addr: *volatile Self, comptime field_name: []const u8, value: anytype) void { - var val = read(addr); - toggle_field(&val, field_name, value); - write(addr, val); + /// First clears the bits in `clear_mask`, + /// then sets the bits in `set_mask`. + /// Operiation done by read-modify-write. + pub inline fn modify(mmio: MmioPtr, clear_mask: Int, set_mask: Int) void { + var val = mmio.read(); + val &= ~clear_mask; + val |= set_mask; + mmio.write(val); } - /// For each `.Field = value` entry of `fields`: - /// In field `F` of this register, toggle (only) all bits that are set in `value`. - pub inline fn toggle(addr: *volatile Self, fields: anytype) void { - var val = read(addr); - inline for (@typeInfo(@TypeOf(fields)).@"struct".field_names) |field_name| { - toggle_field(&val, field_name, @field(fields, field_name)); - } - write(addr, val); + /// Sets the register's bits contained in `set_mask`. + /// Operiation done by read-modify-write. + pub inline fn set(mmio: MmioPtr, set_mask: Int) void { + var val = mmio.read(); + val |= set_mask; + mmio.write(val); + } + + /// Clears the register's bits contained in `clear_mask`, + /// Operiation done by read-modify-write. + pub inline fn clear(mmio: MmioPtr, clear_mask: Int) void { + var val = mmio.read(); + val &= ~clear_mask; + mmio.write(val); + } + + /// Toggles the register's bits contained in `toggle_mask`. + /// Operiation done by read-modify-write. + pub inline fn toggle(mmio: MmioPtr, toggle_mask: Int) void { + var val = mmio.read(); + val ^= toggle_mask; + mmio.write(val); } }; } diff --git a/core/src/utilities.zig b/core/src/utilities.zig index 17d6323b7..1ca0f1209 100644 --- a/core/src/utilities.zig +++ b/core/src/utilities.zig @@ -704,3 +704,15 @@ pub fn IntFracDiv(int_bits: comptime_int, frac_bits: comptime_int) type { } }; } + +pub fn RegFieldType(Peri: type, reg_name: []const u8, field_name: []const u8) type { + const Field = @FieldType(Peri, reg_name); + const Reg = switch (@typeInfo(Field)) { + .@"struct" => Field.Fields, + .array => |info| info.child.Fields, + else => @compileError("Error getting " ++ @typeName(Peri) ++ + "." ++ reg_name ++ "." ++ field_name ++ + " type. Encountered field of type " ++ @typeName(Field)), + }; + return @FieldType(Reg, field_name); +} diff --git a/examples/no_hal/stm32_l031/src/blinky.zig b/examples/no_hal/stm32_l031/src/blinky.zig index 4a717e9d6..dafe611e2 100644 --- a/examples/no_hal/stm32_l031/src/blinky.zig +++ b/examples/no_hal/stm32_l031/src/blinky.zig @@ -22,6 +22,6 @@ pub fn main() !void { asm volatile ("nop"); i += 1; } - GPIOB.ODR.raw = (GPIOB.ODR.raw ^ 0x8); + GPIOB.ODR.raw.toggle(0x8); } } diff --git a/examples/raspberrypi/rp2xxx/src/rp2040_only/tiles.zig b/examples/raspberrypi/rp2xxx/src/rp2040_only/tiles.zig index 2ad4b0d42..9b889c035 100644 --- a/examples/raspberrypi/rp2xxx/src/rp2040_only/tiles.zig +++ b/examples/raspberrypi/rp2xxx/src/rp2040_only/tiles.zig @@ -133,20 +133,20 @@ pub fn main() !void { fn sm_set_consecutive_pindirs(_pio: Pio, _sm: StateMachine, pin: u5, count: u3, is_out: bool) void { const sm_regs = _pio.get_sm_regs(_sm); - const pinctrl_saved = sm_regs.pinctrl.raw; - sm_regs.pinctrl.modify(.{ - .SET_BASE = pin, - .SET_COUNT = count, - }); + const pinctrl_saved = sm_regs.pinctrl.read(); + + var pinctrl_mod = pinctrl_saved; + pinctrl_mod.SET_BASE = pin; + pinctrl_mod.SET_COUNT = count; + sm_regs.pinctrl.write(pinctrl_mod); + _pio.sm_exec(_sm, rp2xxx.pio.Instruction{ .tag = .set, .delay_side_set = 0, - .payload = .{ - .set = .{ - .data = @intFromBool(is_out), - .destination = .pindirs, - }, - }, + .payload = .{ .set = .{ + .data = @intFromBool(is_out), + .destination = .pindirs, + } }, }); - sm_regs.pinctrl.raw = pinctrl_saved; + sm_regs.pinctrl.write(pinctrl_saved); } diff --git a/examples/wch/ch32v/src/blinky_systick.zig b/examples/wch/ch32v/src/blinky_systick.zig index a027fcc2b..c9082c223 100644 --- a/examples/wch/ch32v/src/blinky_systick.zig +++ b/examples/wch/ch32v/src/blinky_systick.zig @@ -45,13 +45,13 @@ pub fn main() !void { const PFIC = peripherals.PFIC; // Reset configuration. - PFIC.STK_CTLR.raw = 0; + PFIC.STK_CTLR.raw.write(0); // Reset the Count Register. - PFIC.STK_CNTL.raw = 0; + PFIC.STK_CNTL.raw.write(0); // Set the compare register to trigger once per second. - PFIC.STK_CMPLR.raw = cpu.cpu_frequency - 1; + PFIC.STK_CMPLR.raw.write(cpu.cpu_frequency - 1); // Set the SysTick Configuration. - PFIC.STK_CTLR.modify(.{ + PFIC.STK_CTLR.write_raw_default_zero(.{ // Turn on the system counter STK .STE = 1, // Enable counter interrupt. diff --git a/examples/wch/ch32v/src/dma.zig b/examples/wch/ch32v/src/dma.zig index 60accd571..f17dfee27 100644 --- a/examples/wch/ch32v/src/dma.zig +++ b/examples/wch/ch32v/src/dma.zig @@ -26,9 +26,9 @@ var wbuf: [1024]u32 = @splat(0); inline fn read_stk_cnt() u64 { const PFIC = microzig.chip.peripherals.PFIC; while (true) { - const high1: u32 = PFIC.STK_CNTH.raw; - const low: u32 = PFIC.STK_CNTL.raw; - const high2: u32 = PFIC.STK_CNTH.raw; + const high1: u32 = PFIC.STK_CNTH.raw.read(); + const low: u32 = PFIC.STK_CNTL.raw.read(); + const high2: u32 = PFIC.STK_CNTH.raw.read(); // If high didn't change, we have a consistent reading if (high1 == high2) { diff --git a/modules/virtual-io/src/root.zig b/modules/virtual-io/src/root.zig index abb3a75bc..7621de17b 100644 --- a/modules/virtual-io/src/root.zig +++ b/modules/virtual-io/src/root.zig @@ -3,7 +3,6 @@ const std = @import("std"); const builtin = @import("builtin"); const Allocator = std.mem.Allocator; -const assert = std.debug.assert; const Io = std.Io; const log = std.log.scoped(.vio); @@ -19,7 +18,7 @@ pub const Dir = struct { pub const kind: Node.Kind = empty; pub const ID = enum(Node.ID) { - // Reserve first 256 file handles for os-specific values, such as sitdin/out/err + // Reserve first 256 file handles for os-specific values, such as stdin/out/err // on posix, cwd on wasm and the reserved NULL value on windows. root = 0x100, _, @@ -283,7 +282,6 @@ pub fn from_handle(T: type, handle: std.posix.fd_t) !T { } pub fn to_handle(id: anytype) std.posix.fd_t { - // const ID = @TypeOf(id); return switch (builtin.os.tag) { .windows => @ptrFromInt(@intFromEnum(id)), else => @intFromEnum(id), diff --git a/port/espressif/esp/src/cpus/esp_riscv.zig b/port/espressif/esp/src/cpus/esp_riscv.zig index 89b803641..3feeae1a8 100644 --- a/port/espressif/esp/src/cpus/esp_riscv.zig +++ b/port/espressif/esp/src/cpus/esp_riscv.zig @@ -60,6 +60,10 @@ pub const Interrupt = enum(u5) { interrupt29 = 29, interrupt30 = 30, interrupt31 = 31, + + pub fn mask(int: Interrupt) u32 { + return int.mask(); + } }; pub const InterruptHandler = union(enum) { @@ -92,27 +96,27 @@ pub const interrupt = struct { const INTERRUPT_CORE0 = microzig.chip.peripherals.INTERRUPT_CORE0; pub fn is_enabled(int: Interrupt) bool { - return INTERRUPT_CORE0.CPU_INT_ENABLE.raw & (@as(u32, 1) << @intFromEnum(int)) != 0; + return INTERRUPT_CORE0.CPU_INT_ENABLE.raw.read() & int.mask() != 0; } pub fn enable(int: Interrupt) void { - INTERRUPT_CORE0.CPU_INT_ENABLE.raw |= @as(u32, 1) << @intFromEnum(int); + INTERRUPT_CORE0.CPU_INT_ENABLE.raw.set(int.mask()); } pub fn disable(int: Interrupt) void { - INTERRUPT_CORE0.CPU_INT_ENABLE.raw &= ~(@as(u32, 1) << @intFromEnum(int)); + INTERRUPT_CORE0.CPU_INT_ENABLE.raw.clear(int.mask()); } /// Checks if a given interrupt is pending. pub fn is_pending(int: Interrupt) bool { - return INTERRUPT_CORE0.CPU_INT_EIP_STATUS.raw & (@as(u32, 1) << @intFromEnum(int)) != 0; + return INTERRUPT_CORE0.CPU_INT_EIP_STATUS.raw.read() & int.mask() != 0; } /// Clears the pending state of claimed (executing) edge-type interrupt only. /// NOTE: Pending state of an unclaimed (not executing) edge type interrupt can be flushed, /// if required, by first disabling it and only then call clearing it. pub fn clear_pending(int: Interrupt) void { - INTERRUPT_CORE0.CPU_INT_CLEAR.raw |= @as(u32, 1) << @intFromEnum(int); + INTERRUPT_CORE0.CPU_INT_CLEAR.raw.set(int.mask()); } pub const Priority = enum(u4) { @@ -160,16 +164,15 @@ pub const interrupt = struct { }; pub fn set_type(int: Interrupt, typ: Type) void { - const num = @intFromEnum(int); switch (typ) { - .level => INTERRUPT_CORE0.CPU_INT_TYPE.raw &= ~(@as(u32, 1) << num), - .edge => INTERRUPT_CORE0.CPU_INT_TYPE.raw |= @as(u32, 1) << num, + .level => INTERRUPT_CORE0.CPU_INT_TYPE.raw.clear(int.mask()), + .edge => INTERRUPT_CORE0.CPU_INT_TYPE.raw.set(int.mask()), } } pub fn get_type(int: Interrupt) Type { const num = @intFromEnum(int); - return @enumFromInt(INTERRUPT_CORE0.CPU_INT_TYPE.raw & (@as(u32, 1) << num) >> num); + return @enumFromInt((INTERRUPT_CORE0.CPU_INT_TYPE.raw.read() >> num) & 1); } pub const Source = enum(u6) { @@ -261,8 +264,8 @@ pub const interrupt = struct { pub fn init() Status { return .{ - .reg = INTERRUPT_CORE0.INTR_STATUS_REG_0.raw | - (@as(u61, INTERRUPT_CORE0.INTR_STATUS_REG_1.raw) << 32), + .reg = INTERRUPT_CORE0.INTR_STATUS_REG_0.raw.read() | + (@as(u61, INTERRUPT_CORE0.INTR_STATUS_REG_1.raw.read()) << 32), }; } diff --git a/port/espressif/esp/src/hal.zig b/port/espressif/esp/src/hal.zig index 4696a0870..32f737624 100644 --- a/port/espressif/esp/src/hal.zig +++ b/port/espressif/esp/src/hal.zig @@ -80,19 +80,19 @@ fn disable_watchdogs() void { const super_dogfood = 0x8F1D312A; // Feed and disable watchdog 0 - TIMG0.WDTWPROTECT.raw = dogfood; - TIMG0.WDTCONFIG0.raw = 0; - TIMG0.WDTWPROTECT.raw = 0; + TIMG0.WDTWPROTECT.raw.write(dogfood); + TIMG0.WDTCONFIG0.raw.write(0); + TIMG0.WDTWPROTECT.raw.write(0); // Feed and disable rtc watchdog - RTC_CNTL.WDTWPROTECT.raw = dogfood; - RTC_CNTL.WDTCONFIG0.raw = 0; - RTC_CNTL.WDTWPROTECT.raw = 0; + RTC_CNTL.WDTWPROTECT.raw.write(dogfood); + RTC_CNTL.WDTCONFIG0.raw.write(0); + RTC_CNTL.WDTWPROTECT.raw.write(0); // Feed and disable rtc super watchdog - RTC_CNTL.SWD_WPROTECT.raw = super_dogfood; + RTC_CNTL.SWD_WPROTECT.raw.write(super_dogfood); RTC_CNTL.SWD_CONF.modify(.{ .SWD_DISABLE = 1 }); - RTC_CNTL.SWD_WPROTECT.raw = 0; + RTC_CNTL.SWD_WPROTECT.raw.write(0); } // Don't change the name of this export, it is checked by espflash tool. Only diff --git a/port/espressif/esp/src/hal/clocks/esp32_c3.zig b/port/espressif/esp/src/hal/clocks/esp32_c3.zig index 5a9eb7ca9..7ae5e26fc 100644 --- a/port/espressif/esp/src/hal/clocks/esp32_c3.zig +++ b/port/espressif/esp/src/hal/clocks/esp32_c3.zig @@ -155,7 +155,7 @@ fn switch_to_xtal(div: u10) void { fn apb_freq_update(freq: u32) void { const value = ((freq >> 12) & @as(u32, std.math.maxInt(u16))) | (((freq >> 12) & @as(u32, std.math.maxInt(u16))) << 16); - RTC_CNTL.STORE5.write_raw(value); + RTC_CNTL.STORE5.raw.write(value); } fn rom_cpu_frequency_update(freq: u32) void { diff --git a/port/espressif/esp/src/hal/gpio.zig b/port/espressif/esp/src/hal/gpio.zig index ff3bfef9a..6d7603bdf 100644 --- a/port/espressif/esp/src/hal/gpio.zig +++ b/port/espressif/esp/src/hal/gpio.zig @@ -378,7 +378,7 @@ pub const Pin = enum(u5) { pub fn read(self: Pin) u1 { std.debug.assert(IO_MUX.GPIO[@intFromEnum(self)].read().FUN_IE == 1); - return @intCast((GPIO.IN.raw >> @intFromEnum(self)) & 1); + return @intCast((GPIO.IN.raw.read() >> @intFromEnum(self)) & 1); } pub fn toggle(self: Pin) void { diff --git a/port/espressif/esp/src/hal/i2c.zig b/port/espressif/esp/src/hal/i2c.zig index b9c0bb64f..7e0614566 100644 --- a/port/espressif/esp/src/hal/i2c.zig +++ b/port/espressif/esp/src/hal/i2c.zig @@ -146,13 +146,13 @@ pub const I2C = struct { self.reset(); // Disable all I2C interrupts - regs.INT_ENA.write_raw(0); + regs.INT_ENA.raw.write(0); // Clear all I2C interrupts self.clear_interrupts(); // Configure controller - regs.CTR.write_raw(0); + regs.CTR.raw.write(0); regs.CTR.modify(.{ .MS_MODE = 1, // Set I2C controller to master mode .SDA_FORCE_OUT = 1, // Use open drain output for SDA @@ -235,7 +235,7 @@ pub const I2C = struct { fn reset_command_list(self: I2C) void { // Reset all command registers for (0..self.get_regs().COMD.len) |i| - self.get_regs().COMD[@intCast(i)].write_raw(0); + self.get_regs().COMD[@intCast(i)].raw.write(0); } /// Set the filter threshold in clock cycles @@ -342,7 +342,7 @@ pub const I2C = struct { /// Clear all interrupts inline fn clear_interrupts(self: I2C) void { - self.get_regs().INT_CLR.write_raw(0x3ffff); + self.get_regs().INT_CLR.raw.write(0x3ffff); } inline fn start_transmission(self: I2C) void { diff --git a/port/espressif/esp/src/hal/rng.zig b/port/espressif/esp/src/hal/rng.zig index 5d2818d6a..c2c797fcd 100644 --- a/port/espressif/esp/src/hal/rng.zig +++ b/port/espressif/esp/src/hal/rng.zig @@ -3,7 +3,7 @@ const microzig = @import("microzig"); const RNG = microzig.chip.peripherals.RNG; pub fn random_u32() u32 { - return RNG.DATA; + return RNG.DATA.raw.read(); } pub fn read(buf: []u8) void { diff --git a/port/espressif/esp/src/hal/spi.zig b/port/espressif/esp/src/hal/spi.zig index e62aa9f6b..7f47ca0b2 100644 --- a/port/espressif/esp/src/hal/spi.zig +++ b/port/espressif/esp/src/hal/spi.zig @@ -129,7 +129,7 @@ pub const SPI = enum(u2) { }); // this also enables using all 16 words - regs.USER.write_raw(0); + regs.USER.raw.write(0); regs.CLK_GATE.modify(.{ .MST_CLK_ACTIVE = 1, @@ -143,11 +143,11 @@ pub const SPI = enum(u2) { }); // this also disables all cs lines - regs.MISC.write_raw(0); + regs.MISC.raw.write(0); - regs.SLAVE.write_raw(0); + regs.SLAVE.raw.write(0); - regs.CLOCK.write_raw(config.get_clock_config()); + regs.CLOCK.raw.write(config.get_clock_config()); regs.DMA_INT_CLR.modify(.{ .TRANS_DONE_INT_CLR = 1, diff --git a/port/espressif/esp/src/hal/system.zig b/port/espressif/esp/src/hal/system.zig index a1643d8ca..9bd012157 100644 --- a/port/espressif/esp/src/hal/system.zig +++ b/port/espressif/esp/src/hal/system.zig @@ -83,18 +83,18 @@ pub fn init() void { /// Sets the bits in the mask of the PERIP_CLK_ENx registers. pub fn clocks_enable_set(mask: PeripheralMask) void { - var current_mask: u64 = @bitCast(@as(u64, SYSTEM.PERIP_CLK_EN0.raw) | ((@as(u64, SYSTEM.PERIP_CLK_EN1.raw) << 32))); + var current_mask: u64 = @bitCast(@as(u64, SYSTEM.PERIP_CLK_EN0.raw.read()) | ((@as(u64, SYSTEM.PERIP_CLK_EN1.raw.read()) << 32))); current_mask |= @as(u43, @bitCast(mask)); - SYSTEM.PERIP_CLK_EN0.write_raw(@intCast(current_mask & 0xffff_ffff)); - SYSTEM.PERIP_CLK_EN1.write_raw(@intCast(current_mask >> 32)); + SYSTEM.PERIP_CLK_EN0.raw.write(@truncate(current_mask)); + SYSTEM.PERIP_CLK_EN1.raw.write(@intCast(current_mask >> 32)); } /// Clears the bits in the mask of the PERIP_CLK_ENx registers. pub fn clocks_enable_clear(mask: PeripheralMask) void { - var current_mask: u64 = @bitCast(@as(u64, SYSTEM.PERIP_CLK_EN0.raw) | ((@as(u64, SYSTEM.PERIP_CLK_EN1.raw) << 32))); + var current_mask: u64 = @bitCast(@as(u64, SYSTEM.PERIP_CLK_EN0.raw.read()) | ((@as(u64, SYSTEM.PERIP_CLK_EN1.raw.read()) << 32))); current_mask &= ~@as(u43, @bitCast(mask)); - SYSTEM.PERIP_CLK_EN0.write_raw(@intCast(current_mask & 0xffff_ffff)); - SYSTEM.PERIP_CLK_EN1.write_raw(@intCast(current_mask >> 32)); + SYSTEM.PERIP_CLK_EN0.raw.write(@truncate(current_mask)); + SYSTEM.PERIP_CLK_EN1.raw.write(@intCast(current_mask >> 32)); } /// Sets and clears the bits in the mask of the PERIP_RST_ENx registers. Resets the peripherals. @@ -105,18 +105,18 @@ pub fn peripheral_reset(mask: PeripheralMask) void { /// Sets the bits in the mask of the PERIP_RST_ENx registers. pub fn peripheral_reset_set(mask: PeripheralMask) void { - var current_mask: u64 = @bitCast(@as(u64, SYSTEM.PERIP_RST_EN0.raw) | ((@as(u64, SYSTEM.PERIP_RST_EN1.raw) << 32))); + var current_mask: u64 = @as(u64, SYSTEM.PERIP_RST_EN0.raw.read()) | (@as(u64, SYSTEM.PERIP_RST_EN1.raw.read()) << 32); current_mask |= @as(u43, @bitCast(mask)); - SYSTEM.PERIP_RST_EN0.write_raw(@intCast(current_mask & 0xffff_ffff)); - SYSTEM.PERIP_RST_EN1.write_raw(@intCast(current_mask >> 32)); + SYSTEM.PERIP_RST_EN0.raw.write(@truncate(current_mask)); + SYSTEM.PERIP_RST_EN1.raw.write(@intCast(current_mask >> 32)); } /// Clears the bits in the mask of the PERIP_RST_ENx registers. pub fn peripheral_reset_clear(mask: PeripheralMask) void { - var current_mask: u64 = @bitCast(@as(u64, SYSTEM.PERIP_RST_EN0.raw) | ((@as(u64, SYSTEM.PERIP_RST_EN1.raw) << 32))); + var current_mask: u64 = @as(u64, SYSTEM.PERIP_RST_EN0.raw.read()) | (@as(u64, SYSTEM.PERIP_RST_EN1.raw.read()) << 32); current_mask &= ~@as(u43, @bitCast(mask)); - SYSTEM.PERIP_RST_EN0.write_raw(@intCast(current_mask & 0xffff_ffff)); - SYSTEM.PERIP_RST_EN1.write_raw(@intCast(current_mask >> 32)); + SYSTEM.PERIP_RST_EN0.raw.write(@truncate(current_mask)); + SYSTEM.PERIP_RST_EN1.raw.write(@intCast(current_mask >> 32)); } /// Enable clocks and release peripherals from reset. diff --git a/port/espressif/esp/src/hal/uart.zig b/port/espressif/esp/src/hal/uart.zig index cbb7aa1d7..186b6d2ef 100644 --- a/port/espressif/esp/src/hal/uart.zig +++ b/port/espressif/esp/src/hal/uart.zig @@ -12,6 +12,6 @@ pub fn write(comptime index: comptime_int, slice: []const u8) void { const r = reg(index); for (slice) |c| { while (r.STATUS.read().TXFIFO_CNT > 8) {} - r.FIFO.raw = c; + r.FIFO.raw.write(c); } } diff --git a/port/gigadevice/gd32/src/hals/GD32VF103/gpio.zig b/port/gigadevice/gd32/src/hals/GD32VF103/gpio.zig index 7a4abee88..56df6d6fe 100644 --- a/port/gigadevice/gd32/src/hals/GD32VF103/gpio.zig +++ b/port/gigadevice/gd32/src/hals/GD32VF103/gpio.zig @@ -1,6 +1,3 @@ -const std = @import("std"); -const assert = std.debug.assert; - const microzig = @import("microzig"); pub const peripherals = microzig.chip.peripherals; @@ -74,15 +71,11 @@ pub const Pin = packed struct(u8) { } inline fn write_pin_config(gpio: Pin, config: u32) void { const port = gpio.get_port(); - if (gpio.number <= 7) { - const offset = @as(u5, gpio.number) << 2; - port.CTL0.raw &= ~(@as(u32, 0b1111) << offset); - port.CTL0.raw |= config << offset; - } else { - const offset = (@as(u5, gpio.number) - 8) << 2; - port.CTL1.raw &= ~(@as(u32, 0b1111) << offset); - port.CTL1.raw |= config << offset; - } + const offset = @as(u5, @as(u3, @truncate(gpio.number))) << 2; + port.CR[gpio.number >> 3].raw.modify( + @as(u32, 0b1111) << offset, + config << offset, + ); } fn mask(gpio: Pin) u16 { @@ -127,29 +120,26 @@ pub const Pin = packed struct(u8) { pub inline fn set_pull(gpio: Pin, pull: Pull) void { var port = gpio.get_port(); switch (pull) { - .up => port.BOP.raw = gpio.mask(), - .down => port.BC.raw = gpio.mask(), + .up => port.BOP.raw.write(gpio.mask()), + .down => port.BC.raw.write(gpio.mask()), } } pub inline fn read(gpio: Pin) u1 { const port = gpio.get_port(); - return if (port.ISTAT.raw & gpio.mask() != 0) - 1 - else - 0; + return @intFromBool(port.ISTAT.raw.read() & gpio.mask() != 0); } pub inline fn put(gpio: Pin, value: u1) void { var port = gpio.get_port(); switch (value) { - 0 => port.OCTL.raw &= ~gpio.mask(), - 1 => port.OCTL.raw |= gpio.mask(), + 0 => port.OCTL.raw.clear(gpio.mask()), + 1 => port.OCTL.raw.set(gpio.mask()), } } pub inline fn toggle(gpio: Pin) void { var port = gpio.get_port(); - port.OCTL.raw ^= gpio.mask(); + port.OCTL.raw.toggle(gpio.mask()); } }; diff --git a/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig b/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig index 211317764..0677ea8ed 100644 --- a/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig +++ b/port/gigadevice/gd32/src/hals/GD32VF103/pins.zig @@ -184,9 +184,9 @@ pub const GlobalConfiguration = struct { if (used_gpios != 0) { const offset = @intFromEnum(@field(Port, port_field_name)) + 2; const bit = @as(u32, 1 << offset); - RCU.APB2EN.raw |= bit; + RCU.APB2EN.raw.set(bit); // Delay after setting - _ = RCU.APB2EN.raw & bit; + _ = RCU.APB2EN.raw.read() & bit; } inline for (@typeInfo(Port.Configuration).@"struct".field_names) |field_name| { diff --git a/port/nordic/nrf5x/src/hal/clocks.zig b/port/nordic/nrf5x/src/hal/clocks.zig index cbddea02d..b0004886c 100644 --- a/port/nordic/nrf5x/src/hal/clocks.zig +++ b/port/nordic/nrf5x/src/hal/clocks.zig @@ -1,5 +1,3 @@ -const std = @import("std"); - const microzig = @import("microzig"); const CLOCK = microzig.chip.peripherals.CLOCK; @@ -22,8 +20,8 @@ pub const hfxo = struct { while (CLOCK.EVENTS_HFCLKSTARTED == 0) {} }, .nrf52 => { - CLOCK.TASKS_HFCLKSTART.write_raw(1); - while (CLOCK.EVENTS_HFCLKSTARTED.raw == 0) {} + CLOCK.TASKS_HFCLKSTART.raw.write(1); + while (CLOCK.EVENTS_HFCLKSTARTED.raw.read() == 0) {} }, } } @@ -34,7 +32,7 @@ pub const hfxo = struct { CLOCK.TASKS_HFCLKSTOP = 1; }, .nrf52 => { - CLOCK.TASKS_HFCLKSTOP.write_raw(1); + CLOCK.TASKS_HFCLKSTOP.raw.write(1); }, } } @@ -63,16 +61,8 @@ pub const lfclk = struct { }; pub fn calibrate() void { - switch (version) { - .nrf51 => { - CLOCK.TASKS_CAL = 1; - while (CLOCK.EVENTS_DONE == 0) {} - }, - .nrf52 => { - CLOCK.TASKS_CAL.write_raw(1); - while (CLOCK.EVENTS_DONE.raw == 0) {} - }, - } + CLOCK.TASKS_CAL.raw.write(1); + while (CLOCK.EVENTS_DONE.raw.read() == 0) {} } pub fn set_source(comptime source: Source) void { @@ -131,26 +121,11 @@ pub const lfclk = struct { } pub fn start() void { - switch (version) { - .nrf51 => { - CLOCK.TASKS_LFCLKSTART = 1; - while (CLOCK.EVENTS_LFCLKSTARTED == 0) {} - }, - .nrf52 => { - CLOCK.TASKS_LFCLKSTART.write_raw(1); - while (CLOCK.EVENTS_LFCLKSTARTED.raw == 0) {} - }, - } + CLOCK.TASKS_LFCLKSTART.raw.write(1); + while (CLOCK.EVENTS_LFCLKSTARTED.raw.read() == 0) {} } pub fn stop() void { - switch (version) { - .nrf51 => { - CLOCK.TASKS_LFCLKSTOP = 1; - }, - .nrf52 => { - CLOCK.TASKS_LFCLKSTOP.write_raw(1); - }, - } + CLOCK.TASKS_LFCLKSTOP.raw.write(1); } }; diff --git a/port/nordic/nrf5x/src/hal/gpio.zig b/port/nordic/nrf5x/src/hal/gpio.zig index 31bfc1adb..e331b7bf4 100644 --- a/port/nordic/nrf5x/src/hal/gpio.zig +++ b/port/nordic/nrf5x/src/hal/gpio.zig @@ -88,8 +88,8 @@ pub const Pin = enum(u6) { pub fn set_direction(pin: Pin, direction: Direction) void { const regs = pin.get_regs(); switch (direction) { - .in => regs.DIRCLR.raw = pin.mask(), - .out => regs.DIRSET.raw = pin.mask(), + .in => regs.DIRCLR.raw.write(pin.mask()), + .out => regs.DIRSET.raw.write(pin.mask()), } } @@ -117,19 +117,19 @@ pub const Pin = enum(u6) { pub inline fn put(pin: Pin, value: u1) void { const regs = pin.get_regs(); switch (value) { - 0 => regs.OUTCLR.raw = pin.mask(), - 1 => regs.OUTSET.raw = pin.mask(), + 0 => regs.OUTCLR.raw.write(pin.mask()), + 1 => regs.OUTSET.raw.write(pin.mask()), } } pub inline fn toggle(pin: Pin) void { const regs = pin.get_regs(); - regs.OUT.raw ^= pin.mask(); + regs.OUT.raw.toggle(pin.mask()); } pub inline fn read(pin: Pin) u1 { const regs = pin.get_regs(); - return @truncate(regs.IN.raw >> pin.index()); + return @truncate(regs.IN.raw.read() >> pin.index()); } pub fn set_drive_strength(pin: Pin, drive_strength: DriveStrength) void { diff --git a/port/nordic/nrf5x/src/hal/i2c.zig b/port/nordic/nrf5x/src/hal/i2c.zig index d9a685572..1d26eac67 100644 --- a/port/nordic/nrf5x/src/hal/i2c.zig +++ b/port/nordic/nrf5x/src/hal/i2c.zig @@ -73,7 +73,7 @@ pub const I2C = enum(u1) { config.scl_pin.set_direction(.in); config.scl_pin.set_drive_strength(.SOD1); switch (version) { - .nrf5283x => regs.PSELSCL.raw = @intFromEnum(config.scl_pin), + .nrf5283x => regs.PSELSCL.raw.write(@intFromEnum(config.scl_pin)), .nrf52840 => regs.PSEL.SCL.write(.{ .PIN = config.scl_pin.index(), .PORT = config.scl_pin.port(), @@ -84,7 +84,7 @@ pub const I2C = enum(u1) { config.sda_pin.set_direction(.in); config.sda_pin.set_drive_strength(.SOD1); switch (version) { - .nrf5283x => regs.PSELSDA.raw = @intFromEnum(config.sda_pin), + .nrf5283x => regs.PSELSDA.raw.write(@intFromEnum(config.sda_pin)), .nrf52840 => regs.PSEL.SDA.write(.{ .PIN = config.sda_pin.index(), .PORT = config.sda_pin.port(), @@ -105,21 +105,21 @@ pub const I2C = enum(u1) { pub fn reset(i2c: I2C) void { i2c.disable(); const regs = i2c.get_regs(); - regs.SHORTS.raw = 0x00000000; - regs.INTENSET.raw = 0x00000000; - regs.ERRORSRC.raw = 0xFFFFFFFF; + regs.SHORTS.raw.write(0x00000000); + regs.INTENSET.raw.write(0x00000000); + regs.ERRORSRC.raw.write(0xFFFFFFFF); switch (version) { .nrf5283x => { - regs.PSELSCL.raw = 0xFFFFFFFF; - regs.PSELSDA.raw = 0xFFFFFFFF; + regs.PSELSCL.raw.write(0xFFFFFFFF); + regs.PSELSDA.raw.write(0xFFFFFFFF); }, .nrf52840 => { - regs.PSEL.SCL.raw = 0xFFFFFFFF; - regs.PSEL.SDA.raw = 0xFFFFFFFF; + regs.PSEL.SCL.raw.write(0xFFFFFFFF); + regs.PSEL.SDA.raw.write(0xFFFFFFFF); }, } - regs.FREQUENCY.raw = 0x04000000; - regs.ADDRESS.raw = 0x00000000; + regs.FREQUENCY.raw.write(0x04000000); + regs.ADDRESS.raw.write(0x00000000); } fn tx_sent(i2c: I2C) bool { @@ -139,7 +139,7 @@ pub const I2C = enum(u1) { try i2c.check_and_clear_error(); std.mem.doNotOptimizeAway(0); } - regs.EVENTS_TXDSENT.raw = 0; + regs.EVENTS_TXDSENT.raw.write(0); } fn read_byte(i2c: I2C, deadline: mdf.time.Deadline) Error!u8 { @@ -151,25 +151,25 @@ pub const I2C = enum(u1) { std.mem.doNotOptimizeAway(0); } const v = regs.RXD.read().RXD; - regs.EVENTS_RXDREADY.raw = 0; + regs.EVENTS_RXDREADY.raw.write(0); return v; } fn clear_shorts(i2c: I2C) void { const regs = i2c.get_regs(); - regs.SHORTS.raw = 0x00000000; + regs.SHORTS.raw.write(0x00000000); } fn clear_events(i2c: I2C) void { const regs = i2c.get_regs(); - regs.EVENTS_SUSPENDED.raw = 0; - regs.EVENTS_STOPPED.raw = 0; - regs.EVENTS_ERROR.raw = 0; + regs.EVENTS_SUSPENDED.raw.write(0); + regs.EVENTS_STOPPED.raw.write(0); + regs.EVENTS_ERROR.raw.write(0); } fn clear_errors(i2c: I2C) void { const regs = i2c.get_regs(); - regs.ERRORSRC.raw = 0xFFFFFFFF; + regs.ERRORSRC.raw.write(0xFFFFFFFF); } fn disable_interrupts(i2c: I2C) void { @@ -203,7 +203,7 @@ pub const I2C = enum(u1) { const error_generated = regs.EVENTS_ERROR.read().EVENTS_ERROR == .Generated; if (error_generated) { // Clear error - regs.EVENTS_ERROR.raw = 0x0000000; + regs.EVENTS_ERROR.raw.write(0x0000000); // We expect this to return an error, if it doesn't then we don't understand the error const error_src = try i2c.check_error(); if (error_src != 0) { diff --git a/port/nordic/nrf5x/src/hal/i2cdma.zig b/port/nordic/nrf5x/src/hal/i2cdma.zig index 57bc261ce..273a445ee 100644 --- a/port/nordic/nrf5x/src/hal/i2cdma.zig +++ b/port/nordic/nrf5x/src/hal/i2cdma.zig @@ -1,11 +1,12 @@ const std = @import("std"); - const microzig = @import("microzig"); -const mdf = microzig.drivers; + const drivers = mdf.base; +const mdf = microzig.drivers; const peripherals = microzig.chip.peripherals; -const compatibility = @import("compatibility.zig"); +const utils = microzig.utilities; +const compatibility = @import("compatibility.zig"); const gpio = @import("gpio.zig"); const time = @import("time.zig"); @@ -18,10 +19,6 @@ const version: enum { else => compatibility.unsupported_chip("DMA I2C"), }; -// "Two Wire Interface Master" -const I2C0 = peripherals.TWIM0; -const I2C1 = peripherals.TWIM1; - const I2cRegs = microzig.chip.types.peripherals.TWIM0; const Config = struct { @@ -54,8 +51,8 @@ pub const I2C = enum(u1) { fn get_regs(i2c: I2C) *volatile I2cRegs { return switch (@intFromEnum(i2c)) { - 0 => I2C0, - 1 => I2C1, + 0 => peripherals.TWIM0, + 1 => peripherals.TWIM1, }; } @@ -121,13 +118,13 @@ pub const I2C = enum(u1) { pub fn reset(i2c: I2C) void { i2c.disable(); const regs = i2c.get_regs(); - regs.SHORTS.raw = 0x00000000; - regs.INTENSET.raw = 0x00000000; - regs.ERRORSRC.raw = 0xFFFFFFFF; - regs.PSEL.SCL.raw = 0xFFFFFFFF; - regs.PSEL.SDA.raw = 0xFFFFFFFF; - regs.FREQUENCY.raw = 0x04000000; - regs.ADDRESS.raw = 0x00000000; + regs.SHORTS.raw.write(0x00000000); + regs.INTENSET.raw.write(0x00000000); + regs.ERRORSRC.raw.write(0xFFFFFFFF); + regs.PSEL.SCL.raw.write(0xFFFFFFFF); + regs.PSEL.SDA.raw.write(0xFFFFFFFF); + regs.FREQUENCY.raw.write(0x04000000); + regs.ADDRESS.raw.write(0x00000000); } /// Check if a TX byte has been sent by reading the TXDSENT event. @@ -143,9 +140,8 @@ pub const I2C = enum(u1) { /// Configure the TX DMA buffer for transmission. /// Returns error if buffer is too large for the hardware's MAXCNT register. fn set_tx_buffer(i2c: I2C, buf: []const u8) !void { - // TODO: There has got to be a nicer way to do this. MAXCNT is u16 on nRF52840, and u8 on - // nRF52831 - const tx_cnt_type = @FieldType(@FieldType(@FieldType(I2cRegs, "TXD"), "MAXCNT").underlying_type, "MAXCNT"); + // MAXCNT is u16 on nRF52840, and u8 on nRF52831 + const tx_cnt_type = utils.RegFieldType(@FieldType(I2cRegs, "TXD"), "MAXCNT", "MAXCNT"); if (std.math.cast(tx_cnt_type, buf.len) == null) return Error.TooMuchData; @@ -158,9 +154,8 @@ pub const I2C = enum(u1) { /// Returns error if buffer is too large for the hardware's MAXCNT register. fn set_rx_buffer(i2c: I2C, buf: []u8) !void { const regs = i2c.get_regs(); - // TODO: There has got to be a nicer way to do this. MAXCNT is u16 on nRF52840, and u8 on - // nRF52831 - const rx_cnt_type = @FieldType(@FieldType(@FieldType(I2cRegs, "RXD"), "MAXCNT").underlying_type, "MAXCNT"); + // MAXCNT is u16 on nRF52840, and u8 on nRF52831 + const rx_cnt_type = utils.RegFieldType(@FieldType(I2cRegs, "RXD"), "MAXCNT", "MAXCNT"); if (std.math.cast(rx_cnt_type, buf.len) == null) return Error.TooMuchData; regs.RXD.PTR.write(.{ .PTR = @intFromPtr(buf.ptr) }); @@ -180,21 +175,21 @@ pub const I2C = enum(u1) { /// Clear all hardware shortcuts by resetting the SHORTS register. fn clear_shorts(i2c: I2C) void { const regs = i2c.get_regs(); - regs.SHORTS.raw = 0x00000000; + regs.SHORTS.raw.write(0x00000000); } /// Clear pending I2C event flags (SUSPENDED, STOPPED, ERROR). fn clear_events(i2c: I2C) void { const regs = i2c.get_regs(); - regs.EVENTS_SUSPENDED.raw = 0; - regs.EVENTS_STOPPED.raw = 0; - regs.EVENTS_ERROR.raw = 0; + regs.EVENTS_SUSPENDED.raw.write(0); + regs.EVENTS_STOPPED.raw.write(0); + regs.EVENTS_ERROR.raw.write(0); } /// Clear all error flags in the ERRORSRC register. fn clear_errors(i2c: I2C) void { const regs = i2c.get_regs(); - regs.ERRORSRC.raw = 0xFFFFFFFF; + regs.ERRORSRC.raw.write(0xFFFFFFFF); } // NOTE: Probably not needed, we never set them @@ -254,12 +249,12 @@ pub const I2C = enum(u1) { if (regs.EVENTS_SUSPENDED.read().EVENTS_SUSPENDED == .Generated or regs.EVENTS_STOPPED.read().EVENTS_STOPPED == .Generated) { - regs.EVENTS_STOPPED.raw = 0; + regs.EVENTS_STOPPED.raw.write(0); break; } // Stop the task on error, but we need to keep waiting until the stop event if (regs.EVENTS_ERROR.read().EVENTS_ERROR == .Generated) { - regs.EVENTS_ERROR.raw = 0; + regs.EVENTS_ERROR.raw.write(0); regs.TASKS_STOP.write(.{ .TASKS_STOP = .Trigger }); } if (deadline.is_reached_by(time.get_time_since_boot())) { diff --git a/port/nordic/nrf5x/src/hal/spim.zig b/port/nordic/nrf5x/src/hal/spim.zig index f410a26bc..df62056a7 100644 --- a/port/nordic/nrf5x/src/hal/spim.zig +++ b/port/nordic/nrf5x/src/hal/spim.zig @@ -1,13 +1,13 @@ const std = @import("std"); - const microzig = @import("microzig"); -const mdf = microzig.drivers; -const peripherals = microzig.chip.peripherals; -const compatibility = @import("compatibility.zig"); +const peripherals = microzig.chip.peripherals; +const mdf = microzig.drivers; +const utils = microzig.utilities; const Deadline = mdf.time.Deadline; const Duration = mdf.time.Duration; +const compatibility = @import("compatibility.zig"); const gpio = @import("gpio.zig"); const time = @import("time.zig"); @@ -22,13 +22,13 @@ const version: enum { const SPIM0 = peripherals.SPIM0; const SPIM1 = peripherals.SPIM1; -const SPIM2 = peripherals.SPIM2; -const SPIM3 = peripherals.SPIM3; +// const SPIM2 = peripherals.SPIM2; +// const SPIM3 = peripherals.SPIM3; const SpimRegs = microzig.chip.types.peripherals.SPIM0; const EASY_DMA_SIZE = std.math.maxInt( - @FieldType(@FieldType(@FieldType(SpimRegs, "TXD"), "MAXCNT").underlying_type, "MAXCNT"), + utils.RegFieldType(@FieldType(SpimRegs, "TXD"), "MAXCNT", "MAXCNT"), ); const Config = struct { @@ -174,7 +174,7 @@ pub const SPIM = enum(u1) { } regs.ENABLE.write(.{ .ENABLE = .Enabled }); - regs.INTENCLR.write_raw(0xFFFFFFFF); + regs.INTENCLR.raw.write(0xFFFFFFFF); } pub fn write_blocking(spi: SPIM, data: []const u8, timeout: ?Duration) TransactionError!void { @@ -240,10 +240,10 @@ pub const SPIM = enum(u1) { fn prepare_dma_transfer(spi: SPIM, tx: []const u8, rx: []u8) TransactionError!void { const regs = spi.get_regs(); - regs.RXD.PTR.write_raw(@intFromPtr(rx.ptr)); + regs.RXD.PTR.raw.write(@intFromPtr(rx.ptr)); regs.RXD.MAXCNT.write(.{ .MAXCNT = @truncate(rx.len) }); - regs.TXD.PTR.write_raw(@intFromPtr(tx.ptr)); + regs.TXD.PTR.raw.write(@intFromPtr(tx.ptr)); regs.TXD.MAXCNT.write(.{ .MAXCNT = @truncate(tx.len) }); regs.EVENTS_END.write(.{ .EVENTS_END = .NotGenerated }); diff --git a/port/nordic/nrf5x/src/hal/time.zig b/port/nordic/nrf5x/src/hal/time.zig index f1f8ea0c0..cf34d4972 100644 --- a/port/nordic/nrf5x/src/hal/time.zig +++ b/port/nordic/nrf5x/src/hal/time.zig @@ -8,16 +8,6 @@ const std = @import("std"); const microzig = @import("microzig"); const time = microzig.drivers.time; const clocks = microzig.hal.clocks; -const compatibility = microzig.hal.compatibility; - -const version: enum { - nrf51, - nrf52, -} = switch (compatibility.chip) { - .nrf51 => .nrf51, - .nrf52, .nrf52833, .nrf52840 => .nrf52, - else => compatibility.unsupported_chip("time"), -}; const rtc = microzig.chip.peripherals.RTC0; const COMPARE_INDEX = 2; @@ -51,16 +41,8 @@ pub fn init() void { rtc.CC[COMPARE_INDEX].write(.{ .COMPARE = 0x800000 }); // Clear counter, then start timer - switch (version) { - .nrf51 => { - rtc.TASKS_CLEAR = 1; - rtc.TASKS_START = 1; - }, - .nrf52 => { - rtc.TASKS_CLEAR.write_raw(1); - rtc.TASKS_START.write_raw(1); - }, - } + rtc.TASKS_CLEAR.raw.write(1); + rtc.TASKS_START.raw.write(1); // Wait for clear while (rtc.COUNTER.read().COUNTER != 0) {} @@ -69,29 +51,14 @@ pub fn init() void { /// Handle both overflow and compare interrupts. Update the period which acts as the high bits of /// the elapsed time. pub fn rtc_interrupt() callconv(.c) void { - switch (version) { - .nrf51 => { - if (rtc.EVENTS_OVRFLW == 1) { - rtc.EVENTS_OVRFLW = 0; - next_period(); - } - - if (rtc.EVENTS_COMPARE[COMPARE_INDEX] == 1) { - rtc.EVENTS_COMPARE[COMPARE_INDEX] = 0; - next_period(); - } - }, - .nrf52 => { - if (rtc.EVENTS_OVRFLW.raw == 1) { - rtc.EVENTS_OVRFLW.write_raw(0); - next_period(); - } - - if (rtc.EVENTS_COMPARE[COMPARE_INDEX].raw == 1) { - rtc.EVENTS_COMPARE[COMPARE_INDEX].write_raw(0); - next_period(); - } - }, + if (rtc.EVENTS_OVRFLW.raw.read() == 1) { + rtc.EVENTS_OVRFLW.raw.write(0); + next_period(); + } + + if (rtc.EVENTS_COMPARE[COMPARE_INDEX].raw.read() == 1) { + rtc.EVENTS_COMPARE[COMPARE_INDEX].raw.write(0); + next_period(); } } diff --git a/port/nordic/nrf5x/src/hal/uart.zig b/port/nordic/nrf5x/src/hal/uart.zig index c0c387e9f..2fe02a6f7 100644 --- a/port/nordic/nrf5x/src/hal/uart.zig +++ b/port/nordic/nrf5x/src/hal/uart.zig @@ -161,7 +161,7 @@ pub const UART = enum(u1) { fn set_txd(uart: UART, pin: gpio.Pin) void { const regs = uart.get_regs(); switch (version) { - .nrf5283x => regs.PSELTXD.raw = @intFromEnum(pin), + .nrf5283x => regs.PSELTXD.raw.write(@intFromEnum(pin)), .nrf52840 => regs.PSEL.TXD.write(.{ .PIN = pin.index(), .PORT = pin.port(), @@ -173,7 +173,7 @@ pub const UART = enum(u1) { fn set_rxd(uart: UART, pin: gpio.Pin) void { const regs = uart.get_regs(); switch (version) { - .nrf5283x => regs.PSELRXD.raw = @intFromEnum(pin), + .nrf5283x => regs.PSELRXD.raw.write(@intFromEnum(pin)), .nrf52840 => regs.PSEL.RXD.write(.{ .PIN = pin.index(), .PORT = pin.port(), @@ -185,7 +185,7 @@ pub const UART = enum(u1) { fn set_cts(uart: UART, pin: gpio.Pin) void { const regs = uart.get_regs(); switch (version) { - .nrf5283x => regs.PSELCTS.raw = @intFromEnum(pin), + .nrf5283x => regs.PSELCTS.raw.write(@intFromEnum(pin)), .nrf52840 => regs.PSEL.CTS.write(.{ .PIN = pin.index(), .PORT = pin.port(), @@ -197,7 +197,7 @@ pub const UART = enum(u1) { fn set_rts(uart: UART, pin: gpio.Pin) void { const regs = uart.get_regs(); switch (version) { - .nrf5283x => regs.PSELRTS.raw = @intFromEnum(pin), + .nrf5283x => regs.PSELRTS.raw.write(@intFromEnum(pin)), .nrf52840 => regs.PSEL.RTS.write(.{ .PIN = pin.index(), .PORT = pin.port(), @@ -373,7 +373,7 @@ pub const UART = enum(u1) { } pub fn clear_rx_rdy_event(uart: UART) void { - uart.get_regs().EVENTS_RXDRDY.raw = 0; + uart.get_regs().EVENTS_RXDRDY.raw.write(0); } pub fn have_tx_rdy_event(uart: UART) bool { @@ -381,7 +381,7 @@ pub const UART = enum(u1) { } pub fn clear_tx_rdy_event(uart: UART) void { - uart.get_regs().EVENTS_TXDRDY.raw = 0; + uart.get_regs().EVENTS_TXDRDY.raw.write(0); } pub fn have_rx_timeout_event(uart: UART) bool { @@ -389,6 +389,6 @@ pub const UART = enum(u1) { } pub fn clear_rx_timeout_event(uart: UART) void { - uart.get_regs().EVENTS_RXTO.raw = 0; + uart.get_regs().EVENTS_RXTO.raw.write(0); } }; diff --git a/port/nordic/nrf5x/src/hal/usbd.zig b/port/nordic/nrf5x/src/hal/usbd.zig index f6ceb0640..332408a12 100644 --- a/port/nordic/nrf5x/src/hal/usbd.zig +++ b/port/nordic/nrf5x/src/hal/usbd.zig @@ -66,25 +66,25 @@ pub const USBD = struct { const Self = @This(); pub fn init() Self { - peripherals.USBD.USBPULLUP.write_raw(0); - peripherals.USBD.ENABLE.write_raw(0); - peripherals.USBD.EPINEN.write_raw(0x01); // only EP0 IN by default - peripherals.USBD.EPOUTEN.write_raw(0x01); // only EP0 OUT by default - peripherals.USBD.EVENTCAUSE.write_raw(0xFFFFFFFF); // W1C all - peripherals.USBD.EPSTATUS.write_raw(0xFFFFFFFF); // W1C all - peripherals.USBD.EPDATASTATUS.write_raw(0xFFFFFFFF); // W1C all - peripherals.USBD.EVENTS_USBRESET.write_raw(0); - peripherals.USBD.EVENTS_EP0SETUP.write_raw(0); - peripherals.USBD.EVENTS_EP0DATADONE.write_raw(0); - peripherals.USBD.EVENTS_EPDATA.write_raw(0); - peripherals.USBD.EVENTS_USBEVENT.write_raw(0); + peripherals.USBD.USBPULLUP.raw.write(0); + peripherals.USBD.ENABLE.raw.write(0); + peripherals.USBD.EPINEN.raw.write(0x01); // only EP0 IN by default + peripherals.USBD.EPOUTEN.raw.write(0x01); // only EP0 OUT by default + peripherals.USBD.EVENTCAUSE.raw.write(0xFFFFFFFF); // W1C all + peripherals.USBD.EPSTATUS.raw.write(0xFFFFFFFF); // W1C all + peripherals.USBD.EPDATASTATUS.raw.write(0xFFFFFFFF); // W1C all + peripherals.USBD.EVENTS_USBRESET.raw.write(0); + peripherals.USBD.EVENTS_EP0SETUP.raw.write(0); + peripherals.USBD.EVENTS_EP0DATADONE.raw.write(0); + peripherals.USBD.EVENTS_EPDATA.raw.write(0); + peripherals.USBD.EVENTS_USBEVENT.raw.write(0); for (0..8) |i| { - peripherals.USBD.EVENTS_ENDEPIN[i].write_raw(0); - peripherals.USBD.EVENTS_ENDEPOUT[i].write_raw(0); - peripherals.USBD.EPIN[i].PTR.write_raw(0); - peripherals.USBD.EPIN[i].MAXCNT.write_raw(0); - peripherals.USBD.EPOUT[i].PTR.write_raw(0); - peripherals.USBD.EPOUT[i].MAXCNT.write_raw(0); + peripherals.USBD.EVENTS_ENDEPIN[i].raw.write(0); + peripherals.USBD.EVENTS_ENDEPOUT[i].raw.write(0); + peripherals.USBD.EPIN[i].PTR.raw.write(0); + peripherals.USBD.EPIN[i].MAXCNT.raw.write(0); + peripherals.USBD.EPOUT[i].PTR.raw.write(0); + peripherals.USBD.EPOUT[i].MAXCNT.raw.write(0); } return .{ .interface = .{ .vtable = &vtable }, @@ -104,28 +104,28 @@ pub const USBD = struct { .detached => { if (peripherals.POWER.USBREGSTATUS.read().VBUSDETECT == .VbusPresent) { errata.pre_enable(); - peripherals.USBD.ENABLE.write_raw(1); + peripherals.USBD.ENABLE.raw.write(1); self.power = .enabling; } }, .enabling => { if (peripherals.USBD.EVENTCAUSE.read().READY == .Ready) { peripherals.USBD.EVENTCAUSE.write(.{ .READY = .Ready }); // W1C - peripherals.USBD.EVENTS_USBEVENT.write_raw(0); + peripherals.USBD.EVENTS_USBEVENT.raw.write(0); errata.post_enable(); self.power = .waiting_pwrrdy; } }, .waiting_pwrrdy => { if (peripherals.POWER.USBREGSTATUS.read().OUTPUTRDY == .Ready) { - peripherals.USBD.USBPULLUP.write_raw(1); + peripherals.USBD.USBPULLUP.raw.write(1); self.power = .connected; } }, .connected => { // Bus reset - if (peripherals.USBD.EVENTS_USBRESET.raw != 0) { - peripherals.USBD.EVENTS_USBRESET.write_raw(0); + if (peripherals.USBD.EVENTS_USBRESET.raw.read() != 0) { + peripherals.USBD.EVENTS_USBRESET.raw.write(0); self.reset(); controller.on_bus_reset(&self.interface); @@ -133,19 +133,22 @@ pub const USBD = struct { } // SETUP packet captured by hardware - if (peripherals.USBD.EVENTS_EP0SETUP.raw != 0) { - peripherals.USBD.EVENTS_EP0SETUP.write_raw(0); + if (peripherals.USBD.EVENTS_EP0SETUP.raw.read() != 0) { + peripherals.USBD.EVENTS_EP0SETUP.raw.write(0); // Aborted control transfer: drop stale DATADONE so it can't // trigger on_buffer for the next transfer. - peripherals.USBD.EVENTS_EP0DATADONE.write_raw(0); + peripherals.USBD.EVENTS_EP0DATADONE.raw.write(0); self.ep0_state.in_pending = false; const setup: usb.types.SetupPacket = .{ - .request_type = @bitCast(@as(u8, @intCast(peripherals.USBD.BMREQUESTTYPE.raw))), - .request = @intCast(peripherals.USBD.BREQUEST.raw), - .value = .from(@as(u16, @intCast(peripherals.USBD.WVALUEH.raw)) << 8 | @as(u16, @intCast(peripherals.USBD.WVALUEL.raw))), - .index = .from(@as(u16, @intCast(peripherals.USBD.WINDEXH.raw)) << 8 | @as(u16, @intCast(peripherals.USBD.WINDEXL.raw))), - .length = .from(@as(u16, @intCast(peripherals.USBD.WLENGTHH.raw)) << 8 | @as(u16, @intCast(peripherals.USBD.WLENGTHL.raw))), + .request_type = @bitCast(@as(u8, @intCast(peripherals.USBD.BMREQUESTTYPE.raw.read()))), + .request = @intCast(peripherals.USBD.BREQUEST.raw.read()), + .value = .from((@as(u16, @intCast(peripherals.USBD.WVALUEH.raw.read())) << 8) | + @as(u16, @intCast(peripherals.USBD.WVALUEL.raw.read()))), + .index = .from((@as(u16, @intCast(peripherals.USBD.WINDEXH.raw.read())) << 8) | + @as(u16, @intCast(peripherals.USBD.WINDEXL.raw.read()))), + .length = .from((@as(u16, @intCast(peripherals.USBD.WLENGTHH.raw.read())) << 8) | + @as(u16, @intCast(peripherals.USBD.WLENGTHL.raw.read()))), }; self.ep0_state.direction = switch (peripherals.USBD.BMREQUESTTYPE.read().DIRECTION) { .HostToDevice => .Out, @@ -156,24 +159,24 @@ pub const USBD = struct { } // EP0 data-phase completions - if (peripherals.USBD.EVENTS_EP0DATADONE.raw != 0) { + if (peripherals.USBD.EVENTS_EP0DATADONE.raw.read() != 0) { // Here nrf-usbd doesn't clear OUT events // (https://github.com/nrf-rs/nrf-usbd/blob/main/src/usbd.rs#L683) // But this case is not handled in the controller yet - peripherals.USBD.EVENTS_EP0DATADONE.write_raw(0); + peripherals.USBD.EVENTS_EP0DATADONE.raw.write(0); self.ep0_state.in_pending = false; switch (self.ep0_state.direction) { .In => controller.on_buffer(&self.interface, .in(.ep0)), // Control-OUT with data-phase is unhandled in the controller - .Out => peripherals.USBD.TASKS_EP0STATUS.write_raw(1), + .Out => peripherals.USBD.TASKS_EP0STATUS.raw.write(1), } } // Data-endpoint completions - if (peripherals.USBD.EVENTS_EPDATA.raw != 0) { - peripherals.USBD.EVENTS_EPDATA.write_raw(0); - const status = peripherals.USBD.EPDATASTATUS.raw; - peripherals.USBD.EPDATASTATUS.write_raw(status); // W1C handled bits + if (peripherals.USBD.EVENTS_EPDATA.raw.read() != 0) { + peripherals.USBD.EVENTS_EPDATA.raw.write(0); + const status = peripherals.USBD.EPDATASTATUS.raw.read(); + peripherals.USBD.EPDATASTATUS.raw.write(status); // W1C handled bits // Calling on_buffer() for each set bit // IN endpoints (bits 1-7) var status_in = status >> 1; @@ -194,13 +197,13 @@ pub const USBD = struct { // TODO: Implement `Suspend` if (peripherals.USBD.EVENTCAUSE.read().SUSPEND == .Detected) { peripherals.USBD.EVENTCAUSE.write(.{ .SUSPEND = .Detected }); - peripherals.USBD.EVENTS_USBEVENT.write_raw(0); + peripherals.USBD.EVENTS_USBEVENT.raw.write(0); } // TODO: Implement `Resume` if (peripherals.USBD.EVENTCAUSE.read().RESUME == .Detected) { peripherals.USBD.EVENTCAUSE.write(.{ .RESUME = .Detected }); - peripherals.USBD.EVENTS_USBEVENT.write_raw(0); + peripherals.USBD.EVENTS_USBEVENT.raw.write(0); } // TODO: ISO endpoints @@ -213,8 +216,8 @@ pub const USBD = struct { if (self.ep0_state.in_pending) { const now = peripherals.USBD.FRAMECNTR.read().FRAMECNTR; if ((now -% self.ep0_state.in_start_frame) >= EP0_IN_STATUS_TIMEOUT_FRAMES) { - peripherals.USBD.TASKS_EP0STATUS.write_raw(1); - peripherals.USBD.EVENTS_EP0DATADONE.write_raw(0); + peripherals.USBD.TASKS_EP0STATUS.raw.write(1); + peripherals.USBD.EVENTS_EP0DATADONE.raw.write(0); self.ep0_state.in_pending = false; } } @@ -228,30 +231,30 @@ pub const USBD = struct { // // But in this case it won't happen because // we busywait for ENDEP* with interrupts disabled - peripherals.USBD.USBPULLUP.write_raw(0); - peripherals.USBD.ENABLE.write_raw(0); + peripherals.USBD.USBPULLUP.raw.write(0); + peripherals.USBD.ENABLE.raw.write(0); } fn reset(self: *Self) void { - peripherals.USBD.EPDATASTATUS.write_raw(0xFFFFFFFF); // W1C all - peripherals.USBD.EPSTATUS.write_raw(0xFFFFFFFF); // W1C all - peripherals.USBD.EVENTS_EP0SETUP.write_raw(0); - peripherals.USBD.EVENTS_EP0DATADONE.write_raw(0); - peripherals.USBD.EVENTS_EPDATA.write_raw(0); + peripherals.USBD.EPDATASTATUS.raw.write(0xFFFFFFFF); // W1C all + peripherals.USBD.EPSTATUS.raw.write(0xFFFFFFFF); // W1C all + peripherals.USBD.EVENTS_EP0SETUP.raw.write(0); + peripherals.USBD.EVENTS_EP0DATADONE.raw.write(0); + peripherals.USBD.EVENTS_EPDATA.raw.write(0); peripherals.USBD.SHORTS.write(.{ .EP0DATADONE_EP0STATUS = .Disabled }); - peripherals.USBD.EPINEN.write_raw(0x01); // only EP0 IN - peripherals.USBD.EPOUTEN.write_raw(0x01); // only EP0 OUT + peripherals.USBD.EPINEN.raw.write(0x01); // only EP0 IN + peripherals.USBD.EPOUTEN.raw.write(0x01); // only EP0 OUT for (1..NUM_EP) |i| { // NOTE: Data endpoints are automatically disabled on reset - peripherals.USBD.EPIN[i].PTR.write_raw(0); - peripherals.USBD.EPIN[i].MAXCNT.write_raw(0); - peripherals.USBD.EPOUT[i].PTR.write_raw(0); - peripherals.USBD.EPOUT[i].MAXCNT.write_raw(0); + peripherals.USBD.EPIN[i].PTR.raw.write(0); + peripherals.USBD.EPIN[i].MAXCNT.raw.write(0); + peripherals.USBD.EPOUT[i].PTR.raw.write(0); + peripherals.USBD.EPOUT[i].MAXCNT.raw.write(0); // When first enabled, bulk/interrupt endpoints // will return NAK until 0 is written to SIZE.EPOUT[n] - peripherals.USBD.SIZE.EPOUT[i].write_raw(0); + peripherals.USBD.SIZE.EPOUT[i].raw.write(0); } self.eps_in = @splat(.{}); @@ -268,7 +271,7 @@ pub const USBD = struct { log.debug("ep_writev {t}: ({} bytes) {X} ({s})", .{ ep_num, data[0].len, data[0], data[0] }); if (data[0].len == 0) { - if (ep_num == .ep0) peripherals.USBD.TASKS_EP0STATUS.write_raw(1); + if (ep_num == .ep0) peripherals.USBD.TASKS_EP0STATUS.raw.write(1); return 0; } @@ -286,8 +289,8 @@ pub const USBD = struct { const len: usb.types.Len = @intCast(scratch_cap - scratch_slice.len); // Prepare DMA transfer - peripherals.USBD.EPIN[i].PTR.write_raw(@intFromPtr(scratch)); - peripherals.USBD.EPIN[i].MAXCNT.write_raw(len); + peripherals.USBD.EPIN[i].PTR.raw.write(@intFromPtr(scratch)); + peripherals.USBD.EPIN[i].MAXCNT.raw.write(len); if (ep_num == .ep0) { // EPIN0: a short packet (len < max_packet_size) indicates the end of the data @@ -312,9 +315,9 @@ pub const USBD = struct { // Start DMA const was_enabled = cpu.interrupt.is_enabled(.USBD); defer if (was_enabled) cpu.interrupt.enable(.USBD); - peripherals.USBD.TASKS_STARTEPIN[i].write_raw(1); - while (peripherals.USBD.EVENTS_ENDEPIN[i].raw != 1) {} - peripherals.USBD.EVENTS_ENDEPIN[i].write_raw(0); + peripherals.USBD.TASKS_STARTEPIN[i].raw.write(1); + while (peripherals.USBD.EVENTS_ENDEPIN[i].raw.read() != 1) {} + peripherals.USBD.EVENTS_ENDEPIN[i].raw.write(0); return len; } @@ -330,20 +333,20 @@ pub const USBD = struct { const self: *Self = @fieldParentPtr("interface", itf); const i = @intFromEnum(ep_num); - const size = peripherals.USBD.SIZE.EPOUT[i].raw; + const size = peripherals.USBD.SIZE.EPOUT[i].raw.read(); const scratch_buf = &self.bufs_out[i]; // Prepare DMA transfer - peripherals.USBD.EPOUT[i].PTR.write_raw(@intFromPtr(scratch_buf)); - peripherals.USBD.EPOUT[i].MAXCNT.write_raw(size); + peripherals.USBD.EPOUT[i].PTR.raw.write(@intFromPtr(scratch_buf)); + peripherals.USBD.EPOUT[i].MAXCNT.raw.write(size); // Start DMA const was_enabled = cpu.interrupt.is_enabled(.USBD); defer if (was_enabled) cpu.interrupt.enable(.USBD); - peripherals.USBD.TASKS_STARTEPOUT[i].write_raw(1); - while (peripherals.USBD.EVENTS_ENDEPOUT[i].raw != 1) {} - peripherals.USBD.EVENTS_ENDEPOUT[i].write_raw(0); + peripherals.USBD.TASKS_STARTEPOUT[i].raw.write(1); + while (peripherals.USBD.EVENTS_ENDEPOUT[i].raw.read() != 1) {} + peripherals.USBD.EVENTS_ENDEPOUT[i].raw.write(0); var scratch_slice: []align(1) u8 = scratch_buf[0..size]; @@ -367,7 +370,7 @@ pub const USBD = struct { log.debug("ep_listen {t}: ({} bytes)", .{ ep_num, len }); if (ep_num == .ep0) { - peripherals.USBD.TASKS_EP0RCVOUT.write_raw(1); + peripherals.USBD.TASKS_EP0RCVOUT.raw.write(1); } } @@ -379,11 +382,11 @@ pub const USBD = struct { switch (ep.dir) { .In => { self.eps_in[i].max_packet_size = desc.max_packet_size.into(); - peripherals.USBD.EPINEN.write_raw(peripherals.USBD.EPINEN.raw | mask); + peripherals.USBD.EPINEN.raw.write(peripherals.USBD.EPINEN.raw.read() | mask); }, .Out => { self.eps_out[i].max_packet_size = desc.max_packet_size.into(); - peripherals.USBD.EPOUTEN.write_raw(peripherals.USBD.EPOUTEN.raw | mask); + peripherals.USBD.EPOUTEN.raw.write(peripherals.USBD.EPOUTEN.raw.read() | mask); }, } diff --git a/port/nxp/lpc/src/hals/LPC176x5x.zig b/port/nxp/lpc/src/hals/LPC176x5x.zig index 00db7633f..38473f182 100644 --- a/port/nxp/lpc/src/hals/LPC176x5x.zig +++ b/port/nxp/lpc/src/hals/LPC176x5x.zig @@ -69,14 +69,14 @@ pub fn route_pin(comptime pin: type, function: PinTarget) void { pub const gpio = struct { pub fn set_output(comptime pin: type) void { - pin.regs.dir.raw |= pin.gpio_mask; + pin.regs.dir.raw.set(pin.gpio_mask); } pub fn set_input(comptime pin: type) void { - pin.regs.dir.raw &= ~pin.gpio_mask; + pin.regs.dir.raw.clear(pin.gpio_mask); } pub fn read(comptime pin: type) microzig.gpio.State { - return if ((pin.regs.pin.raw & pin.gpio_mask) != 0) + return if ((pin.regs.pin.raw.read() & pin.gpio_mask) != 0) microzig.gpio.State.high else microzig.gpio.State.low; @@ -84,9 +84,9 @@ pub const gpio = struct { pub fn write(comptime pin: type, state: microzig.gpio.State) void { if (state == .high) { - pin.regs.set.raw = pin.gpio_mask; + pin.regs.set.raw.write(pin.gpio_mask); } else { - pin.regs.clr.raw = pin.gpio_mask; + pin.regs.clr.raw.write(pin.gpio_mask); } } }; @@ -194,7 +194,7 @@ pub fn Uart(comptime index: usize, comptime pins: microzig.uart.Pins) type { } pub fn tx(self: Self, ch: u8) void { while (!self.can_write()) {} // Wait for Previous transmission - UARTn.THR.raw = ch; // Load the data to be transmitted + UARTn.THR.raw.write(ch); // Load the data to be transmitted } pub fn can_read(self: Self) bool { diff --git a/port/nxp/mcx/src/mcxa153/hal/gpio.zig b/port/nxp/mcx/src/mcxa153/hal/gpio.zig index 8e50b97b6..cba2d4a40 100644 --- a/port/nxp/mcx/src/mcxa153/hal/gpio.zig +++ b/port/nxp/mcx/src/mcxa153/hal/gpio.zig @@ -24,31 +24,31 @@ pub const GPIO = enum(u7) { pub fn put(gpio: GPIO, output: u1) void { const regs = gpio.get_regs(); - const old: u32 = regs.PDOR.raw; + const old: u32 = regs.PDOR.raw.read(); const new = @as(u32, output) << gpio.get_pin(); - regs.PDOR.write_raw(old & ~gpio.get_mask() | new); + regs.PDOR.raw.write(old & ~gpio.get_mask() | new); } pub fn get(gpio: GPIO) bool { const regs = gpio.get_regs(); - return regs.PDIR.raw >> gpio.get_pin() & 1 != 0; + return ((regs.PDIR.raw.read() >> gpio.get_pin()) & 1) != 0; } pub fn toggle(gpio: GPIO) void { const regs = gpio.get_regs(); - const old: u32 = regs.PTOR.raw; + const old: u32 = regs.PTOR.raw.read(); - regs.PTOR.write_raw(old | gpio.get_mask()); + regs.PTOR.raw.write(old | gpio.get_mask()); } pub fn set_direction(gpio: GPIO, direction: Direction) void { const regs = gpio.get_regs(); - const old: u32 = regs.PDDR.raw; + const old: u32 = regs.PDDR.raw.read(); const new = @as(u32, @intFromEnum(direction)) << gpio.get_pin(); - regs.PDDR.write_raw(old & ~gpio.get_mask() | new); + regs.PDDR.raw.write(old & ~gpio.get_mask() | new); } pub fn set_interrupt_config(gpio: GPIO, trigger: InterruptConfig) void { @@ -56,20 +56,20 @@ pub const GPIO = enum(u7) { const irqc = @as(u32, @intFromEnum(trigger)) << 16; const isf = @as(u32, 1) << 24; - regs.ICR[gpio.get_pin()].write_raw(irqc | isf); + regs.ICR[gpio.get_pin()].raw.write(irqc | isf); } pub fn get_interrupt_flag(gpio: GPIO) bool { const regs = gpio.get_regs(); - return regs.ISFR0.raw >> gpio.get_pin() & 1 != 0; + return ((regs.ISFR0.raw.read() >> gpio.get_pin()) & 1) != 0; } pub fn clear_interrupt_flag(gpio: GPIO) void { const regs = gpio.get_regs(); - const old: u32 = regs.ISFR0.raw; + const old: u32 = regs.ISFR0.raw.read(); - regs.ISFR0.write_raw(old | gpio.get_mask()); + regs.ISFR0.raw.write(old | gpio.get_mask()); } fn get_regs(gpio: GPIO) *volatile chip.types.peripherals.GPIO0 { diff --git a/port/nxp/mcx/src/mcxa153/hal/syscon.zig b/port/nxp/mcx/src/mcxa153/hal/syscon.zig index 82f56c532..ee6d36d73 100644 --- a/port/nxp/mcx/src/mcxa153/hal/syscon.zig +++ b/port/nxp/mcx/src/mcxa153/hal/syscon.zig @@ -15,10 +15,10 @@ pub fn enable_clock(comptime peripheral: Peripheral) void { defer freeze_clock_configuration(); switch (peripheral.cc()) { - 0 => chip.peripherals.MRCC0.MRCC_GLB_CC0_SET.write_raw( + 0 => chip.peripherals.MRCC0.MRCC_GLB_CC0_SET.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_CC0_SET)) | peripheral.mask(), ), - 1 => chip.peripherals.MRCC0.MRCC_GLB_CC1_SET.write_raw( + 1 => chip.peripherals.MRCC0.MRCC_GLB_CC1_SET.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_CC1_SET)) | peripheral.mask(), ), } @@ -29,10 +29,10 @@ pub fn disable_clock(comptime peripheral: Peripheral) void { defer freeze_clock_configuration(); switch (peripheral.cc()) { - 0 => chip.peripherals.MRCC0.MRCC_GLB_CC0_CLR.write_raw( + 0 => chip.peripherals.MRCC0.MRCC_GLB_CC0_CLR.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_CC0_CLR)) | peripheral.mask(), ), - 1 => chip.peripherals.MRCC0.MRCC_GLB_CC1_CLR.write_raw( + 1 => chip.peripherals.MRCC0.MRCC_GLB_CC1_CLR.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_CC1_CLR)) | peripheral.mask(), ), } @@ -43,10 +43,10 @@ pub fn reset_release(comptime peripheral: Peripheral) void { defer freeze_clock_configuration(); switch (peripheral.cc()) { - 0 => chip.peripherals.MRCC0.MRCC_GLB_RST0_SET.write_raw( + 0 => chip.peripherals.MRCC0.MRCC_GLB_RST0_SET.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_RST0_SET)) | peripheral.mask(), ), - 1 => chip.peripherals.MRCC0.MRCC_GLB_RST1_SET.write_raw( + 1 => chip.peripherals.MRCC0.MRCC_GLB_RST1_SET.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_RST1_SET)) | peripheral.mask(), ), } @@ -57,10 +57,10 @@ pub fn reset_assert(comptime peripheral: Peripheral) void { defer freeze_clock_configuration(); switch (peripheral.cc()) { - 0 => chip.peripherals.MRCC0.MRCC_GLB_RST0_CLR.write_raw( + 0 => chip.peripherals.MRCC0.MRCC_GLB_RST0_CLR.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_RST0_CLR)) | peripheral.mask(), ), - 1 => chip.peripherals.MRCC0.MRCC_GLB_RST1_CLR.write_raw( + 1 => chip.peripherals.MRCC0.MRCC_GLB_RST1_CLR.raw.write( @as(u32, @bitCast(chip.peripherals.MRCC0.MRCC_GLB_RST1_CLR)) | peripheral.mask(), ), } diff --git a/port/nxp/mcx/src/mcxn947/hal/flexcomm.zig b/port/nxp/mcx/src/mcxn947/hal/flexcomm.zig index ff81b6b53..d5981f805 100644 --- a/port/nxp/mcx/src/mcxn947/hal/flexcomm.zig +++ b/port/nxp/mcx/src/mcxn947/hal/flexcomm.zig @@ -1,9 +1,12 @@ const std = @import("std"); const microzig = @import("microzig"); -const syscon = @import("syscon.zig"); -const chip = microzig.chip; -const peripherals = chip.peripherals; + const assert = std.debug.assert; +const peripherals = microzig.chip.peripherals; +const peri_types = microzig.chip.types.peripherals; +const utils = microzig.utilities; + +const syscon = @import("syscon.zig"); /// A Low-Power Flexible Communications interface (LP FlexComm). /// To initialize Uart, SPI or I2C, use `LPUart` or `LPI2c` instead. @@ -19,7 +22,7 @@ pub const FlexComm = enum(u4) { pub const Type = enum(u3) { none = 0, UART = 1, SPI = 2, I2C = 3, @"UART+I2C" = 7 }; - pub const RegTy = *volatile chip.types.peripherals.LP_FLEXCOMM0; + pub const RegTy = *volatile peri_types.LP_FLEXCOMM0; const Registers: [10]RegTy = .{ peripherals.LP_FLEXCOMM0, peripherals.LP_FLEXCOMM1, @@ -69,7 +72,7 @@ pub const FlexComm = enum(u4) { lp_oscillator = 6, _, // also no clock - const ClockTy = @FieldType(@TypeOf(chip.peripherals.SYSCON0.FCCLKSEL[0]).underlying_type, "SEL"); + const ClockTy = utils.RegFieldType(peri_types.SYSCON0, "FCCLKSEL", "SEL"); pub fn from(clk: ClockTy) Clock { return @enumFromInt(@intFromEnum(clk)); @@ -87,33 +90,33 @@ pub const FlexComm = enum(u4) { pub fn set_clock(flexcomm: FlexComm, clock: Clock, divider: u16) void { assert(divider > 0 and divider <= 256); const n = flexcomm.get_n(); - chip.peripherals.SYSCON0.FLEXCOMMCLKDIV[n].write(.{ + peripherals.SYSCON0.FLEXCOMMCLKDIV[n].write(.{ .DIV = @intCast(divider - 1), .RESET = .RELEASED, .HALT = .RUN, .UNSTAB = .STABLE, // read-only field }); - chip.peripherals.SYSCON0.FCCLKSEL[n].modify_one("SEL", clock.to()); + peripherals.SYSCON0.FCCLKSEL[n].modify_one("SEL", clock.to()); } /// Stops the interface's clock. pub fn stop_clock(flexcomm: FlexComm) void { - chip.peripherals.SYSCON0.FLEXCOMMCLKDIV[flexcomm.get_n()].modify("HALT", .HALT); + peripherals.SYSCON0.FLEXCOMMCLKDIV[flexcomm.get_n()].modify("HALT", .HALT); } /// Starts the interface's clock. pub fn start_clock(flexcomm: FlexComm) void { - chip.peripherals.SYSCON0.FLEXCOMMCLKDIV[flexcomm.get_n()].modify("HALT", .RUN); + peripherals.SYSCON0.FLEXCOMMCLKDIV[flexcomm.get_n()].modify("HALT", .RUN); } /// Computes the current clock speed of the interface in Hz (taking into account the divider). /// Returns 0 if the clock is disabled. pub fn get_clock(flexcomm: FlexComm) u32 { const n = flexcomm.get_n(); - const div = chip.peripherals.SYSCON0.FLEXCOMMCLKDIV[n].read(); + const div = peripherals.SYSCON0.FLEXCOMMCLKDIV[n].read(); if (div.HALT == .HALT) return 0; - const clock = Clock.from(chip.peripherals.SYSCON0.FCCLKSEL[n].read().SEL); + const clock = Clock.from(peripherals.SYSCON0.FCCLKSEL[n].read().SEL); // TODO: complete this function (see the sdk's implementation) const freq: u32 = switch (clock) { // .PLL => 1, diff --git a/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_I2C.zig b/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_I2C.zig index 9c74160d3..2bc9f0503 100644 --- a/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_I2C.zig +++ b/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_I2C.zig @@ -147,7 +147,7 @@ pub const LP_I2C = enum(u4) { } pub fn clear_flags(i2c: LP_I2C) void { - i2c.get_regs().MSR.write_raw(0); + i2c.get_regs().MSR.raw.write(0); } fn reset_fifos(i2c: LP_I2C) void { @@ -369,7 +369,7 @@ pub const LP_I2C = enum(u4) { flags = i2c.get_regs().MSR.read(); try i2c.check_flags(); } - i2c.get_regs().MSR.write_raw(1 << 9); + i2c.get_regs().MSR.raw.write(1 << 9); } fn wait_for_tx_space(i2c: LP_I2C) Error!void { diff --git a/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_UART.zig b/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_UART.zig index 592eac7b9..ca0fbbfa9 100644 --- a/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_UART.zig +++ b/port/nxp/mcx/src/mcxn947/hal/flexcomm/LP_UART.zig @@ -64,33 +64,33 @@ pub const LP_UART = enum(u4) { if (config.data_mode == .@"10bit") regs.BAUD.modify_one("M10", .ENABLED); if (config.stop_bits_count == .two) regs.BAUD.modify_one("SBNS", .TWO); - var ctrl = std.mem.zeroes(@TypeOf(regs.CTRL).underlying_type); - ctrl.M7 = if (config.data_mode == .@"7bit") .DATA7 else .NO_EFFECT; - ctrl.PE = if (config.parity != .none) .ENABLED else .DISABLED; - ctrl.PT = if (@intFromEnum(config.parity) & 1 == 0) .EVEN else .ODD; - ctrl.M = if (config.data_mode == .@"9bit") .DATA9 else .DATA8; - ctrl.TXINV = if (config.tx_invert) .INVERTED else .NOT_INVERTED; - ctrl.IDLECFG = .IDLE_2; // TODO: make this configurable ? - ctrl.ILT = .FROM_STOP; // same - regs.CTRL.write(ctrl); + regs.CTRL.write(.{ + .M7 = if (config.data_mode == .@"7bit") .DATA7 else .NO_EFFECT, + .PE = if (config.parity != .none) .ENABLED else .DISABLED, + .PT = if (@intFromEnum(config.parity) & 1 == 0) .EVEN else .ODD, + .M = if (config.data_mode == .@"9bit") .DATA9 else .DATA8, + .TXINV = if (config.tx_invert) .INVERTED else .NOT_INVERTED, + .IDLECFG = .IDLE_2, // TODO: make this configurable ? + .ILT = .FROM_STOP, // same + }); // clear flags and set bit order - var stat = std.mem.zeroes(@TypeOf(regs.STAT).underlying_type); - // read and write on these bits are different - // writing one cleare those flags - stat.RXEDGIF = .EDGE; - stat.IDLE = .IDLE; - stat.OR = .OVERRUN; - stat.NF = .NOISE; - stat.FE = .ERROR; - stat.PF = .PARITY; - stat.LBKDIF = .DETECTED; - stat.MA1F = .MATCH; - stat.MA2F = .MATCH; - - stat.MSBF = if (config.bit_order == .lsb) .LSB_FIRST else .MSB_FIRST; - stat.RXINV = if (config.rx_invert) .INVERTED else .NOT_INVERTED; - regs.STAT.modify(stat); + regs.STAT.write(.{ + // read and write on these bits are different + // writing one cleare those flags + .RXEDGIF = .EDGE, + .IDLE = .IDLE, + .OR = .OVERRUN, + .NF = .NOISE, + .FE = .ERROR, + .PF = .PARITY, + .LBKDIF = .DETECTED, + .MA1F = .MATCH, + .MA2F = .MATCH, + + .MSBF = if (config.bit_order == .lsb) .LSB_FIRST else .MSB_FIRST, + .RXINV = if (config.rx_invert) .INVERTED else .NOT_INVERTED, + }); uart.set_enabled(config.enable_send, config.enable_receive); diff --git a/port/nxp/mcx/src/mcxn947/hal/gpio.zig b/port/nxp/mcx/src/mcxn947/hal/gpio.zig index dce1d4e95..7e0086f51 100644 --- a/port/nxp/mcx/src/mcxn947/hal/gpio.zig +++ b/port/nxp/mcx/src/mcxn947/hal/gpio.zig @@ -33,31 +33,31 @@ pub const GPIO = enum(u8) { const new: u32 = @as(u32, 1) << gpio.get_pin(); if (output == 1) - regs.PSOR.write_raw(new) + regs.PSOR.raw.write(new) else - regs.PCOR.write_raw(new); + regs.PCOR.raw.write(new); } /// Returns the logical input of the GPIO. pub fn get(gpio: GPIO) bool { const regs = gpio.get_regs(); - return regs.PDIR.raw >> gpio.get_pin() & 1 != 0; + return regs.PDIR.raw.read() >> gpio.get_pin() & 1 != 0; } /// Toggles the logical output of the GPIO. pub fn toggle(gpio: GPIO) void { const regs = gpio.get_regs(); - regs.PTOR.write_raw(gpio.get_mask()); + regs.PTOR.raw.write(gpio.get_mask()); } pub fn set_direction(gpio: GPIO, direction: Direction) void { const regs = gpio.get_regs(); - const old: u32 = regs.PDDR.raw; + const old: u32 = regs.PDDR.raw.read(); const new = @as(u32, @intFromEnum(direction)) << gpio.get_pin(); - regs.PDDR.write_raw((old & ~gpio.get_mask()) | new); + regs.PDDR.raw.write((old & ~gpio.get_mask()) | new); } /// Returns the gpio's control register diff --git a/port/nxp/mcx/src/mcxn947/hal/pin.zig b/port/nxp/mcx/src/mcxn947/hal/pin.zig index 93c141e90..a1af00d36 100644 --- a/port/nxp/mcx/src/mcxn947/hal/pin.zig +++ b/port/nxp/mcx/src/mcxn947/hal/pin.zig @@ -36,7 +36,7 @@ pub const Pin = enum(u8) { const base = @intFromPtr(&pin.get_port().get_regs().PCR0); const reg: PinTy = @ptrFromInt(base + pin.get_n() * @as(u32, 4)); - reg.write_raw(@as(u16, @bitCast(config))); + reg.raw.write(@as(u16, @bitCast(config))); } /// Returns the pin configurator (essentially a builder). diff --git a/port/nxp/mcx/src/mcxn947/hal/syscon.zig b/port/nxp/mcx/src/mcxn947/hal/syscon.zig index 22f4afaf8..c66bfef94 100644 --- a/port/nxp/mcx/src/mcxn947/hal/syscon.zig +++ b/port/nxp/mcx/src/mcxn947/hal/syscon.zig @@ -1,4 +1,3 @@ -const std = @import("std"); const microzig = @import("microzig"); const chip = microzig.chip; @@ -18,7 +17,7 @@ pub fn module_enable_clock(module: Module) void { if (!module.can_control_clock()) return; const reg = &chip.peripherals.SYSCON0.AHBCLKCTRLSET[module.cc()]; - reg.write_raw(@as(u32, 1) << module.offset()); + reg.raw.write(@as(u32, 1) << module.offset()); } /// Disables the module's clock. @@ -27,7 +26,7 @@ pub fn module_disable_clock(module: Module) void { if (!module.can_control_clock()) return; const reg = &chip.peripherals.SYSCON0.AHBCLKCTRLCLR[module.cc()]; - reg.write_raw(@as(u32, 1) << module.offset()); + reg.raw.write(@as(u32, 1) << module.offset()); } // same as for `module_enable_clock` @@ -38,7 +37,7 @@ pub fn module_reset_assert(module: Module) void { if (!module.can_reset()) return; const reg = &chip.peripherals.SYSCON0.PRESETCTRLSET[module.cc()]; - reg.write_raw(@as(u32, 1) << module.offset()); + reg.raw.write(@as(u32, 1) << module.offset()); } /// Release the module's reset. @@ -47,7 +46,7 @@ pub fn module_reset_release(module: Module) void { if (!module.can_reset()) return; const reg = &chip.peripherals.SYSCON0.PRESETCTRLCLR[module.cc()]; - reg.write_raw(@as(u32, 1) << module.offset()); + reg.raw.write(@as(u32, 1) << module.offset()); } // This enum can be automatically generated using `generate.zig`, diff --git a/port/nxp/mcx/src/mcxn947/scripts/generate.zig b/port/nxp/mcx/src/mcxn947/scripts/generate.zig index a290c3a92..a18568d39 100644 --- a/port/nxp/mcx/src/mcxn947/scripts/generate.zig +++ b/port/nxp/mcx/src/mcxn947/scripts/generate.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const core = @import("out/MCXN947_cm33_core0.zig"); +// const core = @import("out/MCXN947_cm33_core0.zig"); const peripherals = @import("out/types.zig").peripherals; const Field = struct { name: []const u8, i: usize, offset: usize }; @@ -30,6 +30,7 @@ pub fn main() void { std.debug.print("preset \"{s}\" not in ahb\n", .{field.name}); } } + pub fn print_fields(comptime ty: []const u8, comptime suffix_: ?[]const u8) []Field { @setEvalBranchQuota(100000); var fields_: [4 * 32]Field = undefined; @@ -38,7 +39,7 @@ pub fn print_fields(comptime ty: []const u8, comptime suffix_: ?[]const u8) []Fi inline for (0..4) |i| { const num: []const u8 = &[_]u8{comptime std.fmt.digitToChar(i, .lower)}; - const T = @FieldType(peripherals.SYSCON0, ty ++ num).underlying_type; + const T = @FieldType(peripherals.SYSCON0, ty ++ num).Fields; inline for (comptime std.meta.fieldNames(T)) |name| { if (comptime std.mem.indexOf(u8, name, "reserved") != null or std.mem.indexOf(u8, name, "padding") != null) continue; const suf_i: ?usize = if (suffix_) |suffix| comptime std.mem.indexOf(u8, name, suffix) else name.len; diff --git a/port/raspberrypi/rp2xxx/src/hal/always_on_timer.zig b/port/raspberrypi/rp2xxx/src/hal/always_on_timer.zig index 7be3f4a56..f9b8a9b00 100644 --- a/port/raspberrypi/rp2xxx/src/hal/always_on_timer.zig +++ b/port/raspberrypi/rp2xxx/src/hal/always_on_timer.zig @@ -10,7 +10,6 @@ /// Note: We generally cannot use the Mmio function to write to the timer /// since all timer write operations require the "magic" value 0x5afe /// to be written to the top 16 bits of the register. -const std = @import("std"); const microzig = @import("microzig"); const peripherals = microzig.chip.peripherals; @@ -37,18 +36,15 @@ pub const ClockSource = enum { /// * `source` - The clock source to use pub fn set_clock_source(source: ClockSource) void { disable(); - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffff; - val |= 0x5afe_0002; - - switch (source) { - .lposc => val |= 0x0100, - .xosc => val |= 0x0200, - .gpio_1khz => val |= 0x0400, - .none => @panic("Cannot set clock source to none."), - } - - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify( + 0xffff_0000, + 0x5afe_0002 | @as(u32, switch (source) { + .lposc => 0x0100, + .xosc => 0x0200, + .gpio_1khz => 0x0400, + .none => @panic("Cannot set clock source to none."), + }), + ); } /// Get the current clock source for the timer @@ -57,7 +53,7 @@ pub fn set_clock_source(source: ClockSource) void { /// /// * `ClockSource` - The current clock source pub fn get_clock_source() ClockSource { - const src = POWMAN.TIMER.raw; + const src = POWMAN.TIMER.raw.read(); if ((src & 0x0001_0000) != 0) return .xosc; if ((src & 0x0002_0000) != 0) return .lposc; @@ -73,11 +69,10 @@ pub fn get_clock_source() ClockSource { /// /// * `use_1hz` - Whether to use the 1 Hz clock pub fn set_use_1hz_clock(use_1hz: bool) void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffff; - val |= 0x5afe_000; - if (use_1hz) val |= 0x2000; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify( + 0xffff_0000, + 0x5afe_0000 | (if (use_1hz) 0x2000 else 0), + ); } /// Get whether the 1 Hz clock is enabled @@ -86,7 +81,7 @@ pub fn set_use_1hz_clock(use_1hz: bool) void { /// /// * `bool` - Whether the 1 Hz clock is enabled pub fn get_use_1hz_clock() bool { - return POWMAN.TIMER.raw & 0x2000 != 0; + return POWMAN.TIMER.raw.read() & 0x2000 != 0; } /// Get the frequency of the low power oscillator @@ -166,18 +161,12 @@ pub fn set_time(time: u64) void { /// Enable the timer pub fn enable() void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffff; - val |= 0x5afe_0002; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify(0xffff_0000, 0x5afe_0002); } /// Disable the timer pub fn disable() void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_fffd; - val |= 0x5afe_0000; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify(0xffff_0002, 0x5afe_0000); } /// Check if the timer is enabled @@ -198,18 +187,12 @@ pub const alarm = struct { /// Disable the alarm pub fn disable() void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffef; - val |= 0x5afe_0000; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify(0x0000_ffef, 0x5afe_0000); } /// Enable the alarm pub fn enable() void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffef; - val |= 0x5afe_0010; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify(0xffff_0010, 0x5afe_0010); } /// Get the raw alarm time in milliseconds @@ -243,10 +226,7 @@ pub const alarm = struct { // Clear the alarm expired flag pub fn clear_expired() void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffbf; - val |= 0x5afe_0040; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify(0xffff_0040, 0x5afe_0040); } // Get the alarm wake from low power flag. @@ -256,18 +236,12 @@ pub const alarm = struct { // Clear the alarm wakes from low power flag. pub fn clear_power_up() void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffdf; - val |= 0x5afe_0000; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify(0xffff_0020, 0x5afe_0000); } // Set the alarm wakes from low power flag. pub fn set_power_up() void { - var val = POWMAN.TIMER.raw; - val &= 0x0000_ffdf; - val |= 0x5afe_0020; - POWMAN.TIMER.raw = val; + POWMAN.TIMER.raw.modify(0xffff_0020, 0x5afe_0020); } }; diff --git a/port/raspberrypi/rp2xxx/src/hal/clocks.zig b/port/raspberrypi/rp2xxx/src/hal/clocks.zig index b6f55c85f..f5d31b876 100644 --- a/port/raspberrypi/rp2xxx/src/hal/clocks.zig +++ b/port/raspberrypi/rp2xxx/src/hal/clocks.zig @@ -1,5 +1,3 @@ -const std = @import("std"); - const microzig = @import("microzig"); const CLOCKS = microzig.chip.peripherals.CLOCKS; @@ -39,7 +37,7 @@ pub const start_ticks = chip_specific.start_ticks; pub fn default_startup_procedure(comptime cfg: config.Global) void { // disable resus if it has been turned on elsewhere - CLOCKS.CLK_SYS_RESUS_CTRL.raw = 0; + CLOCKS.CLK_SYS_RESUS_CTRL.raw.write(0); xosc.init(); cfg.apply(); diff --git a/port/raspberrypi/rp2xxx/src/hal/gpio.zig b/port/raspberrypi/rp2xxx/src/hal/gpio.zig index 4cb8a9102..4382b5d98 100644 --- a/port/raspberrypi/rp2xxx/src/hal/gpio.zig +++ b/port/raspberrypi/rp2xxx/src/hal/gpio.zig @@ -1,5 +1,3 @@ -const std = @import("std"); - const microzig = @import("microzig"); const peripherals = microzig.chip.peripherals; const SIO = peripherals.SIO; @@ -9,7 +7,6 @@ const hw = @import("hw.zig"); const chip = @import("compatibility.zig").chip; -const resets = @import("resets.zig"); const NUM_BANK0_GPIOS = switch (chip) { .RP2040 => 30, .RP2350 => 48, @@ -117,8 +114,8 @@ pub const Mask = pub fn set_direction(self: Mask, direction: Direction) void { const raw_mask = @intFromEnum(self); switch (direction) { - .out => SIO.GPIO_OE_SET.raw = raw_mask, - .in => SIO.GPIO_OE_CLR.raw = raw_mask, + .out => SIO.GPIO_OE_SET.raw.write(raw_mask), + .in => SIO.GPIO_OE_CLR.raw.write(raw_mask), } } @@ -159,11 +156,11 @@ pub const Mask = } pub fn put(self: Mask, value: u32) void { - SIO.GPIO_OUT_XOR.raw = (SIO.GPIO_OUT.raw ^ value) & @intFromEnum(self); + SIO.GPIO_OUT_XOR.raw.write((SIO.GPIO_OUT.raw.read() ^ value) & @intFromEnum(self)); } pub fn read(self: Mask) u32 { - return SIO.GPIO_IN.raw & @intFromEnum(self); + return SIO.GPIO_IN.raw.read() & @intFromEnum(self); } }, .RP2350 => enum(u48) { @@ -191,12 +188,12 @@ pub const Mask = const upper_mask = self.upper_16_mask(); switch (direction) { .out => { - SIO.GPIO_OE_SET.raw = lower_mask; - SIO.GPIO_HI_OE_SET.raw = upper_mask; + SIO.GPIO_OE_SET.raw.write(lower_mask); + SIO.GPIO_HI_OE_SET.raw.write(upper_mask); }, .in => { - SIO.GPIO_OE_CLR.raw = lower_mask; - SIO.GPIO_HI_OE_CLR.raw = lower_mask; + SIO.GPIO_OE_CLR.raw.write(lower_mask); + SIO.GPIO_HI_OE_CLR.raw.write(upper_mask); }, } } @@ -242,15 +239,15 @@ pub const Mask = const lower_val: u32 = @truncate(value); const upper_mask = self.upper_16_mask(); const upper_val: u16 = @truncate(value >> 32); - SIO.GPIO_OUT_XOR.raw = (SIO.GPIO_OUT.raw ^ lower_val) & lower_mask; - SIO.GPIO_HI_OUT_XOR.raw = (SIO.GPIO_HI_OUT.raw ^ upper_val) & upper_mask; + SIO.GPIO_OUT_XOR.raw.write((SIO.GPIO_OUT.raw.read() ^ lower_val) & lower_mask); + SIO.GPIO_HI_OUT_XOR.raw.write((SIO.GPIO_HI_OUT.raw.read() ^ upper_val) & upper_mask); } pub fn read(self: Mask) u48 { const lower_mask = self.lower_32_mask(); - const lower_val: u32 = SIO.GPIO_IN.raw & lower_mask; + const lower_val: u32 = SIO.GPIO_IN.raw.read() & lower_mask; const upper_mask = self.upper_16_mask(); - const upper_val: u16 = @truncate(SIO.GPIO_HI_IN.raw & upper_mask); + const upper_val: u16 = @truncate(SIO.GPIO_HI_IN.raw.read() & upper_mask); return (@as(u48, upper_val) << 32) | @as(u48, lower_val); } }, @@ -342,20 +339,20 @@ pub const Pin = enum(u6) { switch (chip) { .RP2040 => { switch (direction) { - .in => SIO.GPIO_OE_CLR.raw = gpio.mask(), - .out => SIO.GPIO_OE_SET.raw = gpio.mask(), + .in => SIO.GPIO_OE_CLR.raw.write(gpio.mask()), + .out => SIO.GPIO_OE_SET.raw.write(gpio.mask()), } }, .RP2350 => { if (gpio.is_upper()) { switch (direction) { - .in => SIO.GPIO_HI_OE_CLR.raw = gpio.mask(), - .out => SIO.GPIO_HI_OE_SET.raw = gpio.mask(), + .in => SIO.GPIO_HI_OE_CLR.raw.write(gpio.mask()), + .out => SIO.GPIO_HI_OE_SET.raw.write(gpio.mask()), } } else { switch (direction) { - .in => SIO.GPIO_OE_CLR.raw = gpio.mask(), - .out => SIO.GPIO_OE_SET.raw = gpio.mask(), + .in => SIO.GPIO_OE_CLR.raw.write(gpio.mask()), + .out => SIO.GPIO_OE_SET.raw.write(gpio.mask()), } } }, @@ -367,20 +364,20 @@ pub const Pin = enum(u6) { switch (chip) { .RP2040 => { switch (value) { - 0 => SIO.GPIO_OUT_CLR.raw = gpio.mask(), - 1 => SIO.GPIO_OUT_SET.raw = gpio.mask(), + 0 => SIO.GPIO_OUT_CLR.raw.write(gpio.mask()), + 1 => SIO.GPIO_OUT_SET.raw.write(gpio.mask()), } }, .RP2350 => { if (gpio.is_upper()) { switch (value) { - 0 => SIO.GPIO_HI_OUT_CLR.raw = gpio.mask(), - 1 => SIO.GPIO_HI_OUT_SET.raw = gpio.mask(), + 0 => SIO.GPIO_HI_OUT_CLR.raw.write(gpio.mask()), + 1 => SIO.GPIO_HI_OUT_SET.raw.write(gpio.mask()), } } else { switch (value) { - 0 => SIO.GPIO_OUT_CLR.raw = gpio.mask(), - 1 => SIO.GPIO_OUT_SET.raw = gpio.mask(), + 0 => SIO.GPIO_OUT_CLR.raw.write(gpio.mask()), + 1 => SIO.GPIO_OUT_SET.raw.write(gpio.mask()), } } }, @@ -390,13 +387,13 @@ pub const Pin = enum(u6) { pub inline fn toggle(gpio: Pin) void { switch (chip) { .RP2040 => { - SIO.GPIO_OUT_XOR.raw = gpio.mask(); + SIO.GPIO_OUT_XOR.raw.write(gpio.mask()); }, .RP2350 => { if (gpio.is_upper()) { - SIO.GPIO_HI_OUT_XOR.raw = gpio.mask(); + SIO.GPIO_HI_OUT_XOR.raw.write(gpio.mask()); } else { - SIO.GPIO_OUT_XOR.raw = gpio.mask(); + SIO.GPIO_OUT_XOR.raw.write(gpio.mask()); } }, } @@ -405,19 +402,19 @@ pub const Pin = enum(u6) { pub inline fn read(gpio: Pin) u1 { switch (chip) { .RP2040 => { - return if ((SIO.GPIO_IN.raw & gpio.mask()) != 0) + return if ((SIO.GPIO_IN.raw.read() & gpio.mask()) != 0) 1 else 0; }, .RP2350 => { if (gpio.is_upper()) { - return if ((SIO.GPIO_HI_IN.raw & gpio.mask()) != 0) + return if ((SIO.GPIO_HI_IN.raw.read() & gpio.mask()) != 0) 1 else 0; } else { - return if ((SIO.GPIO_IN.raw & gpio.mask()) != 0) + return if ((SIO.GPIO_IN.raw.read() & gpio.mask()) != 0) 1 else 0; diff --git a/port/raspberrypi/rp2xxx/src/hal/i2c_slave.zig b/port/raspberrypi/rp2xxx/src/hal/i2c_slave.zig index a3fdd9145..3f9487b6e 100644 --- a/port/raspberrypi/rp2xxx/src/hal/i2c_slave.zig +++ b/port/raspberrypi/rp2xxx/src/hal/i2c_slave.zig @@ -43,20 +43,15 @@ //! If the master requests more data, we call the tx_callback with the `first` //! parameter set to `false`. The user can return 0 if no more data is available. //! - -const std = @import("std"); const microzig = @import("microzig"); const i2c = microzig.hal.i2c; -const mdf = microzig.drivers; const peripherals = microzig.chip.peripherals; const I2C0 = peripherals.I2C0; const I2C1 = peripherals.I2C1; const I2cRegs = microzig.chip.types.peripherals.I2C0; -const fifo_length = 16; - -const gpio = @import("gpio.zig"); +// const fifo_length = 16; pub const RXCallback = *const fn (data: []const u8, first: bool, last: bool, gen_call: bool, param: ?*anyopaque) void; pub const TXCallback = *const fn (data: []u8, first: bool, param: ?*anyopaque) usize; @@ -211,7 +206,7 @@ fn isr_common(self: *Self) void { // IC_CLR_INTR does not do this correctly. if (interruptStatus.TX_ABRT == .ACTIVE) { - self.regs.IC_CLR_TX_ABRT.raw = 0; + self.regs.IC_CLR_TX_ABRT.raw.write(0); } _ = self.regs.IC_CLR_INTR.read(); @@ -295,13 +290,13 @@ fn isr_common(self: *Self) void { // If we have no more data, fill the TX FIFO with zeros while (self.regs.IC_STATUS.read().TFNF == .NOT_FULL) { - self.regs.IC_DATA_CMD.write_raw(0); + self.regs.IC_DATA_CMD.raw.write(0); } } else { // Fill the TX FIFO with data from the transfer buffer while (self.transfer_index < self.transfer_length and self.regs.IC_STATUS.read().TFNF == .NOT_FULL) { - self.regs.IC_DATA_CMD.write_raw(@intCast(self.transfer_buffer[self.transfer_index])); + self.regs.IC_DATA_CMD.raw.write(@intCast(self.transfer_buffer[self.transfer_index])); self.transfer_index += 1; } } diff --git a/port/raspberrypi/rp2xxx/src/hal/multicore.zig b/port/raspberrypi/rp2xxx/src/hal/multicore.zig index 6bed8dfc4..4ed5dd556 100644 --- a/port/raspberrypi/rp2xxx/src/hal/multicore.zig +++ b/port/raspberrypi/rp2xxx/src/hal/multicore.zig @@ -1,6 +1,4 @@ -const builtin = @import("builtin"); const std = @import("std"); -const assert = std.debug.assert; const microzig = @import("microzig"); const interrupt = microzig.interrupt; @@ -9,7 +7,6 @@ const peripherals = microzig.chip.peripherals; const CriticalSection = interrupt.CriticalSection; const SIO = peripherals.SIO; const PSM = peripherals.PSM; -const PPB = peripherals.PPB; pub const fifo = struct { /// Check if the FIFO has valid data for reading. @@ -121,7 +118,7 @@ pub fn launch_core1_with_stack(entrypoint: *const fn () void, stack: []u32) void 0, 1, if (microzig.hal.compatibility.arch == .riscv) - microzig.cpu.csr.mtvec.read_raw() + microzig.cpu.csr.mtvec.raw.read() else microzig.cpu.peripherals.scb.VTOR, stack_ptr, @@ -160,7 +157,7 @@ pub const Spinlock = struct { lock_reg: *volatile u32, - const spinlock_base: usize = @intFromPtr(&SIO.SPINLOCK0.raw); + const spinlock_base: usize = @intFromPtr(&SIO.SPINLOCK0); /// Returns an initialized Spinlock struct. /// Parameters: diff --git a/port/raspberrypi/rp2xxx/src/hal/pins.zig b/port/raspberrypi/rp2xxx/src/hal/pins.zig index 94c6b2b64..08f961573 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pins.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pins.zig @@ -866,12 +866,12 @@ pub const GlobalConfiguration = struct { const used_gpios = comptime input_gpios | output_gpios; if (used_gpios != 0) { - SIO.GPIO_OE_CLR.raw = @truncate(used_gpios); - SIO.GPIO_OUT_CLR.raw = @truncate(used_gpios); + SIO.GPIO_OE_CLR.raw.write(@truncate(used_gpios)); + SIO.GPIO_OUT_CLR.raw.write(@truncate(used_gpios)); if (chip == .RP2350) { - SIO.GPIO_HI_OE_CLR.raw = @intCast(used_gpios >> 32); - SIO.GPIO_HI_OUT_CLR.raw = @intCast(used_gpios >> 32); + SIO.GPIO_HI_OE_CLR.raw.write(@intCast(used_gpios >> 32)); + SIO.GPIO_HI_OUT_CLR.raw.write(@intCast(used_gpios >> 32)); } } @@ -922,9 +922,9 @@ pub const GlobalConfiguration = struct { } if (output_gpios != 0) { - SIO.GPIO_OE_SET.raw = @truncate(output_gpios); + SIO.GPIO_OE_SET.raw.write(@truncate(output_gpios)); if (chip == .RP2350) - SIO.GPIO_HI_OE_SET.raw = @truncate(output_gpios >> 32); + SIO.GPIO_HI_OE_SET.raw.write(@truncate(output_gpios >> 32)); } inline for (@typeInfo(GlobalConfiguration).@"struct".field_names) |field_name| diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/common.zig b/port/raspberrypi/rp2xxx/src/hal/pio/common.zig index 315492531..5fc36fb02 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/common.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/common.zig @@ -12,6 +12,7 @@ pub const PIO1 = microzig.chip.peripherals.PIO1; pub const assembler = @import("assembler.zig"); const encoder = @import("assembler/encoder.zig"); const gpio = @import("../gpio.zig"); +const hw = @import("../hw.zig"); pub const ClkDivOptions = microzig.utilities.IntFracDiv(16, 8); pub const Instruction = encoder.Instruction; @@ -202,9 +203,9 @@ pub fn PioImpl(EnumType: type, chip: Chip) type { pub fn set_input_sync_bypass(self: EnumType, pin: gpio.Pin) !void { const index = try pin_to_index(self, pin); const mask = @as(u32, 1) << index; - var val = self.get_regs().INPUT_SYNC_BYPASS.raw; + var val = self.get_regs().INPUT_SYNC_BYPASS.raw.read(); val |= mask; - self.get_regs().INPUT_SYNC_BYPASS.write_raw(val); + self.get_regs().INPUT_SYNC_BYPASS.raw.write(val); } pub fn get_sm_regs(self: EnumType, sm: StateMachine) *volatile StateMachine.Regs { @@ -403,6 +404,18 @@ pub fn PioImpl(EnumType: type, chip: Chip) type { }); } + /// changing the state of fifos will clear them + pub fn sm_clear_fifos(self: EnumType, sm: StateMachine) void { + const sm_regs = self.get_sm_regs(sm); + const xor_shiftctrl = hw.xor_alias(&sm_regs.shiftctrl); + // Toggle twice + inline for (0..2) |_| + xor_shiftctrl.write_default_zero(.{ + .FJOIN_TX = 1, + .FJOIN_RX = 1, + }); + } + pub fn sm_fifo_level(self: EnumType, sm: StateMachine, fifo: Fifo) u4 { const snum = @intFromEnum(sm); const offset: u5 = switch (fifo) { @@ -411,7 +424,7 @@ pub fn PioImpl(EnumType: type, chip: Chip) type { }; const regs = self.get_regs(); - const levels = regs.FLEVEL.raw; + const levels = regs.FLEVEL.raw.read(); return @as(u4, @truncate(levels >> (@as(u5, 8) * snum) + offset)); } @@ -431,7 +444,7 @@ pub fn PioImpl(EnumType: type, chip: Chip) type { // TODO: why does the raw interrupt register no have irq1/0? _ = irq; const regs = self.get_regs(); - regs.IRQ.raw |= @as(u32, 1) << interrupt_bit_pos(sm, source); + regs.IRQ.raw.set(@as(u32, 1) << interrupt_bit_pos(sm, source)); } // TODO: be able to disable an interrupt @@ -442,7 +455,7 @@ pub fn PioImpl(EnumType: type, chip: Chip) type { source: Irq.Source, ) void { const irq_regs = self.get_irq_regs(irq); - irq_regs.enable.raw |= @as(u32, 1) << interrupt_bit_pos(sm, source); + irq_regs.enable.raw.set(@as(u32, 1) << interrupt_bit_pos(sm, source)); } pub fn sm_restart(self: EnumType, sm: StateMachine) void { @@ -495,7 +508,7 @@ pub fn PioImpl(EnumType: type, chip: Chip) type { pub fn sm_exec(self: EnumType, sm: StateMachine, instruction: Instruction(chip)) void { const sm_regs = self.get_sm_regs(sm); - sm_regs.instr.raw = @as(u16, @bitCast(instruction)); + sm_regs.instr.raw.write(@as(u16, @bitCast(instruction))); } pub fn sm_load_and_start_program( diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig b/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig index df1ab1775..67226d239 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig @@ -1,13 +1,5 @@ -const std = @import("std"); -const assert = std.debug.assert; - -const microzig = @import("microzig"); - const common = @import("common.zig"); - const gpio = @import("../gpio.zig"); -const resets = @import("../resets.zig"); -const hw = @import("../hw.zig"); pub const Pio = enum(u1) { pio0 = 0, @@ -77,26 +69,7 @@ pub const Pio = enum(u1) { pub const sm_set_enabled = PioImpl.sm_set_enabled; pub const sm_clear_debug = PioImpl.sm_clear_debug; - /// changing the state of fifos will clear them - pub fn sm_clear_fifos(self: Pio, sm: common.StateMachine) void { - const sm_regs = self.get_sm_regs(sm); - const xor_shiftctrl = hw.xor_alias(&sm_regs.shiftctrl); - const mask = @TypeOf(common.PIO0.SM0_SHIFTCTRL).underlying_type{ - .FJOIN_TX = 1, - .FJOIN_RX = 1, - - .AUTOPUSH = 0, - .AUTOPULL = 0, - .IN_SHIFTDIR = 0, - .OUT_SHIFTDIR = 0, - .PUSH_THRESH = 0, - .PULL_THRESH = 0, - }; - - xor_shiftctrl.write(mask); - xor_shiftctrl.write(mask); - } - + pub const sm_clear_fifos = PioImpl.sm_clear_fifos; pub const sm_fifo_level = PioImpl.sm_fifo_level; pub const sm_clear_interrupt = PioImpl.sm_clear_interrupt; pub const sm_enable_interrupt = PioImpl.sm_enable_interrupt; diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig b/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig index 0eacfa785..d5ac07f26 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig @@ -1,13 +1,7 @@ -const std = @import("std"); -const assert = std.debug.assert; - const microzig = @import("microzig"); const common = @import("common.zig"); - const gpio = @import("../gpio.zig"); -const resets = @import("../resets.zig"); -const hw = @import("../hw.zig"); const PIO2 = microzig.chip.peripherals.PIO2; @@ -47,7 +41,7 @@ pub const Pio = enum(u2) { pub const sm_set_clkdiv = PioImpl.sm_set_clkdiv; pub fn get_gpio_base(self: Pio) u32 { // Base is either 0 or 16 - return 0x10 & self.get_regs().GPIOBASE.raw; + return 0x10 & self.get_regs().GPIOBASE.raw.read(); } pub const sm_set_exec_options = PioImpl.sm_set_exec_options; @@ -86,30 +80,7 @@ pub const Pio = enum(u2) { pub const sm_set_enabled = PioImpl.sm_set_enabled; pub const sm_clear_debug = PioImpl.sm_clear_debug; - /// changing the state of fifos will clear them - pub fn sm_clear_fifos(self: Pio, sm: common.StateMachine) void { - const sm_regs = self.get_sm_regs(sm); - const xor_shiftctrl = hw.xor_alias(&sm_regs.shiftctrl); - const mask = @TypeOf(common.PIO0.SM0_SHIFTCTRL).underlying_type{ - .FJOIN_TX = 1, - .FJOIN_RX = 1, - - .AUTOPUSH = 0, - .AUTOPULL = 0, - .IN_SHIFTDIR = 0, - .OUT_SHIFTDIR = 0, - .PUSH_THRESH = 0, - .PULL_THRESH = 0, - - .FJOIN_RX_GET = 0, - .FJOIN_RX_PUT = 0, - .IN_COUNT = 0, - }; - - xor_shiftctrl.write(mask); - xor_shiftctrl.write(mask); - } - + pub const sm_clear_fifos = PioImpl.sm_clear_fifos; pub const sm_fifo_level = PioImpl.sm_fifo_level; pub const sm_clear_interrupt = PioImpl.sm_clear_interrupt; pub const sm_enable_interrupt = PioImpl.sm_enable_interrupt; diff --git a/port/raspberrypi/rp2xxx/src/hal/pwm.zig b/port/raspberrypi/rp2xxx/src/hal/pwm.zig index 3b63c40a8..9a6f2ba59 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pwm.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pwm.zig @@ -1,7 +1,5 @@ -const std = @import("std"); const microzig = @import("microzig"); const PWM = microzig.chip.peripherals.PWM; -const pins = microzig.hal.pins; const compatibility = @import("compatibility.zig"); const has_rp2350b = compatibility.has_rp2350b; @@ -197,7 +195,7 @@ pub fn set_channel_inversion( /// slice - the slice to set /// wrap - the wrap value pub fn set_slice_wrap(slice: u32, wrap: u16) void { - get_regs(slice).top.raw = wrap; + get_regs(slice).top.raw.write(wrap); } /// Set the level of the channel. This is the number of pwm clock diff --git a/port/raspberrypi/rp2xxx/src/hal/random.zig b/port/raspberrypi/rp2xxx/src/hal/random.zig index 393c8839f..3c7beab10 100644 --- a/port/raspberrypi/rp2xxx/src/hal/random.zig +++ b/port/raspberrypi/rp2xxx/src/hal/random.zig @@ -17,9 +17,9 @@ pub const trng = if (chip == .RP2350) struct { /// Generate a random number using the TRNG. /// Returns a random 32-bit unsigned integer, pub fn random_blocking() u32 { - TRNG.RND_SOURCE_ENABLE.raw = 1; + TRNG.RND_SOURCE_ENABLE.raw.write(1); - defer TRNG.RND_SOURCE_ENABLE.raw = 0; + defer TRNG.RND_SOURCE_ENABLE.raw.write(0); while (TRNG.TRNG_VALID.read().EHR_VALID == 0) {} @@ -30,39 +30,36 @@ pub const trng = if (chip == .RP2350) struct { /// Fill buffer with random data pub fn random_bytes_blocking(out: []u8) void { - var reg: *volatile u32 = &TRNG.EHR_DATA0.raw; + const first: [*]volatile u32 = @ptrCast(&TRNG.EHR_DATA0); + const last: [*]volatile u32 = @ptrCast(&TRNG.EHR_DATA5); + + var reg = first; var i: u32 = 0; if (out.len == 0) return; - TRNG.RND_SOURCE_ENABLE.raw = 1; - - defer TRNG.RND_SOURCE_ENABLE.raw = 0; + TRNG.RND_SOURCE_ENABLE.raw.write(1); + defer TRNG.RND_SOURCE_ENABLE.raw.write(0); while (i < out.len) { while (TRNG.TRNG_VALID.read().EHR_VALID == 0) {} - var data = reg.*; + var data = reg[0]; - if (reg == &TRNG.EHR_DATA5.raw) { - reg = &TRNG.EHR_DATA0.raw; - } else { - reg = @ptrFromInt(@intFromPtr(reg) + @sizeOf(u32)); - } + if (reg == last) reg = first else reg += 1; for (0..@min(4, out.len - i)) |j| { out[i + j] = @truncate(data); data >>= 8; } - i += 4; + i += @sizeOf(u32); } // If we didn't read all the data, read DATA5 to clear the buffer - if (reg != &TRNG.EHR_DATA0.raw) { + if (reg != first) _ = TRNG.EHR_DATA5.read().EHR_DATA5; - } } /// Generate an internal reset in the RNG block. diff --git a/port/raspberrypi/rp2xxx/src/hal/resets.zig b/port/raspberrypi/rp2xxx/src/hal/resets.zig index 6aafe637f..b2175d37c 100644 --- a/port/raspberrypi/rp2xxx/src/hal/resets.zig +++ b/port/raspberrypi/rp2xxx/src/hal/resets.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const EnumField = std.builtin.Type.EnumField; const microzig = @import("microzig"); const RESETS = microzig.chip.peripherals.RESETS; @@ -85,24 +84,24 @@ pub const Mask = pub fn reset(mask: Mask) void { const raw_mask: u32 = @bitCast(mask); - RESETS.RESET.write_raw(raw_mask); - RESETS.RESET.write_raw(0); + RESETS.RESET.raw.write(raw_mask); + RESETS.RESET.raw.write(0); wait_for_reset_done(mask); } pub inline fn reset_block(mask: Mask) void { - hw.set_alias(RESETS).RESET.write_raw(@bitCast(mask)); + hw.set_alias(RESETS).RESET.raw.write(@bitCast(mask)); } pub inline fn unreset_block(mask: Mask) void { - hw.clear_alias(RESETS).RESET.write_raw(@bitCast(mask)); + hw.clear_alias(RESETS).RESET.raw.write(@bitCast(mask)); } pub fn unreset_block_wait(mask: Mask) void { const raw_mask: u32 = @bitCast(mask); - hw.clear_alias(RESETS).RESET.write_raw(raw_mask); + hw.clear_alias(RESETS).RESET.raw.write(raw_mask); wait_for_reset_done(mask); } @@ -110,7 +109,7 @@ pub fn unreset_block_wait(mask: Mask) void { inline fn wait_for_reset_done(mask: Mask) void { const raw_mask: u32 = @bitCast(mask); - // have to bitcast after a read() instead of `RESETS.RESET_DONE.raw` due to + // have to bitcast after a read() instead of `RESETS.RESET_DONE.raw.read()` due to // some optimization bug. While loops will not be optimzed away if the // condition has side effects like dereferencing a volatile pointer. // It seems that volatile is not propagating correctly. diff --git a/port/raspberrypi/rp2xxx/src/hal/spi.zig b/port/raspberrypi/rp2xxx/src/hal/spi.zig index 7c0c7ea5f..6e9e47dc7 100644 --- a/port/raspberrypi/rp2xxx/src/hal/spi.zig +++ b/port/raspberrypi/rp2xxx/src/hal/spi.zig @@ -6,8 +6,6 @@ const SPI1_reg = peripherals.SPI1; const clocks = @import("clocks.zig"); const dma = @import("dma.zig"); -const resets = @import("resets.zig"); -const time = @import("time.zig"); const hw = @import("hw.zig"); const SpiRegs = microzig.chip.types.peripherals.SPI0; @@ -213,7 +211,7 @@ pub const SPI = enum(u1) { var count: usize = 0; while (spi.is_writable()) { const element = src_iter.next_element() orelse break; - spi_regs.SSPDR.write_raw(element.value); + spi_regs.SSPDR.raw.write(element.value); count += 1; } spi_regs.SSPCR1.modify(.{ @@ -230,7 +228,7 @@ pub const SPI = enum(u1) { }); var tx_remaining = repeat_count; while (tx_remaining > 0 and spi.is_writable()) { - spi_regs.SSPDR.write_raw(repeated_byte); + spi_regs.SSPDR.raw.write(repeated_byte); tx_remaining -= 1; } spi_regs.SSPCR1.modify(.{ @@ -279,7 +277,7 @@ pub const SPI = enum(u1) { while (rx_remaining > 0 or tx_remaining > 0) { if (tx_remaining > 0 and spi.is_writable() and rx_remaining < tx_remaining + fifo_depth) { const element = src_iter.next_element() orelse unreachable; - spi_regs.SSPDR.write_raw(element.value); + spi_regs.SSPDR.raw.write(element.value); tx_remaining -= 1; } if (rx_remaining > 0 and spi.is_readable()) { @@ -330,7 +328,7 @@ pub const SPI = enum(u1) { while (!spi.is_writable()) { hw.tight_loop_contents(); } - spi_regs.SSPDR.write_raw(element.value); + spi_regs.SSPDR.raw.write(element.value); } // Drain RX FIFO, then wait for shifting to finish (which may be *after* @@ -387,7 +385,7 @@ pub const SPI = enum(u1) { tx_remaining -= spi.prime_tx_fifo_repeated(PacketType, repeated_tx_data, tx_remaining); while (rx_remaining > 0 or tx_remaining > 0) { if (tx_remaining > 0 and spi.is_writable() and rx_remaining < tx_remaining + fifo_depth) { - spi_regs.SSPDR.write_raw(repeated_tx_data); + spi_regs.SSPDR.raw.write(repeated_tx_data); tx_remaining -= 1; } if (rx_remaining > 0 and spi.is_readable()) { diff --git a/port/raspberrypi/rp2xxx/src/hal/system_timer.zig b/port/raspberrypi/rp2xxx/src/hal/system_timer.zig index dc1455ad9..f479fcbe1 100644 --- a/port/raspberrypi/rp2xxx/src/hal/system_timer.zig +++ b/port/raspberrypi/rp2xxx/src/hal/system_timer.zig @@ -54,7 +54,7 @@ pub const Timer = enum(u1) { /// Clears the interrupt flag for the given alarm. pub fn clear_interrupt(timer: Timer, alarm: Alarm) void { const regs = timer.get_regs(); - regs.INTR.write_raw(@as(u4, 1) << @intFromEnum(alarm)); + regs.INTR.raw.write(@as(u4, 1) << @intFromEnum(alarm)); } /// Schedules an alarm to be triggered when the low word of the timer diff --git a/port/raspberrypi/rp2xxx/src/hal/uart.zig b/port/raspberrypi/rp2xxx/src/hal/uart.zig index a175e71e7..b37245275 100644 --- a/port/raspberrypi/rp2xxx/src/hal/uart.zig +++ b/port/raspberrypi/rp2xxx/src/hal/uart.zig @@ -278,7 +278,7 @@ pub const UART = enum(u1) { }); var tx_remaining = src.len; while (tx_remaining > 0 and uart.is_writeable()) { - uart_regs.UARTDR.write_raw(src[src.len - tx_remaining]); + uart_regs.UARTDR.raw.write(src[src.len - tx_remaining]); tx_remaining -= 1; } uart_regs.UARTCR.modify(.{ @@ -372,7 +372,7 @@ pub const UART = enum(u1) { while (!uart.is_writeable()) { try deadline.check(time.get_time_since_boot()); } - uart_regs.UARTDR.write_raw(payload[offset]); + uart_regs.UARTDR.raw.write(payload[offset]); offset += 1; written += 1; } diff --git a/port/raspberrypi/rp2xxx/src/hal/usb.zig b/port/raspberrypi/rp2xxx/src/hal/usb.zig index db0957ba1..20038c5f9 100644 --- a/port/raspberrypi/rp2xxx/src/hal/usb.zig +++ b/port/raspberrypi/rp2xxx/src/hal/usb.zig @@ -9,6 +9,7 @@ const log = std.log.scoped(.usb_dev); const microzig = @import("microzig"); const peripherals = microzig.chip.peripherals; +const peri_types = microzig.chip.types.peripherals; const chip = microzig.hal.compatibility.chip; const usb = microzig.core.usb; @@ -65,10 +66,10 @@ fn PerEndpoint(T: type) type { } // It would be nice to instead generate those arrays automatically with a regz patch. -const BufferControlMmio = microzig.mmio.Mmio(@TypeOf(peripherals.USB_DPRAM.EP0_IN_BUFFER_CONTROL).underlying_type); +const BufferControlMmio = @FieldType(peri_types.USB_DPRAM, "EP0_IN_BUFFER_CONTROL"); const buffer_control: *volatile [16]PerEndpoint(BufferControlMmio) = @ptrCast(&peripherals.USB_DPRAM.EP0_IN_BUFFER_CONTROL); -const EndpointControlMmio = microzig.mmio.Mmio(@TypeOf(peripherals.USB_DPRAM.EP1_IN_CONTROL).underlying_type); +const EndpointControlMmio = @FieldType(peri_types.USB_DPRAM, "EP1_IN_CONTROL"); const endpoint_control: *volatile [15]PerEndpoint(EndpointControlMmio) = @ptrCast(&peripherals.USB_DPRAM.EP1_IN_CONTROL); // +++++++++++++++++++++++++++++++++++++++++++++++++ @@ -121,12 +122,12 @@ pub fn Polled(config: Config) type { buffer_control[0].in.modify(.{ .PID_0 = 0 }); // Clear the status flag (write-one-to-clear) - peripherals.USB.SIE_STATUS.modify(.{ .SETUP_REC = 1 }); + peripherals.USB.SIE_STATUS.write_default_zero(.{ .SETUP_REC = 1 }); // The SVD exposes this buffer as two 32-bit registers. const setup: usb.types.SetupPacket = @bitCast([2]u32{ - peripherals.USB_DPRAM.SETUP_PACKET_LOW.raw, - peripherals.USB_DPRAM.SETUP_PACKET_HIGH.raw, + peripherals.USB_DPRAM.SETUP_PACKET_LOW.raw.read(), + peripherals.USB_DPRAM.SETUP_PACKET_HIGH.raw.read(), }); log.debug("setup {any}", .{setup}); @@ -137,7 +138,7 @@ pub fn Polled(config: Config) type { if (ints.BUFF_STATUS != 0) { log.debug("-- buffer status --", .{}); - const buff_status = peripherals.USB.BUFF_STATUS.raw; + const buff_status = peripherals.USB.BUFF_STATUS.raw.read(); inline for (0..2 * config.max_endpoints_count) |shift| { if (buff_status & (@as(u32, 1) << shift) != 0) { @@ -162,7 +163,7 @@ pub fn Polled(config: Config) type { controller.on_buffer(&self.interface, ep); } } - peripherals.USB.BUFF_STATUS.raw = buff_status; + peripherals.USB.BUFF_STATUS.raw.write(buff_status); } // Has the host signaled a bus reset? @@ -183,17 +184,17 @@ pub fn Polled(config: Config) type { // Clear the control portion of DPRAM. This may not be necessary -- the // datasheet is ambiguous -- but the C examples do it, and so do we. - peripherals.USB_DPRAM.SETUP_PACKET_LOW.write_raw(0); - peripherals.USB_DPRAM.SETUP_PACKET_HIGH.write_raw(0); + peripherals.USB_DPRAM.SETUP_PACKET_LOW.raw.write(0); + peripherals.USB_DPRAM.SETUP_PACKET_HIGH.raw.write(0); for (1..config.max_endpoints_count) |i| { - endpoint_control[i - 1].in.write_raw(0); - endpoint_control[i - 1].out.write_raw(0); + endpoint_control[i - 1].in.raw.write(0); + endpoint_control[i - 1].out.raw.write(0); } for (0..config.max_endpoints_count) |i| { - buffer_control[i].in.write_raw(0); - buffer_control[i].out.write_raw(0); + buffer_control[i].in.raw.write(0); + buffer_control[i].out.raw.write(0); } // Mux the controller to the onboard USB PHY. I was surprised that there are diff --git a/port/stmicro/stm32/src/hals/STM32F103/adc.zig b/port/stmicro/stm32/src/hals/STM32F103/adc.zig index b808bf031..f446fae10 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/adc.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/adc.zig @@ -1,4 +1,3 @@ -const std = @import("std"); const microzig = @import("microzig"); const enums = @import("../common/enums.zig"); const periferals = microzig.chip.peripherals; @@ -39,7 +38,7 @@ pub const ADC = struct { pub fn enable(self: *const ADC) void { const regs = self.regs; - regs.CR2.raw = 0; //force reset + regs.CR2.raw.write(0); //force reset regs.CR2.modify(.{ .ADON = 1 }); //enable ADC //wait for ADC stabilization time @@ -51,7 +50,7 @@ pub const ADC = struct { while (regs.CR2.read().CAL == 1) { asm volatile ("" ::: .{ .memory = true }); } - regs.SR.raw = 0; //clear all status flags + regs.SR.raw.write(0); //clear all status flags regs.CR2.modify(.{ .TSVREFE = 1, //enable temperature sensor and Vrefint @@ -64,7 +63,7 @@ pub const ADC = struct { pub fn disable(self: *const ADC) void { const regs = self.regs; - regs.CR2.raw = 0; //force reset + regs.CR2.raw.write(0); //force reset } pub fn set_channel_sample_rate(self: *const ADC, channel: u5, sample_rate: SampleRate) void { @@ -74,9 +73,9 @@ pub const ADC = struct { const rate: u32 = @intFromEnum(sample_rate); const smpr_val = rate << (smpr_index * 3); if (channel < 10) { - regs.SMPR2.raw |= smpr_val; + regs.SMPR2.raw.set(smpr_val); } else { - regs.SMPR1.raw |= smpr_val; + regs.SMPR1.raw.set(smpr_val); } } @@ -119,11 +118,11 @@ pub const ADC = struct { const bit_index: u5 = @intCast((index % 6) * 5); //each channel takes 5 bits const mask = @as(u32, sq) << bit_index; if (index < 6) { - regs.SQR3.raw |= mask; //load into SQR3 + regs.SQR3.raw.set(mask); //load into SQR3 } else if (index < 12) { - regs.SQR2.raw |= mask; //load into SQR2 + regs.SQR2.raw.set(mask); //load into SQR2 } else { - regs.SQR1.raw |= mask; //load into SQR1 + regs.SQR1.raw.set(mask); //load into SQR1 } } regs.SQR1.modify(.{ .L = @as(u4, @intCast(len - 1)) }); //set number of conversions @@ -140,7 +139,7 @@ pub const ADC = struct { const len = @min(recv.len, seq_len); const to_read = recv[0..len]; - regs.SR.raw = 0; //clear all status flag + regs.SR.raw.write(0); //clear all status flag regs.CR1.modify(.{ .DISCEN = 1, @@ -157,7 +156,7 @@ pub const ADC = struct { regs.CR2.modify(.{ .SWSTART = 1 }); //start conversion, if software trigger is not enabled, this will do nothing } - regs.SR.raw = 0; //clear all status flag + regs.SR.raw.write(0); //clear all status flag regs.CR1.modify(.{ .DISCEN = 0, @@ -401,13 +400,13 @@ pub const AdvancedADC = struct { /// NOTE: this is also put the ADC in power down mode. pub fn clear_config(self: *const AdvancedADC) void { const regs = self.regs; - regs.CR2.raw = 0; //force reset - regs.CR1.raw = 0; //force reset - regs.SQR1.raw = 0; //force reset - regs.SQR2.raw = 0; //force reset - regs.SQR3.raw = 0; //force reset - regs.SMPR1.raw = 0; //force reset - regs.SMPR2.raw = 0; //force reset + regs.CR2.raw.write(0); //force reset + regs.CR1.raw.write(0); //force reset + regs.SQR1.raw.write(0); //force reset + regs.SQR2.raw.write(0); //force reset + regs.SQR3.raw.write(0); //force reset + regs.SMPR1.raw.write(0); //force reset + regs.SMPR2.raw.write(0); //force reset } ///calibrate the ADC and return the calibration data. @@ -454,13 +453,13 @@ pub const AdvancedADC = struct { } pub fn read_flags(self: *const AdvancedADC) Flags { - const val: u5 = @truncate(self.regs.SR.raw); + const val: u5 = @truncate(self.regs.SR.raw.read()); return @bitCast(val); } pub fn clear_flags(self: *const AdvancedADC, flags: Flags) void { const val: u5 = @bitCast(flags); - self.regs.SR.raw &= ~val; + self.regs.SR.raw.clear(val); } //========== ADC Regular conversion functions =========== @@ -568,9 +567,9 @@ pub const AdvancedADC = struct { const rate: u32 = @intFromEnum(sample_rate); const smpr_val = rate << (smpr_index * 3); if (channel < 10) { - regs.SMPR2.raw |= smpr_val; + regs.SMPR2.raw.set(smpr_val); } else { - regs.SMPR1.raw |= smpr_val; + regs.SMPR1.raw.set(smpr_val); } } @@ -597,11 +596,11 @@ pub const AdvancedADC = struct { const bit_index: u5 = @intCast((index % 6) * 5); //each channel takes 5 bits const mask = @as(u32, sq) << bit_index; if (index < 6) { - regs.SQR3.raw |= mask; //load into SQR3 + regs.SQR3.raw.set(mask); //load into SQR3 } else if (index < 12) { - regs.SQR2.raw |= mask; //load into SQR2 + regs.SQR2.raw.set(mask); //load into SQR2 } else { - regs.SQR1.raw |= mask; //load into SQR1 + regs.SQR1.raw.set(mask); //load into SQR1 } } regs.SQR1.modify(.{ .L = @as(u4, @intCast(len - 1)) }); //set number of conversions @@ -795,7 +794,7 @@ pub const AdvancedADC = struct { for (sequence[0..len], sti..4) |sq, index| { const bit_index: usize = index * 5; //each channel takes 5 bits const mask = @as(u32, sq) << @as(u5, @truncate(bit_index)); - regs.JSQR.raw |= mask; //load into JSQR + regs.JSQR.raw.set(mask); //load into JSQR } regs.JSQR.modify(.{ .JL = @as(u2, @intCast(len - 1)) }); //set number of conversions diff --git a/port/stmicro/stm32/src/hals/STM32F103/crc.zig b/port/stmicro/stm32/src/hals/STM32F103/crc.zig index f453f3a6a..6b089958a 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/crc.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/crc.zig @@ -1,4 +1,3 @@ -const std = @import("std"); const microzig = @import("microzig"); const crc = microzig.chip.peripherals.CRC; @@ -15,7 +14,7 @@ pub inline fn read() u32 { ///reset the CRC calculation unit pub inline fn reset() void { - crc.CR.raw = 0x1; // reset bit + crc.CR.raw.write(0x1); // reset bit } ///load a value into the CRC independent data register (just a single byte) diff --git a/port/stmicro/stm32/src/hals/STM32F103/exti.zig b/port/stmicro/stm32/src/hals/STM32F103/exti.zig index 4d5980615..4046c8644 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/exti.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/exti.zig @@ -58,62 +58,64 @@ pub fn apply_line(config: Config) void { } pub fn set_line(line: u4, port: gpio.Port) void { - const reg_idx: usize = line / 4; const shift = (@as(u5, line) % 4) * 4; const port_sel: u32 = @intFromEnum(port); - AFIO.EXTICR[reg_idx].raw &= ~(@as(u32, 0xF) << shift); //clear the current value - AFIO.EXTICR[reg_idx].raw |= (port_sel << shift); //set the port value + AFIO.EXTICR[line / 4].raw.modify( + @as(u32, 0xF) << shift, //clear the current value + port_sel << shift, //set the port value + ); } pub fn set_line_edge(line: u5, edge: TriggerEdge) void { + const mask = @as(u32, 1) << line; switch (edge) { .None => { - EXTI.@"RTSR[0]".raw &= ~(@as(u32, 1) << line); - EXTI.@"FTSR[0]".raw &= ~(@as(u32, 1) << line); + EXTI.@"RTSR[0]".raw.clear(mask); + EXTI.@"FTSR[0]".raw.clear(mask); }, .rising => { - EXTI.@"RTSR[0]".raw |= (@as(u32, 1) << line); - EXTI.@"FTSR[0]".raw &= ~(@as(u32, 1) << line); + EXTI.@"RTSR[0]".raw.set(mask); + EXTI.@"FTSR[0]".raw.clear(mask); }, .falling => { - EXTI.@"RTSR[0]".raw &= ~(@as(u32, 1) << line); - EXTI.@"FTSR[0]".raw |= (@as(u32, 1) << line); + EXTI.@"RTSR[0]".raw.clear(mask); + EXTI.@"FTSR[0]".raw.set(mask); }, .both => { - EXTI.@"RTSR[0]".raw |= (@as(u32, 1) << line); - EXTI.@"FTSR[0]".raw |= (@as(u32, 1) << line); + EXTI.@"RTSR[0]".raw.set(mask); + EXTI.@"FTSR[0]".raw.set(mask); }, } } pub fn set_event(line: u5, enable: bool) void { - if (enable) { - EXTI.@"EMR[0]".raw |= (@as(u32, 1) << line); - } else { - EXTI.@"EMR[0]".raw &= ~(@as(u32, 1) << line); - } + const mask = @as(u32, 1) << line; + if (enable) + EXTI.@"EMR[0]".raw.set(mask) + else + EXTI.@"EMR[0]".raw.clear(mask); } pub fn set_interrupt(line: u5, enable: bool) void { - if (enable) { - EXTI.@"IMR[0]".raw |= (@as(u32, 1) << line); - } else { - EXTI.@"IMR[0]".raw &= ~(@as(u32, 1) << line); - } + const mask = @as(u32, 1) << line; + if (enable) + EXTI.@"IMR[0]".raw.set(mask) + else + EXTI.@"IMR[0]".raw.clear(mask); } ///force a software trigger on the given line /// this trigger is cleared by `clear_pending()` pub inline fn software_trigger(line: u5) void { - EXTI.SWIER.raw |= (@as(u32, 1) << line); + EXTI.SWIER.raw.set(@as(u32, 1) << line); } ///check for pending lines (for both events and interrupts) pub inline fn pending() pendingLine { - return @bitCast(@as(u20, @intCast(EXTI.@"PR[0]".raw))); + return @bitCast(@as(u20, @intCast(EXTI.@"PR[0]".raw.read()))); } ///clears all pending lines returned by: `pending()`. pub inline fn clear_pending(pendings: pendingLine) void { - EXTI.@"PR[0]".raw = @as(u20, @bitCast(pendings)); + EXTI.@"PR[0]".raw.write(@as(u20, @bitCast(pendings))); } diff --git a/port/stmicro/stm32/src/hals/STM32F103/gpio.zig b/port/stmicro/stm32/src/hals/STM32F103/gpio.zig index e37e340e1..323a24cdd 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/gpio.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/gpio.zig @@ -1,6 +1,3 @@ -const std = @import("std"); -const assert = std.debug.assert; - const microzig = @import("microzig"); pub const peripherals = microzig.chip.peripherals; @@ -72,15 +69,11 @@ pub const Pin = enum(usize) { inline fn write_pin_config(gpio: Pin, config: u32) void { const port = gpio.get_port(); const pin: u4 = @intCast(@intFromEnum(gpio) % 16); - if (pin <= 7) { - const offset = @as(u5, pin) << 2; - port.CR[0].raw &= ~(@as(u32, 0b1111) << offset); - port.CR[0].raw |= config << offset; - } else { - const offset = (@as(u5, pin) - 8) << 2; - port.CR[1].raw &= ~(@as(u32, 0b1111) << offset); - port.CR[1].raw |= config << offset; - } + const offset = @as(u5, @as(u3, @truncate(pin))) << 2; + port.CR[pin >> 3].raw.modify( + @as(u32, 0b1111) << offset, + config << offset, + ); } fn mask(gpio: Pin) u32 { @@ -132,30 +125,27 @@ pub const Pin = enum(usize) { pub inline fn set_pull(gpio: Pin, pull: Pull) void { var port = gpio.get_port(); switch (pull) { - .up => port.BSRR.raw = gpio.mask(), - .down => port.BRR.raw = gpio.mask(), + .up => port.BSRR.raw.write(gpio.mask()), + .down => port.BRR.raw.write(gpio.mask()), } } pub inline fn read(gpio: Pin) u1 { const port = gpio.get_port(); - return if (port.IDR.raw & gpio.mask() != 0) - 1 - else - 0; + @intFromBool(port.IDR.raw.read() & gpio.mask() != 0); } pub inline fn put(gpio: Pin, value: u1) void { var port = gpio.get_port(); switch (value) { - 0 => port.BSRR.raw = @intCast(gpio.mask() << 16), - 1 => port.BSRR.raw = gpio.mask(), + 0 => port.BSRR.raw.write(@intCast(gpio.mask() << 16)), + 1 => port.BSRR.raw.write(gpio.mask()), } } pub inline fn toggle(gpio: Pin) void { var port = gpio.get_port(); - port.ODR.raw ^= gpio.mask(); + port.ODR.raw.toggle(gpio.mask()); } pub fn num(pin: usize) Pin { diff --git a/port/stmicro/stm32/src/hals/STM32F103/i2c.zig b/port/stmicro/stm32/src/hals/STM32F103/i2c.zig index 37dc21d8c..a82137973 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/i2c.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/i2c.zig @@ -6,7 +6,6 @@ const enums = @import("../common/enums.zig"); const I2C_Peripheral = microzig.chip.types.peripherals.i2c_v1.I2C; const DUTY = microzig.chip.types.peripherals.i2c_v1.DUTY; const F_S = microzig.chip.types.peripherals.i2c_v1.F_S; -const peripherals = microzig.chip.peripherals; const mdf = microzig.drivers; const drivers = mdf.base; const Duration = mdf.time.Duration; @@ -309,8 +308,8 @@ pub const I2C = struct { fn clear_flags(i2c: *const I2C) void { const regs = i2c.regs; //clear ADDR register - std.mem.doNotOptimizeAway(regs.SR1.raw); - std.mem.doNotOptimizeAway(regs.SR2.raw); + std.mem.doNotOptimizeAway(regs.SR1.raw.read()); + std.mem.doNotOptimizeAway(regs.SR2.raw.read()); } fn send_7bits_addr(i2c: *const I2C, addr: u10, IO: u1, deadline: Deadline) Error!void { diff --git a/port/stmicro/stm32/src/hals/STM32F103/pins.zig b/port/stmicro/stm32/src/hals/STM32F103/pins.zig index b3ec0fc88..8f39ea1db 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/pins.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/pins.zig @@ -175,9 +175,9 @@ pub const GlobalConfiguration = struct { if (used_gpios != 0) { const offset = @intFromEnum(@field(Port, port_field_name)) + 2; const bit = @as(u32, 1 << offset); - RCC.APB2ENR.raw |= bit; + RCC.APB2ENR.raw.set(bit); // Delay after setting - _ = RCC.APB2ENR.raw & bit; + _ = RCC.APB2ENR.raw.read() & bit; } inline for (@typeInfo(Port.Configuration).@"struct".field_names) |field_name| { diff --git a/port/stmicro/stm32/src/hals/STM32F103/rcc.zig b/port/stmicro/stm32/src/hals/STM32F103/rcc.zig index 21f70c452..e1d34757c 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/rcc.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/rcc.zig @@ -138,8 +138,8 @@ pub inline fn set_flash(latency: flash_v1.LATENCY, prefetch: bool) void { pub fn secure_enable() void { set_hsi(true); - rcc.BDCR.raw = 0; - rcc.CFGR.raw = 0; + rcc.BDCR.raw.write(0); + rcc.CFGR.raw.write(0); while (rcc.CFGR.read().SWS != .HSI) { asm volatile (""); } @@ -388,7 +388,7 @@ pub fn reset_clock(comptime peri: Peripherals) void { @field(rcc, rcc_register_name).modify_one(field, 1); //release the reset, this is necessary because the reset bits are not self-clearing //write 0 to all bits is safe becuse 0 does nothing (other than releasing the reset) - @field(rcc, rcc_register_name).raw = 0; + @field(rcc, rcc_register_name).raw.write(0); } pub fn set_clock(comptime peri: Peripherals, state: u1) void { @@ -426,16 +426,16 @@ pub fn disable_clock(comptime peri: Peripherals) void { pub fn enable_all_clocks() void { //enable all clocks - rcc.AHBENR.raw = std.math.maxInt(u32); - rcc.APB1ENR.raw = std.math.maxInt(u32); - rcc.APB2ENR.raw = std.math.maxInt(u32); + rcc.AHBENR.raw.write(std.math.maxInt(u32)); + rcc.APB1ENR.raw.write(std.math.maxInt(u32)); + rcc.APB2ENR.raw.write(std.math.maxInt(u32)); } pub fn disable_all_clocks() void { //disable all clocks - rcc.AHBENR.raw = 0; - rcc.APB1ENR.raw = 0; - rcc.APB2ENR.raw = 0; + rcc.AHBENR.raw.write(0); + rcc.APB1ENR.raw.write(0); + rcc.APB2ENR.raw.write(0); } ///Reset all periferals of the specified bus to they default state. @@ -446,12 +446,12 @@ pub fn reset_bus(bus: Bus) void { //this is necessary because the reset bits are not self-clearing switch (bus) { .APB1 => { - rcc.APB1RSTR.raw = std.math.maxInt(u32); - rcc.APB1RSTR.raw = 0; + rcc.APB1RSTR.raw.write(std.math.maxInt(u32)); + rcc.APB1RSTR.raw.write(0); }, .APB2 => { - rcc.APB2RSTR.raw = std.math.maxInt(u32); - rcc.APB2RSTR.raw = 0; + rcc.APB2RSTR.raw.write(std.math.maxInt(u32)); + rcc.APB2RSTR.raw.write(0); }, } } diff --git a/port/stmicro/stm32/src/hals/STM32F103/spi.zig b/port/stmicro/stm32/src/hals/STM32F103/spi.zig index aae2284e8..e59529813 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/spi.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/spi.zig @@ -27,7 +27,7 @@ pub const SPI = struct { spi: *volatile SPI_Peripheral, pub fn apply(self: *const SPI, config: Config) void { - self.spi.CR1.raw = 0; // Disable SPI end clear configs before configuration + self.spi.CR1.raw.write(0); // Disable SPI end clear configs before configuration self.spi.CR1.modify(.{ .CPOL = config.polarity, .CPHA = config.phase, @@ -67,7 +67,7 @@ pub const SPI = struct { //trasmite only procedure | RM008 page 721 pub fn write_blocking(self: *const SPI, data: []const u8) void { for (data) |byte| { - self.spi.DR.raw = byte; + self.spi.DR.raw.write(byte); while (!self.check_TX()) {} } self.busy_wait(); @@ -78,15 +78,15 @@ pub const SPI = struct { } pub fn read_blocking(self: *const SPI, data: []u8) void { - self.spi.DR.raw = 0; + self.spi.DR.raw.write(0); for (data) |*byte| { //send dummy byte to generate clock while (!(self.check_TX())) {} - self.spi.DR.raw = 0; // send dummy byte + self.spi.DR.raw.write(0); // send dummy byte //wait for data to be received while (!(self.check_RX())) {} - byte.* = @intCast(self.spi.DR.raw & 0xFF); + byte.* = @intCast(self.spi.DR.raw.read() & 0xFF); } self.busy_wait(); @@ -111,19 +111,19 @@ pub const SPI = struct { //load the first byte //the RX value will be loaded into the shift register, and will be loaded into the DR register after the first clock cycle - self.spi.DR.raw = out[0]; + self.spi.DR.raw.write(out[0]); while ((out_remain > 0) or (in_remain > 0)) { while (!check_TX(self)) {} if (out_remain > 0) { - self.spi.DR.raw = out[out_len - out_remain]; + self.spi.DR.raw.write(out[out_len - out_remain]); out_remain -= 1; } else { - self.spi.DR.raw = 0; // send dummy byte + self.spi.DR.raw.write(0); // send dummy byte } while (!check_RX(self)) {} if (in_remain > 0) { - in[in_len - in_remain] = @intCast(self.spi.DR.raw & 0xFF); + in[in_len - in_remain] = @intCast(self.spi.DR.raw.read() & 0xFF); in_remain -= 1; } } diff --git a/port/stmicro/stm32/src/hals/STM32F103/uart.zig b/port/stmicro/stm32/src/hals/STM32F103/uart.zig index 2cfae299f..e2d03fdd4 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/uart.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/uart.zig @@ -9,11 +9,9 @@ const enums = @import("../common/enums.zig"); const assert = std.debug.assert; const mdf = microzig.drivers; -const drivers = mdf.base; const Duration = mdf.time.Duration; const Deadline = mdf.time.Deadline; -const peripherals = microzig.chip.peripherals; const USART_Peripheral = microzig.chip.types.peripherals.usart_v1.USART; const M0 = microzig.chip.types.peripherals.usart_v1.M0; const PS = microzig.chip.types.peripherals.usart_v1.PS; @@ -161,7 +159,7 @@ pub const UART = struct { frac = frac % 16; const value: u32 = 0xFFFF & ((mantissa << 4) | frac); - regs.BRR.raw = value; + regs.BRR.raw.write(value); } fn set_wordbits(uart: *const UART, word: WordBits) void { @@ -234,7 +232,7 @@ pub const UART = struct { while (!uart.is_writeable()) { if (deadline.is_reached_by(time.get_time_since_boot())) return error.Timeout; } - regs.DR.raw = @intCast(byte); + regs.DR.raw.write(@intCast(byte)); n += 1; } } @@ -261,7 +259,7 @@ pub const UART = struct { } else if (SR.PE != 0) { return error.ParityError; } - const rx = regs.DR.raw; + const rx = regs.DR.raw.read(); bytes.* = @intCast(0xFF & rx); n += 1; @@ -283,8 +281,8 @@ pub const UART = struct { pub inline fn clear_errors(uart: *const UART) void { const regs = uart.regs; - std.mem.doNotOptimizeAway(regs.SR.raw); - std.mem.doNotOptimizeAway(regs.DR.raw); + std.mem.doNotOptimizeAway(regs.SR.raw.read()); + std.mem.doNotOptimizeAway(regs.DR.raw.read()); } pub fn write_blocking(uart: *const UART, data: []const u8, timeout: ?Duration) TransmitError!usize { diff --git a/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig b/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig index 6a8d615c5..f137d11a5 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_ll.zig @@ -10,25 +10,6 @@ const Deadline = microzig.drivers.time.Deadline; const USB = microzig.chip.peripherals.USB; const USBTypes = microzig.chip.types.peripherals.usb_v1; -const ep_test = packed struct(u16) { - ep0: u1, - ep1: u1, - ep2: u1, - ep3: u1, - ep4: u1, - ep5: u1, - ep6: u1, - ep7: u1, - ep8: u1, - ep9: u1, - ep10: u1, - ep11: u1, - ep12: u1, - ep13: u1, - ep14: u1, - ep15: u1, -}; - const InitError = error{ UsbAlreadyEnabled, InvalidEPC, @@ -303,8 +284,8 @@ fn inner_init(config: Config, PMA_conf: PMA.Config, startup: Duration) InitError while (USB.ISTR.read().RESET == 0) { asm volatile ("nop"); } - USB.CNTR.raw = 0; - USB.ISTR.raw = 0; + USB.CNTR.raw.write(0); + USB.ISTR.raw.write(0); for (config.endpoints) |ep_conf| { const epc_num: usize = @intFromEnum(ep_conf.ep_control); @@ -416,7 +397,7 @@ pub fn default_reset_handler() void { }); } - USB.ISTR.raw = 0; + USB.ISTR.raw.write(0); //re-configure endpoints for (0..8) |i| { diff --git a/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_pma.zig b/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_pma.zig index c5bde4b7d..9a6c4c0b7 100644 --- a/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_pma.zig +++ b/port/stmicro/stm32/src/hals/STM32F103/usb_internals/usb_pma.zig @@ -3,12 +3,6 @@ const microzig = @import("microzig"); const USB = microzig.chip.peripherals.USB; const PMA_BASE: u32 = 0x40006000; -const pma_data = packed struct(u32) { - low_byte: u8, - high_byte: u8, - _res: u16 = 0, -}; - //PMA(u16) <==> CPU(u32) const PMA_value = packed struct(u32) { value: u16, @@ -92,13 +86,13 @@ pub const BTABLEError = error{ const BTABLE: *volatile [8]BTABLEDescriptor = @ptrFromInt(PMA_BASE); var metadata: [8]?EntryMetadata = undefined; -var init = false; + pub fn btable_init(config: Config) BTABLEError!void { try load_and_check(config); var offset: usize = 32; - USB.BTABLE.raw = 0; + USB.BTABLE.raw.write(0); //init BTABLE; for (0..8) |i| { diff --git a/port/stmicro/stm32/src/hals/STM32F407.zig b/port/stmicro/stm32/src/hals/STM32F407.zig index e72e7b597..7c6bf0378 100644 --- a/port/stmicro/stm32/src/hals/STM32F407.zig +++ b/port/stmicro/stm32/src/hals/STM32F407.zig @@ -256,9 +256,9 @@ pub fn Uart(comptime index: usize, comptime pins: microzig.uart.Pins) type { rx_gpio.init(); // clear USART configuration to its default - @field(peripherals, usart_name).CR1.raw = 0; - @field(peripherals, usart_name).CR2.raw = 0; - @field(peripherals, usart_name).CR3.raw = 0; + @field(peripherals, usart_name).CR1.raw.write(0); + @field(peripherals, usart_name).CR2.raw.write(0); + @field(peripherals, usart_name).CR3.raw.write(0); // Return error for unsupported combinations if (config.data_bits == .nine and config.parity != null) { @@ -298,7 +298,7 @@ pub fn Uart(comptime index: usize, comptime pins: microzig.uart.Pins) type { else => unreachable, }; const usartdiv = @as(u16, @intCast(@divTrunc(bus_frequency, config.baud_rate))); - @field(peripherals, usart_name).BRR.raw = usartdiv; + @field(peripherals, usart_name).BRR.raw.write(usartdiv); // enable USART, and its transmitter and receiver @field(peripherals, usart_name).CR1.modify(.{ .UE = 1 }); diff --git a/port/stmicro/stm32/src/hals/common/bdma_v1.zig b/port/stmicro/stm32/src/hals/common/bdma_v1.zig index 53648be9c..6ff727486 100644 --- a/port/stmicro/stm32/src/hals/common/bdma_v1.zig +++ b/port/stmicro/stm32/src/hals/common/bdma_v1.zig @@ -3,7 +3,7 @@ // We need to fix this in the embassy gen from regz. const std = @import("std"); const microzig = @import("microzig"); -const util = @import("../common/util.zig"); + const dma_common = @import("dma_common.zig"); const enums = @import("./enums.zig"); pub const Instances = enums.DMA_Type; @@ -63,12 +63,12 @@ pub fn DMA(comptime dma_ctrl: Instances, comptime ch: ChannelNumber) type { pub fn clear_events(events: ChannelEvent) void { const ch_evt_idx: u5 = 4 * @as(u5, @intCast(@intFromEnum(ch))); const bits: u32 = @as(u4, @bitCast(events)); - reg_dma.IFCR.raw |= (bits & 0xF) << ch_evt_idx; + reg_dma.IFCR.raw.set((bits & 0xF) << ch_evt_idx); } pub fn read_events() ChannelEvent { const ch_evt_idx: u5 = 4 * @as(u5, @intCast(@intFromEnum(ch))); - return @bitCast(@as(u4, @truncate(reg_dma.ISR.raw >> ch_evt_idx))); + return @bitCast(@as(u4, @truncate(reg_dma.ISR.raw.read() >> ch_evt_idx))); } pub fn enable_interrupt() void { diff --git a/port/stmicro/stm32/src/hals/common/bdma_v2.zig b/port/stmicro/stm32/src/hals/common/bdma_v2.zig index d645e2a61..ad7fe2d65 100644 --- a/port/stmicro/stm32/src/hals/common/bdma_v2.zig +++ b/port/stmicro/stm32/src/hals/common/bdma_v2.zig @@ -3,7 +3,7 @@ // We need to fix this in the embassy gen from regz. const std = @import("std"); const microzig = @import("microzig"); -const util = @import("../common/util.zig"); + const dma_common = @import("dma_common.zig"); const enums = @import("../common/enums.zig"); pub const Instances = enums.DMA_Type; @@ -64,12 +64,12 @@ pub fn DMA(comptime dma_ctrl: Instances, comptime ch: ChannelNumber) type { pub fn clear_events(events: ChannelEvent) void { const ch_evt_idx: u5 = 4 * @as(u5, @intCast(@intFromEnum(ch))); const bits: u32 = @as(u4, @bitCast(events)); - reg_dma.IFCR.raw |= (bits & 0xF) << ch_evt_idx; + reg_dma.IFCR.raw.set((bits & 0xF) << ch_evt_idx); } pub fn read_events() ChannelEvent { const ch_evt_idx: u5 = 4 * @as(u5, @intCast(@intFromEnum(ch))); - return @bitCast(@as(u4, @truncate(reg_dma.ISR.raw >> ch_evt_idx))); + return @bitCast(@as(u4, @truncate(reg_dma.ISR.raw.read() >> ch_evt_idx))); } pub fn enable_interrupt() void { diff --git a/port/stmicro/stm32/src/hals/common/dma_common.zig b/port/stmicro/stm32/src/hals/common/dma_common.zig index 24824048d..dc78faca6 100644 --- a/port/stmicro/stm32/src/hals/common/dma_common.zig +++ b/port/stmicro/stm32/src/hals/common/dma_common.zig @@ -65,12 +65,12 @@ pub const Channel = struct { }); if (config.mem_address) |address| { - self.reg_channel.MAR = address; + self.reg_channel.MAR.raw.write(address); } if (config.transfer_count) |count| { self.reg_channel.NDTR.modify_one("NDT", count); } - self.reg_channel.PAR = config.periph_address; + self.reg_channel.PAR.raw.write(config.periph_address); } pub fn start(self: *Self) void { @@ -106,7 +106,7 @@ pub const Channel = struct { @memcpy(self.dma_buffer[0..buffer.len], buffer); self.reg_channel.NDTR.modify_one("NDT", @as(u16, @intCast(buffer.len))); - self.reg_channel.MAR = @intFromPtr(self.dma_buffer.ptr); + self.reg_channel.MAR.raw.write(@intFromPtr(self.dma_buffer.ptr)); } /// Reads the number of remaining transfers. diff --git a/port/stmicro/stm32/src/hals/common/gpio_v2.zig b/port/stmicro/stm32/src/hals/common/gpio_v2.zig index fba4909f6..e28c16fc2 100644 --- a/port/stmicro/stm32/src/hals/common/gpio_v2.zig +++ b/port/stmicro/stm32/src/hals/common/gpio_v2.zig @@ -1,7 +1,5 @@ -const std = @import("std"); const microzig = @import("microzig"); -const assert = std.debug.assert; pub const peripherals = microzig.chip.peripherals; const gpio_v2 = microzig.chip.types.peripherals.gpio_v2; @@ -10,7 +8,6 @@ const MODER = gpio_v2.MODER; const PUPDR = gpio_v2.PUPDR; const OSPEEDR = gpio_v2.OSPEEDR; const OT = gpio_v2.OT; -const AFIO = microzig.chip.peripherals.AFIO; pub const Port = enum { A, @@ -136,7 +133,7 @@ pub const Pin = enum(usize) { const pin: u5 = @intCast(@intFromEnum(gpio) % 16); const modMask: u32 = gpio.mask_2bit(); - port.PUPDR.write_raw((port.PUPDR.raw & ~modMask) | @as(u32, @intFromEnum(bias)) << (pin << 1)); + port.PUPDR.raw.write((port.PUPDR.raw.read() & ~modMask) | @as(u32, @intFromEnum(bias)) << (pin << 1)); } pub inline fn set_speed(gpio: Pin, speed: OSPEEDR) void { @@ -144,7 +141,7 @@ pub const Pin = enum(usize) { const pin: u5 = @intCast(@intFromEnum(gpio) % 16); const modMask: u32 = gpio.mask_2bit(); - port.OSPEEDR.write_raw((port.OSPEEDR.raw & ~modMask) | @as(u32, @intFromEnum(speed)) << (pin << 1)); + port.OSPEEDR.raw.write((port.OSPEEDR.raw.read() & ~modMask) | @as(u32, @intFromEnum(speed)) << (pin << 1)); } pub inline fn set_moder(gpio: Pin, moder: MODER) void { @@ -152,14 +149,14 @@ pub const Pin = enum(usize) { const pin: u5 = @intCast(@intFromEnum(gpio) % 16); const modMask: u32 = gpio.mask_2bit(); - port.MODER.write_raw((port.MODER.raw & ~modMask) | @as(u32, @intFromEnum(moder)) << (pin << 1)); + port.MODER.raw.write((port.MODER.raw.read() & ~modMask) | @as(u32, @intFromEnum(moder)) << (pin << 1)); } pub inline fn set_output_type(gpio: Pin, otype: OT) void { const port = gpio.get_port(); const pin: u5 = @intCast(@intFromEnum(gpio) % 16); - port.OTYPER.write_raw((port.OTYPER.raw & ~gpio.mask()) | @as(u32, @intFromEnum(otype)) << pin); + port.OTYPER.raw.write((port.OTYPER.raw.read() & ~gpio.mask()) | @as(u32, @intFromEnum(otype)) << pin); } pub inline fn set_alternate_function(gpio: Pin, afr: AF) void { @@ -167,7 +164,7 @@ pub const Pin = enum(usize) { const pin: u5 = @intCast(@intFromEnum(gpio) % 16); const afrMask: u32 = @as(u32, 0b1111) << ((pin % 8) << 2); const register = if (pin > 7) &port.AFR[1] else &port.AFR[0]; - register.write_raw((register.raw & ~afrMask) | @as(u32, @intFromEnum(afr)) << ((pin % 8) << 2)); + register.raw.write((register.raw.read() & ~afrMask) | @as(u32, @intFromEnum(afr)) << ((pin % 8) << 2)); } pub fn from_port(port: Port, pin: u4) Pin { diff --git a/port/stmicro/stm32/src/hals/common/i2c_v2.zig b/port/stmicro/stm32/src/hals/common/i2c_v2.zig index 56c36451d..4929c85f1 100644 --- a/port/stmicro/stm32/src/hals/common/i2c_v2.zig +++ b/port/stmicro/stm32/src/hals/common/i2c_v2.zig @@ -4,7 +4,6 @@ const enums = @import("enums.zig"); const I2C_Type = enums.I2C_Type; const I2C_Peripherals = microzig.chip.types.peripherals.i2c_v2.I2C; -const peripherals = microzig.chip.peripherals; const hal = microzig.hal; const drivers = microzig.drivers.base; @@ -41,7 +40,7 @@ const TIMINGR = blk: { const I2C = struct { regs: *volatile I2C_Peripherals, - timingr: TIMINGR.underlying_type, + timingr: TIMINGR.Fields, fn compute_presc(comptime instance: I2C_Type) ConfigError!struct { f32, u4 } { // Let first see if we need to prescale. @@ -126,7 +125,7 @@ const I2C = struct { regs.CR1.modify(.{ .PE = 0 }); - regs.TIMINGR.modify(i2c.timingr); + regs.TIMINGR.write(i2c.timingr); regs.CR1.modify(.{ .PE = 1 }); } @@ -205,15 +204,16 @@ const I2C = struct { const scll = try compute_low_time(t_presc); const sclh = try compute_high_time(t_presc); - const timingr: TIMINGR.underlying_type = .{ - .PRESC = presc, - .SCLDEL = scdel, - .SDADEL = sdadel, - .SCLL = scll, - .SCLH = sclh, + return .{ + .regs = enums.get_regs(I2C_Peripherals, instance), + .timingr = .{ + .PRESC = presc, + .SCLDEL = scdel, + .SDADEL = sdadel, + .SCLL = scll, + .SCLH = sclh, + }, }; - - return .{ .regs = enums.get_regs(I2C_Peripherals, instance), .timingr = timingr }; } }; diff --git a/port/stmicro/stm32/src/hals/common/pins_v2.zig b/port/stmicro/stm32/src/hals/common/pins_v2.zig index d08405492..1bfec3be9 100644 --- a/port/stmicro/stm32/src/hals/common/pins_v2.zig +++ b/port/stmicro/stm32/src/hals/common/pins_v2.zig @@ -46,7 +46,7 @@ pub const InputGPIO = struct { pin: gpio.Pin, pub inline fn read(self: @This()) u1 { const port = self.pin.get_port(); - return if (port.IDR.raw & self.pin.mask() != 0) + return if (port.IDR.raw.read() & self.pin.mask() != 0) 1 else 0; @@ -59,8 +59,8 @@ pub const OutputGPIO = struct { pub inline fn put(self: @This(), value: u1) void { var port = self.pin.get_port(); switch (value) { - 0 => port.BSRR.raw = @intCast(self.pin.mask() << 16), - 1 => port.BSRR.raw = self.pin.mask(), + 0 => port.BSRR.raw.write(@intCast(self.pin.mask() << 16)), + 1 => port.BSRR.raw.write(self.pin.mask()), } } @@ -74,7 +74,7 @@ pub const OutputGPIO = struct { pub inline fn toggle(self: @This()) void { var port = self.pin.get_port(); - port.ODR.raw ^= self.pin.mask(); + port.ODR.raw.toggle(self.pin.mask()); } }; @@ -114,14 +114,14 @@ pub const Digital_IO_Pin = struct { const self: *@This() = @ptrCast(@alignCast(ptr)); var port = self.pin.get_port(); switch (state) { - .low => port.BSRR.raw = @intCast(self.pin.mask() << 16), - .high => port.BSRR.raw = self.pin.mask(), + .low => port.BSRR.raw.write(@intCast(self.pin.mask() << 16)), + .high => port.BSRR.raw.write(self.pin.mask()), } } pub fn read_fn(ptr: *anyopaque) ReadError!State { const self: *@This() = @ptrCast(@alignCast(ptr)); const port = self.pin.get_port(); - return if (port.IDR.raw & self.pin.mask() != 0) + return if (port.IDR.raw.read() & self.pin.mask() != 0) .high else .low; diff --git a/port/stmicro/stm32/src/hals/common/spi_v2.zig b/port/stmicro/stm32/src/hals/common/spi_v2.zig index 5d28c5218..30d170dbf 100644 --- a/port/stmicro/stm32/src/hals/common/spi_v2.zig +++ b/port/stmicro/stm32/src/hals/common/spi_v2.zig @@ -46,7 +46,7 @@ pub const SPI = struct { else => .Div256, }; - self.spi.CR1.raw = 0; // Disable SPI end clear configs before configuration + self.spi.CR1.raw.write(0); // Disable SPI end clear configs before configuration self.spi.CR1.modify(.{ .CPOL = config.polarity, .CPHA = config.phase, diff --git a/port/stmicro/stm32/src/hals/common/timer_v1.zig b/port/stmicro/stm32/src/hals/common/timer_v1.zig index 5ba51079f..96d6fe126 100644 --- a/port/stmicro/stm32/src/hals/common/timer_v1.zig +++ b/port/stmicro/stm32/src/hals/common/timer_v1.zig @@ -1,7 +1,6 @@ const std = @import("std"); const microzig = @import("microzig"); const enums = @import("enums.zig"); -const periferals = microzig.chip.peripherals; const TIM_GP16 = microzig.chip.types.peripherals.timer_v1.TIM_GP16; const DIR = microzig.chip.types.peripherals.timer_v1.DIR; @@ -188,7 +187,7 @@ pub const GPTimer = struct { //disable timer before configuring self.clear_configs(); self.set_update_event(false); //disable update event to prevent unwanted updates - regs.PSC = config.prescaler; + regs.PSC.raw.write(config.prescaler); regs.ARR.modify(.{ .ARR = config.auto_reload }); regs.CR1.modify(.{ .CKD = config.clock_division, @@ -219,25 +218,25 @@ pub const GPTimer = struct { ///This function clears all control registers of the timer. pub fn clear_all_control_registers(self: *const GPTimer) void { const regs = self.regs; - regs.CR1.raw = 0; - regs.CR2.raw = 0; - regs.SR.raw = 0; - regs.EGR.raw = 0; - regs.DIER.raw = 0; - regs.ARR.raw = 0; - regs.CNT.raw = 0; - regs.PSC.raw = 0; - regs.SMCR.raw = 0; - regs.CCER.raw = 0; - regs.DCR.raw = 0; - regs.DMAR.raw = 0; + regs.CR1.raw.write(0); + regs.CR2.raw.write(0); + regs.SR.raw.write(0); + regs.EGR.raw.write(0); + regs.DIER.raw.write(0); + regs.ARR.raw.write(0); + regs.CNT.raw.write(0); + regs.PSC.raw.write(0); + regs.SMCR.raw.write(0); + regs.CCER.raw.write(0); + regs.DCR.raw.write(0); + regs.DMAR.raw.write(0); } ///clear only CR1 and CR2 registers pub fn clear_configs(self: *const GPTimer) void { - self.regs.CR1.raw = 0; - self.regs.CR2.raw = 0; - self.regs.SMCR.raw = 0; + self.regs.CR1.raw.write(0); + self.regs.CR2.raw.write(0); + self.regs.SMCR.raw.write(0); } // ============ Timer control functions ============ pub inline fn start(self: *const GPTimer) void { @@ -254,7 +253,7 @@ pub const GPTimer = struct { pub fn reset(self: *const GPTimer) void { self.regs.CR1.modify(.{ .CEN = 0 }); - self.regs.SR.raw = 0; + self.regs.SR.raw.write(0); self.regs.EGR.modify(.{ .UG = 1 }); self.regs.CR1.modify(.{ .CEN = 1 }); } @@ -272,11 +271,11 @@ pub const GPTimer = struct { } pub inline fn get_prescaler(self: *const GPTimer) u32 { - return self.regs.PSC; + return self.regs.PSC.raw.read(); } pub inline fn set_prescaler(self: *const GPTimer, value: u32) void { - self.regs.PSC = value; + self.regs.PSC.raw.write(value); } pub inline fn get_auto_reload(self: *const GPTimer) u16 { @@ -359,21 +358,20 @@ pub const GPTimer = struct { } pub fn set_channel_interrupt(self: *const GPTimer, channel: u2, set: bool) void { - const regs = self.regs; - if (set) { - regs.DIER.raw |= @as(u32, 0b1) << (@as(u5, channel) + 1); //CCxIE bits - } else { - regs.DIER.raw &= ~(@as(u32, 0b1) << (@as(u5, channel) + 1)); //CCxIE bits - } + const mask = @as(u32, 0b1) << (@as(u5, channel) + 1); + if (set) + self.regs.DIER.raw.set(mask) //CCxIE bits + else + self.regs.DIER.raw.clear(mask); //CCxIE bits + } pub fn set_channel_dma_request(self: *const GPTimer, channel: u2, set: bool) void { - const regs = self.regs; - if (set) { - regs.DIER.raw |= @as(u32, 0b1) << (@as(u5, channel) + 9); //CCxDE bits - } else { - regs.DIER.raw &= ~(@as(u32, 0b1) << (@as(u5, channel) + 9)); //CCxDE bits - } + const mask = @as(u32, 0b1) << (@as(u5, channel) + 9); + if (set) + self.regs.DIER.raw.set(mask) //CCxDE bits + else + self.regs.DIER.raw.clear(mask); //CCxDE bits } pub inline fn software_update(self: *const GPTimer) void { @@ -381,7 +379,7 @@ pub const GPTimer = struct { } pub inline fn clear_update_interrupt_flag(self: *const GPTimer) void { - self.regs.SR.raw = 0; + self.regs.SR.raw.write(0); } //=============== sync mode Functions ================ @@ -407,25 +405,19 @@ pub const GPTimer = struct { } pub fn set_channel(self: *const GPTimer, channel: u2, set: bool) void { - const regs = self.regs; - if (set) { - regs.CCER.raw |= @as(u32, 0b1) << (@as(u5, channel) * 4); //CCxE bits - } else { - regs.CCER.raw &= ~(@as(u32, 0b1) << (@as(u5, channel) * 4)); //CCxE bits - } + const mask = @as(u32, 1) << (@as(u5, channel) * 4); + if (set) + self.regs.CCER.raw.set(mask) //CCxE bits + else + self.regs.CCER.raw.clear(mask); //CCxE bits } pub fn set_polarity(self: *const GPTimer, channel: u2, polarity: Polarity) void { - const regs = self.regs; - const offset: u5 = @as(u5, channel) * 4 + 1; //CCxP bits offset + const mask = @as(u32, 1) << (@as(u5, channel) * 4 + 1); // CCxP bits offset switch (polarity) { - .high => { - regs.CCER.raw &= ~(@as(u32, 0b1) << offset); //clear CCxP bits - }, - .low => { - regs.CCER.raw |= @as(u32, 0b1) << offset; //set CCxP bits - }, + .low => self.regs.CCER.raw.set(mask), //set CCxP bits + .high => self.regs.CCER.raw.clear(mask), //clear CCxP bits } } @@ -448,30 +440,34 @@ pub const GPTimer = struct { const regs = self.regs; const CCMR = if (channel < 2) ®s.CCMR_Input[0] else ®s.CCMR_Input[1]; const offset: u5 = if (channel % 2 == 0) 0 else 8; + const mask_base = @as(u32, 1) << offset; - CCMR.raw &= ~(@as(u32, 0b11) << offset); //clear mode bits, set output compare mode (00) + // Instead of so many volatile reads and writes, + // maybe read once, do the modifications and then write the final value? - if (config.fast_mode) { - CCMR.raw |= @as(u32, 0b1) << (offset + 2); //OCxFE bits - } else { - CCMR.raw &= ~(@as(u32, 0b1) << (offset + 2)); //OCxFE bits - } + // clear mode bits, set output compare mode (00) + CCMR.raw.clear(@as(u32, 0b11) << offset); - if (config.pre_load) { - CCMR.raw |= @as(u32, 0b1) << (offset + 3); //CCxS bits - } else { - CCMR.raw &= ~(@as(u32, 0b1) << (offset + 3)); //CCxS bits - } + if (config.fast_mode) + CCMR.raw.set(mask_base << 2) //OCxFE bits + else + CCMR.raw.clear(mask_base << 2); //OCxFE bits - const mode: u32 = @intFromEnum(config.mode); - CCMR.raw &= ~(@as(u32, 0b111) << offset + 4); //clear mode bits - CCMR.raw |= mode << (offset + 4); //set mode bits + if (config.pre_load) + CCMR.raw.set(mask_base << 3) //CCxS bits + else + CCMR.raw.clear(mask_base << 3); //CCxS bits - if (config.clear_enable) { - CCMR.raw |= @as(u32, 0b1) << (offset + 7); //CCxE bits - } else { - CCMR.raw &= ~(@as(u32, 0b1) << (offset + 7)); //CCxE bits - } + const mode: u32 = @intFromEnum(config.mode); + CCMR.raw.modify( + @as(u32, 0b111) << (offset + 4), //clear mode bits + mode << (offset + 4), //set mode bits + ); + + if (config.clear_enable) + CCMR.raw.set(mask_base << 7) //CCxE bits + else + CCMR.raw.clear(mask_base << 7); //CCxE bits } pub fn configure_input(self: *const GPTimer, channel: u2, config: Capture) void { diff --git a/port/stmicro/stm32/src/hals/common/uart_v3.zig b/port/stmicro/stm32/src/hals/common/uart_v3.zig index b1ff8050a..cd984c617 100644 --- a/port/stmicro/stm32/src/hals/common/uart_v3.zig +++ b/port/stmicro/stm32/src/hals/common/uart_v3.zig @@ -58,9 +58,9 @@ pub fn Uart(comptime index: UART_Type) type { @panic("Trying to initialize USART while it is already enabled"); // clear USART1 configuration to its default - regs.CR1.raw = 0; - regs.CR2.raw = 0; - regs.CR3.raw = 0; + regs.CR1.raw.write(0); + regs.CR2.raw.write(0); + regs.CR3.raw.write(0); switch (config.word_bits) { .seven => regs.CR1.modify(.{ .M0 = .Bit8, .M1 = .Bit7 }), @@ -80,7 +80,7 @@ pub fn Uart(comptime index: UART_Type) type { // from the chip // TODO: Do some checks to see if the baud rate is too high (or perhaps too low) const usartdiv = @divTrunc(rcc.get_clock(enums.to_peripheral(index)), config.baud_rate); - regs.BRR.raw = @as(u16, @intCast(usartdiv)); + regs.BRR.raw.write(@as(u16, @intCast(usartdiv))); // TODO: We assume the default OVER8=0 configuration above. // enable USART1, and its transmitter and receiver diff --git a/port/texasinstruments/msp430/src/hal/gpio.zig b/port/texasinstruments/msp430/src/hal/gpio.zig index 04e54ee02..4e7542dcb 100644 --- a/port/texasinstruments/msp430/src/hal/gpio.zig +++ b/port/texasinstruments/msp430/src/hal/gpio.zig @@ -1,6 +1,5 @@ -const std = @import("std"); const microzig = @import("microzig"); -const cpu = microzig.cpu; + const peripherals = microzig.chip.peripherals; pub fn num(port: u3, n: u3) Pin { @@ -27,7 +26,7 @@ pub const Pin = struct { if (!@hasField(@typeInfo(@TypeOf(periph)).pointer.child, register_name)) @panic("missing register " ++ register_name); - return &@field(periph, register_name).raw; + return &@field(periph, register_name).raw.read(); } inline fn out(p: Pin) *volatile u8 { diff --git a/port/texasinstruments/mspm0/src/hal/Uart.zig b/port/texasinstruments/mspm0/src/hal/Uart.zig index e62a8fa43..2f6c1c48c 100644 --- a/port/texasinstruments/mspm0/src/hal/Uart.zig +++ b/port/texasinstruments/mspm0/src/hal/Uart.zig @@ -3,6 +3,7 @@ const microzig = @import("microzig"); const peri_types = microzig.chip.types.peripherals; const Uart = @This(); +const utils = microzig.utilities; regs: *volatile peri_types.uart0, @@ -15,17 +16,20 @@ pub fn num(n: comptime_int) Uart { } pub const Config = struct { + pub const Bits = utils.RegFieldType(peri_types.uart0, "UART0_LCRH", "WLEN"); + pub const Clock = struct { pub const Source = enum { BUSCLK, MFCLK, LFCLK }; + pub const Ovs = utils.RegFieldType(peri_types.uart0, "UART0_CTL0", "HSE"); src: Source = .BUSCLK, div0: peri_types.uart0.ClkdivRatio = .@"1", - ovs: RegFieldType("UART0_CTL0", "HSE") = .OVS16, - div: microzig.utilities.IntFracDiv(16, 6), + ovs: Ovs = .OVS16, + div: utils.IntFracDiv(16, 6), }; clk: Clock, - bits: RegFieldType("UART0_LCRH", "WLEN") = .DATABIT8, + bits: Bits = .DATABIT8, loopback: bool = false, manchester_encode: bool = false, enable: bool = true, @@ -33,7 +37,7 @@ pub const Config = struct { /// See Technical Reference Manual 14.2.6: Initialization pub fn configure(self: Uart, cfg: Config) void { - self.regs.UART0_PWREN.raw = 0x2600_0001; + self.regs.UART0_PWREN.raw.write(0x2600_0001); // Technical reference manual part 2.2.6 inline for (0..4) |_| asm volatile ("nop"); @@ -172,13 +176,3 @@ pub fn log( w.interface.flush() catch {}; } } - -fn RegFieldType(register_name: []const u8, field_name: []const u8) type { - const reg_idx = std.meta.fieldIndex(peri_types.uart0, register_name) orelse - @compileError("No register " ++ register_name ++ " in uart0."); - const Reg = std.meta.fieldTypes(peri_types.uart0)[reg_idx].underlying_type; - - const fld_idx = std.meta.fieldIndex(Reg, field_name) orelse - @compileError("No field " ++ field_name ++ " in uart0." ++ register_name ++ "."); - return std.meta.fieldTypes(Reg)[fld_idx]; -} diff --git a/port/texasinstruments/mspm0/src/hal/gpio.zig b/port/texasinstruments/mspm0/src/hal/gpio.zig index fa9aa6074..da68940d3 100644 --- a/port/texasinstruments/mspm0/src/hal/gpio.zig +++ b/port/texasinstruments/mspm0/src/hal/gpio.zig @@ -1,4 +1,3 @@ -const std = @import("std"); const microzig = @import("microzig"); const peri = microzig.chip.peripherals; @@ -12,7 +11,7 @@ fn instance(port: Port) *volatile microzig.chip.types.peripherals.gpioa { } pub fn enable(port: Port) void { - instance(port).GPIOA_PWREN.raw = 0x26000001; + instance(port).GPIOA_PWREN.raw.write(0x26000001); // Technical reference manual part 2.2.6 inline for (0..4) |_| asm volatile ("nop"); @@ -43,8 +42,8 @@ pub const Pin = struct { pub fn set_direction(p: Pin, dir: Direction) void { const reg = switch (dir) { - .in => &instance(p.port).GPIOA_DOECLR31_0.raw, - .out => &instance(p.port).GPIOA_DOESET31_0.raw, + .in => &instance(p.port).GPIOA_DOECLR31_0.raw.read(), + .out => &instance(p.port).GPIOA_DOESET31_0.raw.read(), }; reg.* = p.mask(); } @@ -55,18 +54,18 @@ pub const Pin = struct { pub fn put(p: Pin, value: u1) void { const reg = switch (value) { - 0 => &instance(p.port).GPIOA_DOUTCLR31_0.raw, - 1 => &instance(p.port).GPIOA_DOUTSET31_0.raw, + 0 => &instance(p.port).GPIOA_DOUTCLR31_0.raw.read(), + 1 => &instance(p.port).GPIOA_DOUTSET31_0.raw.read(), }; reg.* = p.mask(); } pub fn toggle(p: Pin) void { - instance(p.port).GPIOA_DOUTTGL31_0.raw = p.mask(); + instance(p.port).GPIOA_DOUTTGL31_0.raw.write(p.mask()); } pub fn read(p: Pin) u1 { - return @intFromBool(instance(p.port).GPIOA_DIN31_0.raw & p.mask() != 0); + return @intFromBool(instance(p.port).GPIOA_DIN31_0.raw.read() & p.mask() != 0); } }; diff --git a/port/wch/ch32v/src/cpus/main.zig b/port/wch/ch32v/src/cpus/main.zig index 443c7ac13..4f0b34f6f 100644 --- a/port/wch/ch32v/src/cpus/main.zig +++ b/port/wch/ch32v/src/cpus/main.zig @@ -92,10 +92,10 @@ pub const interrupt = struct { const num = irq_num >> 5; const pos = irq_num & 0x1F; switch (num) { - 0 => PFIC.IENR1.raw |= @as(u32, 1) << pos, - 1 => PFIC.IENR2.raw |= @as(u32, 1) << pos, - 2 => PFIC.IENR3.raw |= @as(u32, 1) << pos, - 3 => PFIC.IENR4.raw |= @as(u32, 1) << pos, + 0 => PFIC.IENR1.raw.set(@as(u32, 1) << pos), + 1 => PFIC.IENR2.raw.set(@as(u32, 1) << pos), + 2 => PFIC.IENR3.raw.set(@as(u32, 1) << pos), + 3 => PFIC.IENR4.raw.set(@as(u32, 1) << pos), else => @compileError("Invalid interrupt number!"), } } @@ -105,10 +105,10 @@ pub const interrupt = struct { const num = irq_num >> 5; const pos = irq_num & 0x1F; switch (num) { - 0 => PFIC.IRER1.raw |= @as(u32, 1) << pos, - 1 => PFIC.IRER2.raw |= @as(u32, 1) << pos, - 2 => PFIC.IRER3.raw |= @as(u32, 1) << pos, - 3 => PFIC.IRER4.raw |= @as(u32, 1) << pos, + 0 => PFIC.IRER1.raw.set(@as(u32, 1) << pos), + 1 => PFIC.IRER2.raw.set(@as(u32, 1) << pos), + 2 => PFIC.IRER3.raw.set(@as(u32, 1) << pos), + 3 => PFIC.IRER4.raw.set(@as(u32, 1) << pos), else => @compileError("Invalid interrupt number!"), } } @@ -132,10 +132,10 @@ pub const interrupt = struct { const num = irq_num >> 5; const pos = irq_num & 0x1F; switch (num) { - 0 => PFIC.IPSR1.raw |= @as(u32, 1) << pos, - 1 => PFIC.IPSR2.raw |= @as(u32, 1) << pos, - 2 => PFIC.IPSR3.raw |= @as(u32, 1) << pos, - 3 => PFIC.IPSR4.raw |= @as(u32, 1) << pos, + 0 => PFIC.IPSR1.raw.set(@as(u32, 1) << pos), + 1 => PFIC.IPSR2.raw.set(@as(u32, 1) << pos), + 2 => PFIC.IPSR3.raw.set(@as(u32, 1) << pos), + 3 => PFIC.IPSR4.raw.set(@as(u32, 1) << pos), else => @compileError("Invalid interrupt number!"), } } @@ -145,10 +145,10 @@ pub const interrupt = struct { const num = irq_num >> 5; const pos = irq_num & 0x1F; switch (num) { - 0 => PFIC.IPRR1.raw |= @as(u32, 1) << pos, - 1 => PFIC.IPRR2.raw |= @as(u32, 1) << pos, - 2 => PFIC.IPRR3.raw |= @as(u32, 1) << pos, - 3 => PFIC.IPRR4.raw |= @as(u32, 1) << pos, + 0 => PFIC.IPRR1.raw.set(@as(u32, 1) << pos), + 1 => PFIC.IPRR2.raw.set(@as(u32, 1) << pos), + 2 => PFIC.IPRR3.raw.set(@as(u32, 1) << pos), + 3 => PFIC.IPRR4.raw.set(@as(u32, 1) << pos), else => @compileError("Invalid interrupt number!"), } } @@ -185,7 +185,7 @@ pub const interrupt = struct { } inline fn get_bit(self: anytype, pos: u5) u1 { - return @truncate(self.raw >> pos); + return @truncate(self.raw.read() >> pos); } }; @@ -248,13 +248,13 @@ pub const startup_logic = struct { .@"qingkev3-rv32imac" => {}, .@"qingkev4-rv32imac" => { // Configure pipelining and instruction prediction. - csr.corecfgr.write_raw(0x1f); + csr.corecfgr.raw.write(0x1f); // Enable interrupt nesting and hardware stack. csr.intsyscr.write(.{ .hwstken = 1, .inesten = 1, .pmtcfg = 0 }); }, .@"qingkev4-rv32imacf" => { // Configure pipelining and instruction prediction. - csr.corecfgr.write_raw(0x1f); + csr.corecfgr.raw.write(0x1f); // Enable interrupt nesting and hardware stack. csr.intsyscr.write(.{ .hwstken = 1, .inesten = 1, .pmtcfg = 0b10 }); }, diff --git a/port/wch/ch32v/src/cpus/qingkev4-rv32imacf.zig b/port/wch/ch32v/src/cpus/qingkev4-rv32imacf.zig index e64dbbb1b..c28284380 100644 --- a/port/wch/ch32v/src/cpus/qingkev4-rv32imacf.zig +++ b/port/wch/ch32v/src/cpus/qingkev4-rv32imacf.zig @@ -247,7 +247,7 @@ pub inline fn system_init(comptime chip: anytype) void { .CSSC = 1, }); // RCC->CFGR2 = 0x00000000; - RCC.CFGR2.raw = 0; + RCC.CFGR2.raw.write(0); } pub const csr_types = struct { diff --git a/port/wch/ch32v/src/hals/ch32v003/gpio.zig b/port/wch/ch32v/src/hals/ch32v003/gpio.zig index abd941fec..ec641d6f0 100644 --- a/port/wch/ch32v/src/hals/ch32v003/gpio.zig +++ b/port/wch/ch32v/src/hals/ch32v003/gpio.zig @@ -64,8 +64,10 @@ pub const Pin = packed struct(u8) { inline fn write_pin_config(gpio: Pin, config: u32) void { const port = gpio.get_port(); const offset = @as(u5, gpio.number) << 2; // number * 4 - port.CFGLR.raw &= ~(@as(u32, 0b1111) << offset); - port.CFGLR.raw |= config << offset; + port.CFGLR.raw.modify( + @as(u32, 0b1111) << offset, + config << offset, + ); } fn mask(gpio: Pin) u16 { @@ -106,30 +108,27 @@ pub const Pin = packed struct(u8) { pub inline fn set_pull(gpio: Pin, pull: Pull) void { var port = gpio.get_port(); switch (pull) { - .up => port.BSHR.raw = gpio.mask(), - .down => port.BCR.raw = gpio.mask(), + .up => port.BSHR.raw.write(gpio.mask()), + .down => port.BCR.raw.write(gpio.mask()), } } pub inline fn read(gpio: Pin) u1 { const port = gpio.get_port(); - return if (port.IDR.raw & gpio.mask() != 0) - 1 - else - 0; + return @intFromBool(port.IDR.raw.read() & gpio.mask() != 0); } pub inline fn put(gpio: Pin, value: u1) void { var port = gpio.get_port(); switch (value) { - // 0 => port.BSHR.raw = gpio.mask() << 16, // BR - 0 => port.BCR.raw = gpio.mask(), // clear, accessed only 16bit form - 1 => port.BSHR.raw = gpio.mask(), // BS + // 0 => port.BSHR.raw.write(gpio.mask() << 16), // BR + 0 => port.BCR.raw.write(gpio.mask()), // clear, accessed only 16bit form + 1 => port.BSHR.raw.write(gpio.mask()), // BS } } pub inline fn toggle(gpio: Pin) void { var port = gpio.get_port(); - port.OUTDR.raw ^= gpio.mask(); // mask: 0 => stay, 1 => flip + port.OUTDR.raw.toggle(gpio.mask()); // mask: 0 => stay, 1 => flip } }; diff --git a/port/wch/ch32v/src/hals/ch32v003/pins.zig b/port/wch/ch32v/src/hals/ch32v003/pins.zig index 058e061be..2d1ee7022 100644 --- a/port/wch/ch32v/src/hals/ch32v003/pins.zig +++ b/port/wch/ch32v/src/hals/ch32v003/pins.zig @@ -170,7 +170,7 @@ pub const GlobalConfiguration = struct { if (used_gpios != 0) { const offset = @as(u3, @intFromEnum(@field(Port, port_field_name))) + 2; - RCC.APB2PCENR.raw |= @as(u32, 1 << offset); + RCC.APB2PCENR.raw.set(@as(u32, 1 << offset)); } // GPIO diff --git a/port/wch/ch32v/src/hals/dma.zig b/port/wch/ch32v/src/hals/dma.zig index 32687c725..449ffb4ab 100644 --- a/port/wch/ch32v/src/hals/dma.zig +++ b/port/wch/ch32v/src/hals/dma.zig @@ -5,11 +5,8 @@ //! //! const std = @import("std"); -const assert = std.debug.assert; const microzig = @import("microzig"); -const mdf = microzig.drivers; -const drivers = mdf.base; const hal = microzig.hal; const DMA1 = microzig.chip.peripherals.DMA1; @@ -227,7 +224,7 @@ pub const Channel = enum(u3) { // Clear all interrupt flags for this channel. There are four interrupts per channel, so we // shift by 4 * (channel - 1). Channel enum is 1-indexed, so subtract 1 for bit position. const flag_shift: u5 = (@as(u5, @intFromEnum(chan)) - 1) * 4; - regs.INTFCR.write_raw(@as(u32, 0b1111) << flag_shift); + regs.INTFCR.raw.write(@as(u32, 0b1111) << flag_shift); // NOTE: DIR bit affects transfer direction even in MEM2MEM mode (undocumented behavior): // - Always place the peripheral address in PADDR when a peripheral is involved. @@ -239,14 +236,14 @@ pub const Channel = enum(u3) { // Periph→Mem: PADDR=read (periph), MADDR=write (memory), DIR=0 // Mem→Mem: PADDR=read (source), MADDR=write (dest), DIR=0 if (H.is_peripheral(WriteType)) { - regs.MADDR.write_raw(read_addr); - regs.PADDR.write_raw(write_addr); + regs.MADDR.raw.write(read_addr); + regs.PADDR.raw.write(write_addr); } else { - regs.MADDR.write_raw(write_addr); - regs.PADDR.write_raw(read_addr); + regs.MADDR.raw.write(write_addr); + regs.PADDR.raw.write(read_addr); } // Set the amount of data to transfer - regs.CNTR.write_raw(count); + regs.CNTR.raw.write(count); // Set the priority regs.CFGR.modify(.{ .PL = @intFromEnum(config.priority) }); // Set the rest of the config @@ -286,7 +283,7 @@ pub const Channel = enum(u3) { const flag_shift: u5 = (@as(u5, @intFromEnum(chan)) - 1) * 4; const tcif_bit: u5 = flag_shift + 1; const tcif_mask: u32 = @as(u32, 1) << tcif_bit; - const tcif = (regs.INTFR.raw & tcif_mask) != 0; + const tcif = (regs.INTFR.raw.read() & tcif_mask) != 0; // Not busy if transfer complete flag is set return !tcif; @@ -316,14 +313,14 @@ pub const Channel = enum(u3) { const flag_shift: u5 = (@as(u5, @intFromEnum(chan)) - 1) * 4; const tcif_bit: u5 = flag_shift + 1; const tcif_mask: u32 = @as(u32, 1) << tcif_bit; - return (regs.INTFR.raw & tcif_mask) != 0; + return (regs.INTFR.raw.read() & tcif_mask) != 0; } /// Clear the transfer complete flag (useful in circular mode to detect next cycle) pub fn clear_complete_flag(comptime chan: Channel) void { const regs = chan.get_regs(); const flag_shift: u5 = (@as(u5, @intFromEnum(chan)) - 1) * 4; - regs.INTFCR.write_raw(@as(u32, 0b0010) << flag_shift); // Clear only TCIF + regs.INTFCR.raw.write(@as(u32, 0b0010) << flag_shift); // Clear only TCIF } pub fn get_remaining_count(comptime chan: Channel) u16 { diff --git a/port/wch/ch32v/src/hals/gpio.zig b/port/wch/ch32v/src/hals/gpio.zig index 9c828e40d..179fc6946 100644 --- a/port/wch/ch32v/src/hals/gpio.zig +++ b/port/wch/ch32v/src/hals/gpio.zig @@ -69,15 +69,11 @@ pub const Pin = packed struct(u8) { // TODO: inline fn write_pin_config(gpio: Pin, config: u32) void { const port = gpio.get_port(); - if (gpio.number <= 7) { - const offset = @as(u5, gpio.number) << 2; // number * 4 - port.CFGLR.raw &= ~(@as(u32, 0b1111) << offset); - port.CFGLR.raw |= config << offset; - } else { - const offset = (@as(u5, gpio.number) - 8) << 2; // number * 4 - port.CFGHR.raw &= ~(@as(u32, 0b1111) << offset); - port.CFGHR.raw |= config << offset; - } + const offset = @as(u5, @as(u3, @truncate(gpio.number))) << 2; + port.CR[gpio.number >> 3].raw.modify( + @as(u32, 0b1111) << offset, + config << offset, + ); } fn mask(gpio: Pin) u16 { @@ -146,31 +142,28 @@ pub const Pin = packed struct(u8) { pub inline fn set_pull(gpio: Pin, pull: Pull) void { var port = gpio.get_port(); switch (pull) { - .up => port.BSHR.raw = gpio.mask(), - .down => port.BCR.raw = gpio.mask(), + .up => port.BSHR.raw.write(gpio.mask()), + .down => port.BCR.raw.write(gpio.mask()), .disabled => gpio.set_input_mode(.floating), } } pub inline fn read(gpio: Pin) u1 { const port = gpio.get_port(); - return if (port.INDR.raw & gpio.mask() != 0) - 1 - else - 0; + return (@intFromBool(port.INDR.raw.read() & gpio.mask() != 0)); } pub inline fn put(gpio: Pin, value: u1) void { var port = gpio.get_port(); switch (value) { - // 0 => port.BSHR.raw = gpio.mask() << 16, // BR - 0 => port.BCR.raw = gpio.mask(), // clear, accessed only 16bit form - 1 => port.BSHR.raw = gpio.mask(), // BS + // 0 => port.BSHR.raw.write(gpio.mask()) << 16, // BR + 0 => port.BCR.raw.write(gpio.mask()), // clear, accessed only 16bit form + 1 => port.BSHR.raw.write(gpio.mask()), // BS } } pub inline fn toggle(gpio: Pin) void { var port = gpio.get_port(); - port.OUTDR.raw ^= gpio.mask(); // mask: 0 => stay, 1 => flip + port.OUTDR.raw.toggle(gpio.mask()); // mask: 0 => stay, 1 => flip } }; diff --git a/port/wch/ch32v/src/hals/i2c.zig b/port/wch/ch32v/src/hals/i2c.zig index 62f18a5a5..ea950a6de 100644 --- a/port/wch/ch32v/src/hals/i2c.zig +++ b/port/wch/ch32v/src/hals/i2c.zig @@ -4,8 +4,8 @@ //! Based on the WCH CH32V20x I2C peripheral implementation. //! Reference: CH32V20x Reference Manual Section on I2C //! -const std = @import("std"); const microzig = @import("microzig"); + const mdf = microzig.drivers; const drivers = mdf.base; const hal = microzig.hal; @@ -178,7 +178,7 @@ pub const I2C = enum(u1) { } // Write clock configuration - regs.CKCFGR.write_raw(ccr); + regs.CKCFGR.raw.write(ccr); // Enable peripheral first i2c.enable(); @@ -231,7 +231,7 @@ pub const I2C = enum(u1) { /// Send 7-bit address with direction bit inline fn send_address(i2c: I2C, addr: Address, direction: enum { write, read }) void { const addr_byte = @as(u8, @intFromEnum(addr)) << 1 | @intFromBool(direction == .read); - i2c.get_regs().DATAR.write_raw(addr_byte); + i2c.get_regs().DATAR.raw.write(addr_byte); } /// Common wait for STAR1/STAR2 flag with timeout @@ -330,7 +330,7 @@ pub const I2C = enum(u1) { try i2c.wait_flag_star1("TxE", 1, deadline); // Write data to DATAR - regs.DATAR.write_raw(element.value); + regs.DATAR.raw.write(element.value); } // Wait for BTF (Byte Transfer Finished) - ensures last byte is transmitted diff --git a/port/wch/ch32v/src/hals/pins.zig b/port/wch/ch32v/src/hals/pins.zig index cf404fae1..8693949b7 100644 --- a/port/wch/ch32v/src/hals/pins.zig +++ b/port/wch/ch32v/src/hals/pins.zig @@ -208,7 +208,7 @@ pub const GlobalConfiguration = struct { if (used_gpios != 0) { // Figure out IO port enable bit from name const offset = @as(u3, @intFromEnum(@field(Port, port_field_name))) + 2; - RCC.APB2PCENR.raw |= @as(u32, 1 << offset); + RCC.APB2PCENR.raw.set(@as(u32, 1 << offset)); } // GPIO diff --git a/port/wch/ch32v/src/hals/time.zig b/port/wch/ch32v/src/hals/time.zig index 25ab48d79..ffb49c7d9 100644 --- a/port/wch/ch32v/src/hals/time.zig +++ b/port/wch/ch32v/src/hals/time.zig @@ -1,7 +1,6 @@ -const std = @import("std"); const microzig = @import("microzig"); + const cpu = microzig.cpu; -const board = microzig.board; const time = microzig.drivers.time; const peripherals = microzig.chip.peripherals; @@ -21,9 +20,9 @@ const TIM2 = peripherals.TIM2; /// This ensures we never get a value where low has rolled over but we read the old high value. inline fn read_stk_cnt() u64 { while (true) { - const high1: u32 = PFIC.STK_CNTH.raw; - const low: u32 = PFIC.STK_CNTL.raw; - const high2: u32 = PFIC.STK_CNTH.raw; + const high1: u32 = PFIC.STK_CNTH.raw.read(); + const low: u32 = PFIC.STK_CNTL.raw.read(); + const high2: u32 = PFIC.STK_CNTH.raw.read(); // If high didn't change, we have a consistent reading if (high1 == high2) { @@ -60,8 +59,8 @@ fn init_delay_counter() void { }); // Reset the count registers - PFIC.STK_CNTL.raw = 0; - PFIC.STK_CNTH.raw = 0; + PFIC.STK_CNTL.raw.write(0); + PFIC.STK_CNTH.raw.write(0); } /// Initialize TIM2 to fire interrupts every 1ms for timekeeping. @@ -72,7 +71,7 @@ fn init_tick_timer() void { const freq: u32 = microzig.hal.clocks.get_sysclk(); // Enable TIM2 clock (bit 0 of APB1PCENR) - RCC.APB1PCENR.raw |= 1 << 0; + RCC.APB1PCENR.raw.set(1 << 0); // Set prescaler and auto-reload for 1ms ticks // For 48MHz: PSC = 47 (divide by 48), ARR = 999 (count to 1000) diff --git a/port/wch/ch32v/src/hals/usart.zig b/port/wch/ch32v/src/hals/usart.zig index a6fc86c1d..6163233ec 100644 --- a/port/wch/ch32v/src/hals/usart.zig +++ b/port/wch/ch32v/src/hals/usart.zig @@ -310,7 +310,7 @@ pub const USART = enum(u2) { const fraction = ((fraction_part * 16 + 50) / 100) & 0x0F; const brr_value = (mantissa << 4) | fraction; - regs.BRR.write_raw(@intCast(brr_value)); + regs.BRR.raw.write(@intCast(brr_value)); } /// Check if transmit data register is empty (can write) @@ -330,7 +330,7 @@ pub const USART = enum(u2) { /// Write a single byte (non-blocking) pub inline fn write_byte(usart: USART, byte: u8) void { - usart.get_regs().DATAR.write_raw(byte); + usart.get_regs().DATAR.raw.write(byte); } /// Read a single byte (non-blocking) diff --git a/tools/regz/src/gen.zig b/tools/regz/src/gen.zig index 770f1d3dc..01dfa7a6f 100644 --- a/tools/regz/src/gen.zig +++ b/tools/regz/src/gen.zig @@ -1174,25 +1174,12 @@ fn write_register( array_prefix, ref_type, }); - } else if (array_prefix.len != 0) { - try writer.print("{f}: {s}u{},\n", .{ - std.zig.fmtId(register.name), - array_prefix, - register.size_bits, - }); } else { - try writer.print("{f}: u{}", .{ + try writer.print("{f}: {s}mmio.MmioRaw(u{}),\n", .{ std.zig.fmtId(register.name), + array_prefix, register.size_bits, }); - - // Just assume non-masked areas are zero I guess - if (register_reset) |rr| { - const mask = (@as(u64, 1) << @intCast(register.size_bits)) - 1; - try writer.print(" = 0x{X}", .{rr.value & mask}); - } - - try writer.writeAll(",\n"); } try out_writer.writeAll(buf.written()); @@ -2078,7 +2065,7 @@ test "gen.peripheral with modes" { \\ \\ TEST_MODE1: extern struct { \\ /// offset: 0x00 - \\ TEST_REGISTER1: u32, + \\ TEST_REGISTER1: mmio.MmioRaw(u32), \\ /// offset: 0x04 \\ COMMON_REGISTER: mmio.Mmio(packed struct(u32) { \\ TEST_FIELD: u1, @@ -2087,7 +2074,7 @@ test "gen.peripheral with modes" { \\ }, \\ TEST_MODE2: extern struct { \\ /// offset: 0x00 - \\ TEST_REGISTER2: u32, + \\ TEST_REGISTER2: mmio.MmioRaw(u32), \\ /// offset: 0x04 \\ COMMON_REGISTER: mmio.Mmio(packed struct(u32) { \\ TEST_FIELD: u1, @@ -2163,7 +2150,7 @@ test "gen.peripheral with enum" { \\ }; \\ \\ /// offset: 0x00 - \\ TEST_REGISTER: u8, + \\ TEST_REGISTER: mmio.MmioRaw(u8), \\}; \\ , @@ -2231,7 +2218,7 @@ test "gen.peripheral with enum, enum is exhausted of values" { \\ }; \\ \\ /// offset: 0x00 - \\ TEST_REGISTER: u8, + \\ TEST_REGISTER: mmio.MmioRaw(u8), \\}; \\ , @@ -2741,20 +2728,20 @@ test "gen.namespaced register groups" { \\ \\pub const PORTB = extern struct { \\ /// offset: 0x00 - \\ PORTB: u8, + \\ PORTB: mmio.MmioRaw(u8), \\ /// offset: 0x01 - \\ DDRB: u8, + \\ DDRB: mmio.MmioRaw(u8), \\ /// offset: 0x02 - \\ PINB: u8, + \\ PINB: mmio.MmioRaw(u8), \\}; \\ \\pub const PORTC = extern struct { \\ /// offset: 0x00 - \\ PORTC: u8, + \\ PORTC: mmio.MmioRaw(u8), \\ /// offset: 0x01 - \\ DDRC: u8, + \\ DDRC: mmio.MmioRaw(u8), \\ /// offset: 0x02 - \\ PINC: u8, + \\ PINC: mmio.MmioRaw(u8), \\}; \\ , @@ -2853,11 +2840,11 @@ test "gen.peripheral with reserved register" { \\ \\pub const PORTB = extern struct { \\ /// offset: 0x00 - \\ PORTB: u32, + \\ PORTB: mmio.MmioRaw(u32), \\ /// offset: 0x04 \\ reserved4: [4]u8, \\ /// offset: 0x08 - \\ PINB: u32, + \\ PINB: mmio.MmioRaw(u32), \\}; \\ , @@ -2956,11 +2943,11 @@ test "gen.peripheral with count" { \\ \\pub const PORTB = extern struct { \\ /// offset: 0x00 - \\ PORTB: u8, + \\ PORTB: mmio.MmioRaw(u8), \\ /// offset: 0x01 - \\ DDRB: u8, + \\ DDRB: mmio.MmioRaw(u8), \\ /// offset: 0x02 - \\ PINB: u8, + \\ PINB: mmio.MmioRaw(u8), \\}; \\ , @@ -3060,11 +3047,11 @@ test "gen.peripheral with count, padding required" { \\ \\pub const PORTB = extern struct { \\ /// offset: 0x00 - \\ PORTB: u8, + \\ PORTB: mmio.MmioRaw(u8), \\ /// offset: 0x01 - \\ DDRB: u8, + \\ DDRB: mmio.MmioRaw(u8), \\ /// offset: 0x02 - \\ PINB: u8, + \\ PINB: mmio.MmioRaw(u8), \\ padding: [1]u8, \\}; \\ @@ -3165,11 +3152,11 @@ test "gen.register with count" { \\ \\pub const PORTB = extern struct { \\ /// offset: 0x00 - \\ PORTB: [4]u8, + \\ PORTB: [4]mmio.MmioRaw(u8), \\ /// offset: 0x04 - \\ DDRB: u8, + \\ DDRB: mmio.MmioRaw(u8), \\ /// offset: 0x05 - \\ PINB: u8, + \\ PINB: mmio.MmioRaw(u8), \\}; \\ , @@ -3287,9 +3274,9 @@ test "gen.register with count and fields" { \\ padding: u4 = 0, \\ }), \\ /// offset: 0x04 - \\ DDRB: u8, + \\ DDRB: mmio.MmioRaw(u8), \\ /// offset: 0x05 - \\ PINB: u8, + \\ PINB: mmio.MmioRaw(u8), \\}; \\ ,