diff --git a/build.zig b/build.zig index 1d53b09..eacdb1e 100644 --- a/build.zig +++ b/build.zig @@ -7,13 +7,12 @@ pub fn build(b: *std.Build) void { .os_tag = .freestanding, .abi = .none }); - const optimize = .Debug; // .ReleaseSmall const exe = b.addExecutable(.{ .name = "stm32", .root_source_file = b.path("src/main.zig"), .target = target, - .optimize = optimize, + .optimize = .Debug, // .ReleaseSmall, .linkage = .static, }); diff --git a/src/gpio.zig b/src/gpio.zig index 1d713e6..cbb20fa 100644 --- a/src/gpio.zig +++ b/src/gpio.zig @@ -7,8 +7,7 @@ const registers = packed struct { odr: u32, bsrr: u32, lckr: u32, - afrl: u32, - afrh: u32, + afr: u64, brr: u32, ascr: u32, }; @@ -16,30 +15,79 @@ const registers = packed struct { const driver = struct { port: *registers, - const mode = enum { + const mode = enum(u32) { + alternate_0 = 0, + alternate_1, + alternate_2, + alternate_3, + alternate_4, + alternate_5, + alternate_6, + alternate_7, + alternate_8, + alternate_9, + alternate_10, + alternate_11, + alternate_12, + alternate_13, + alternate_14, + alternate_15, input, output, - alternate, analog, }; pub fn set_mode(self: driver, pin: u4, m: mode) void { - self.port.moder &= ~(@as(u32, 0x3) << (2 * pin)); + const offset = 2 * @as(u5, pin); + const moder = self.port.moder & ~(@as(u32, 3) << offset); const mask: u32 = switch (m) { .input => 0, .output => 1, - .alternate => 2, - .analog => 3 + .analog => 3, + else => 2, }; - self.port.moder |= mask << (2 * pin); + self.port.moder = moder | (mask << offset); + + if (mask == 2) { + const afr_offset = (4 * @as(u6, pin)); + const afr = self.port.afr & ~(@as(u64, 0xF) << afr_offset); + self.port.afr = afr | (@as(u64, @intFromEnum(m)) << afr_offset); + } } pub fn toggle(self: driver, pin: u4) void { self.port.odr ^= @as(u32, 1) << pin; } + + pub fn set(self: driver, pin: u4) void { + self.port.odr |= @as(u32, 1) << pin; + } + + pub fn clear(self: driver, pin: u4) void { + self.port.odr &= ~(@as(u32, 1) << pin); + } + + pub fn write(self: driver, pin: u4, val: bool) void { + if (val) { + self.set(pin); + } else { + self.clear(pin); + } + } + + pub fn read(self: driver, pin: u4) bool { + return (self.port.idr & @as(u32, 1) << pin) != 0; + } }; pub const gpioa = driver { .port = @ptrFromInt(0x48000000) }; +pub const gpiob = driver { .port = @ptrFromInt(0x48000400) }; +pub const gpioc = driver { .port = @ptrFromInt(0x48000800) }; +pub const gpiod = driver { .port = @ptrFromInt(0x48000C00) }; +pub const gpioe = driver { .port = @ptrFromInt(0x48001000) }; +pub const gpiof = driver { .port = @ptrFromInt(0x48001400) }; +pub const gpiog = driver { .port = @ptrFromInt(0x48001800) }; +pub const gpioh = driver { .port = @ptrFromInt(0x48001C00) }; diff --git a/src/main.zig b/src/main.zig index 8ca6ada..3891e52 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3,15 +3,18 @@ const gpio = @import("gpio.zig"); const rcc: *[39]u32 = @ptrFromInt(0x40021000); const gpioa = gpio.gpioa; +const gpioc = gpio.gpioc; export fn _start() callconv(.C) noreturn { cpu.interrupt_disable(); - rcc[19] |= 1; // gpioaen + rcc[19] |= 5; // gpio a and c gpioa.set_mode(5, .output); + gpioc.set_mode(13, .input); while (true) { - gpioa.toggle(5); + const state = gpioc.read(13); + gpioa.write(5, state); } }