From 683552f4b45c9eabc29ba020e1cd59727f4fe5a9 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 28 Sep 2023 11:27:00 -0300 Subject: [PATCH 01/11] started work on clocks config --- src/hals/STM32F103/clocks.zig | 153 ++++++++++++++++++++++++++++++++++ src/hals/STM32F103/hal.zig | 1 + 2 files changed, 154 insertions(+) create mode 100644 src/hals/STM32F103/clocks.zig diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig new file mode 100644 index 0000000..0a954cf --- /dev/null +++ b/src/hals/STM32F103/clocks.zig @@ -0,0 +1,153 @@ +const std = @import("std"); + +// const pll = @import("pll.zig"); +const assert = std.debug.assert; +const comptimePrint = std.fmt.comptimePrint; + +const microzig = @import("microzig"); +const peripherals = microzig.chip.peripherals; +const RCC = peripherals.RCC; + +pub const Source = enum { + HSI, + HSE, + PLL, + LSE, + LSI, +}; + +pub const SysConfig = struct { + source: Source, + freq: u32, +}; + +pub const GlobalConfiguration = struct { + sys: ?SysConfig = null, + ahb_freq: ?u32 = null, + apb1_freq: ?u32 = null, + apb2_freq: ?u32 = null, + + pub fn apply(comptime config: GlobalConfiguration) void { + const sys = config.sys orelse .{ .source = .HSI, .freq = 8_000_000 }; + comptime { + if (sys.freq > 72_000_000) { + @compileError(comptimePrint("Sys frequency is too high. Max frequency: 72 MHz, got {}", sys.freq / 1_000_000)); + } + + switch (sys.source) { + .LSE, .LSI => { + @compileError("Invalid source for sys clock"); + }, + else => {}, + } + } + + const ahb_freq: u32 = ahb_blk: { + if (config.ahb_freq) |f| { + const divisor = sys.freq / f; + // for some reason 32 is not a valid prescaler for AHB + if (!isValidPrescaler(divisor, 512) or divisor == 32) { + @compileError(comptimePrint("AHB frequency is too high. Max frequency: {} Hz, got {}", sys.freq / 512, f)); + } + break :ahb_blk f; + } + sys.freq; + }; + + const apb1_freq: u32 = apb1_blk: { + if (config.apb1_freq) |f| { + const divisor = ahb_freq / f; + if (!isValidPrescaler(divisor, 16)) { + @compileError(comptimePrint("Invalid frequency for APB1: {}", f)); + } + break :apb1_blk f; + } + ahb_freq; + }; + + const apb2_freq: u32 = apb1_blk: { + if (config.apb2_freq) |f| { + const divisor = ahb_freq / f; + if (!isValidPrescaler(divisor, 16)) { + @compileError(comptimePrint("Invalid frequency for APB1: {}", f)); + } + break :apb1_blk f; + } + ahb_freq; + }; + + comptime { + if (apb1_freq > 36_000_000) { + @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", apb1_freq / 1_000_000)); + } + + if (apb2_freq > 72_000_000) { + @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", apb2_freq / 1_000_000)); + } + } + + switch (sys.source) { + .HSI => { + // HSI is enabled by default + while (RCC.CR.read().HSIRDY != 1) {} + }, + .HSE => { + RCC.CR.modify(.{ .HSEON = 1 }); + while (RCC.CR.read().HSERDY != 1) {} + }, + .PLL => {}, + else => {}, + } + + // Set the highest APBx dividers in order to ensure that we do not go through + // a non-spec phase whatever we decrease or increase HCLK. + RCC.CFGR.modify(.{ + .PPRE1 = 0b111, + .PPRE2 = 0b111, + }); + + const hpre = sys.freq / ahb_freq; + RCC.CFGR.modify(.{ .HPRE = getHPREdiv(hpre) }); + + const source_num = @as(u2, @intFromEnum(sys.source)); + RCC.CFGR.modify(.{ .SW = source_num }); + while (RCC.CFGR.read().SWS != source_num) {} + + const ppre1 = ahb_freq / apb1_freq; + const ppre2 = ahb_freq / apb2_freq; + RCC.CFGR.modify(.{ + .PPRE1 = getAPPREdiv(ppre1), + .PPRE2 = getAPPREdiv(ppre2), + }); + } +}; + +fn isValidPrescaler(comptime d: u32, comptime max: u8) bool { + return d <= max and std.math.isPowerOfTwo(d); +} + +fn getHPREdiv(d: u32) u4 { + return switch (d) { + 1 => 0b0000, + 2 => 0b1000, + 4 => 0b1001, + 8 => 0b1011, + 16 => 0b1011, + 64 => 0b1100, + 128 => 0b1101, + 256 => 0b1101, + 512 => 0b1111, + else => 0b0000, + }; +} + +fn getAPPREdiv(d: u32) u3 { + return switch (d) { + 1 => 0b000, + 2 => 0b100, + 4 => 0b101, + 8 => 0b110, + 16 => 0b111, + else => 0b000, + }; +} diff --git a/src/hals/STM32F103/hal.zig b/src/hals/STM32F103/hal.zig index fafa677..fc5c708 100644 --- a/src/hals/STM32F103/hal.zig +++ b/src/hals/STM32F103/hal.zig @@ -1,3 +1,4 @@ pub const pins = @import("pins.zig"); +pub const clocks = @import("clocks.zig"); pub fn init() void {} From 69afa7478419287115bf42156716ec91217da870 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 29 Sep 2023 09:21:42 -0300 Subject: [PATCH 02/11] added more sys clock sources --- src/hals/STM32F103/clocks.zig | 175 +++++++++++++++++++++++++++------- 1 file changed, 139 insertions(+), 36 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index 0a954cf..da78034 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -8,38 +8,130 @@ const microzig = @import("microzig"); const peripherals = microzig.chip.peripherals; const RCC = peripherals.RCC; -pub const Source = enum { - HSI, - HSE, - PLL, - LSE, - LSI, -}; +const MHz = 1_000_000; pub const SysConfig = struct { + pub const Source = enum { + HSI, + HSE, + PLL, + }; + + source: Source, + freq: u32, +}; + +pub const PLLConfig = struct { + pub const Source = enum { + HSI_DIV_2, + HSE, + HSE_DIV_2, + }; + source: Source, freq: u32, }; pub const GlobalConfiguration = struct { sys: ?SysConfig = null, + hsi_trim: ?u5 = null, + pll: ?PLLConfig = null, ahb_freq: ?u32 = null, apb1_freq: ?u32 = null, apb2_freq: ?u32 = null, pub fn apply(comptime config: GlobalConfiguration) void { - const sys = config.sys orelse .{ .source = .HSI, .freq = 8_000_000 }; - comptime { - if (sys.freq > 72_000_000) { - @compileError(comptimePrint("Sys frequency is too high. Max frequency: 72 MHz, got {}", sys.freq / 1_000_000)); + const sys = config.sys orelse .{ .source = .HSI, .freq = 8 * MHz }; + + if (sys.freq > 72_000_000) { + @compileError(comptimePrint("Sys frequency is too high. Max frequency: 72 MHz, got {} MHz", sys.freq / MHz)); + } + + if (config.pll) |pll| { + if (pll.freq > 72 * MHz) { + @compileError(comptimePrint("PLL frequency is too high. Max frequency: 72 MHz, got {} MHz", pll.freq / MHz)); + } + } + + if (sys.source == .PLL and !config.pll) { + @compileError("PLL used as source for sys but not configured"); + } + + const hsi_enabled = hsi_blk: { + if (sys.source == .HSI) { + if (sys.freq != 8 * MHz) { + @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSI source 8 MHz", sys.freq / MHz)); + } + break :hsi_blk true; } - switch (sys.source) { - .LSE, .LSI => { - @compileError("Invalid source for sys clock"); + if (config.pll) |pll| { + if (pll.source == .HSI_DIV_2) { + break :hsi_blk true; + } + } + + break :hsi_blk false; + }; + + const hse_enabled = hse_blk: { + if (sys.source == .HSE) { + break :hse_blk true; + } + + if (config.pll) |pll| { + if (pll.source == .HSE_DIV_2 or pll.source == .HSE) { + break :hse_blk true; + } + } + + break :hse_blk false; + }; + + const pll_enabled = config.pll != null; + + // NOTE: HSI has to be enabled until sys clock is changed + + if (config.hsi_trim) |trim| { + RCC.CR.modify(.{ .HSITRIM = trim }); + } + + if (hse_enabled) { + RCC.CR.modify(.{ .HSEON = 1 }); + while (RCC.CR.read().HSERDY != 1) {} + } else { + RCC.CR.modify(.{ .HSEON = 0 }); + while (RCC.CR.read().HSERDY != 0) {} + } + + if (pll_enabled) { + // we need to turn off the pll to configure it + RCC.CR.modify(.{ .PLLON = 0 }); + while (RCC.CR.read().PLLREADY != 0) {} + + const pll_config = config.pll.?; + switch (pll_config.source) { + .HSI_DIV_2 => { + const mul = pll_config.freq / (4 * MHz); + RCC.CFGR.modify(.{ .PLLSRC = 0, .PLLMUL = getPLLmul(mul) }); + }, + .HSE => { + const mul = pll_config.freq / (8 * MHz); + RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 0, .PLLMUL = getPLLmul(mul) }); + @compileError("TODO: figure out HSE frequency. Probably 8MHz"); + }, + .HSE_DIV_2 => { + const mul = pll_config.freq / (8 * MHz); + RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 1, .PLLMUL = getPLLmul(mul) }); + @compileError("TODO: figure out HSE frequency. Probably 8MHz"); }, - else => {}, } + + RCC.CR.modify(.{ .PLLON = 1 }); + while (RCC.CR.read().PLLREADY != 1) {} + } else { + RCC.CR.modify(.{ .PLLON = 0 }); + while (RCC.CR.read().PLLREADY != 0) {} } const ahb_freq: u32 = ahb_blk: { @@ -51,7 +143,7 @@ pub const GlobalConfiguration = struct { } break :ahb_blk f; } - sys.freq; + break :ahb_blk sys.freq; }; const apb1_freq: u32 = apb1_blk: { @@ -62,41 +154,38 @@ pub const GlobalConfiguration = struct { } break :apb1_blk f; } - ahb_freq; + break :apb1_blk ahb_freq; }; - const apb2_freq: u32 = apb1_blk: { + const apb2_freq: u32 = apb2_blk: { if (config.apb2_freq) |f| { const divisor = ahb_freq / f; if (!isValidPrescaler(divisor, 16)) { @compileError(comptimePrint("Invalid frequency for APB1: {}", f)); } - break :apb1_blk f; + break :apb2_blk f; } - ahb_freq; + break :apb2_blk ahb_freq; }; - comptime { - if (apb1_freq > 36_000_000) { - @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", apb1_freq / 1_000_000)); - } + if (apb1_freq > 36_000_000) { + @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", apb1_freq / 1_000_000)); + } - if (apb2_freq > 72_000_000) { - @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", apb2_freq / 1_000_000)); - } + if (apb2_freq > 72_000_000) { + @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", apb2_freq / 1_000_000)); } switch (sys.source) { .HSI => { - // HSI is enabled by default while (RCC.CR.read().HSIRDY != 1) {} }, .HSE => { - RCC.CR.modify(.{ .HSEON = 1 }); while (RCC.CR.read().HSERDY != 1) {} }, - .PLL => {}, - else => {}, + .PLL => { + while (RCC.CR.read().PLLRDY != 1) {} + }, } // Set the highest APBx dividers in order to ensure that we do not go through @@ -109,7 +198,8 @@ pub const GlobalConfiguration = struct { const hpre = sys.freq / ahb_freq; RCC.CFGR.modify(.{ .HPRE = getHPREdiv(hpre) }); - const source_num = @as(u2, @intFromEnum(sys.source)); + // HACK: Ummmmmmm what? + const source_num = @as(u2, @intFromEnum(@as(SysConfig.Source, sys.source))); RCC.CFGR.modify(.{ .SW = source_num }); while (RCC.CFGR.read().SWS != source_num) {} @@ -119,6 +209,11 @@ pub const GlobalConfiguration = struct { .PPRE1 = getAPPREdiv(ppre1), .PPRE2 = getAPPREdiv(ppre2), }); + + if (!hsi_enabled) { + RCC.CR.modify(.{ .HSION = 0 }); + while (RCC.CR.read().HSIRDY != 0) {} + } } }; @@ -126,7 +221,7 @@ fn isValidPrescaler(comptime d: u32, comptime max: u8) bool { return d <= max and std.math.isPowerOfTwo(d); } -fn getHPREdiv(d: u32) u4 { +fn getHPREdiv(comptime d: u32) u4 { return switch (d) { 1 => 0b0000, 2 => 0b1000, @@ -137,17 +232,25 @@ fn getHPREdiv(d: u32) u4 { 128 => 0b1101, 256 => 0b1101, 512 => 0b1111, - else => 0b0000, + else => @compileError("Invalid HPRE"), }; } -fn getAPPREdiv(d: u32) u3 { +fn getAPPREdiv(comptime d: u32) u3 { return switch (d) { 1 => 0b000, 2 => 0b100, 4 => 0b101, 8 => 0b110, 16 => 0b111, - else => 0b000, + else => @compileError("Invalid APRE"), }; } + +fn getPLLmul(comptime m: u32) u4 { + if (m < 2 or m > 16) { + @compileError("Invalid PLL mul"); + } + + return @as(u4, m - 2); +} From 0b2f19957fa4277b6af7d83b0b737c4196631d11 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 29 Sep 2023 10:01:06 -0300 Subject: [PATCH 03/11] fixed a few errors --- src/hals/STM32F103/clocks.zig | 88 +++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index da78034..f65451f 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -43,24 +43,31 @@ pub const GlobalConfiguration = struct { pub fn apply(comptime config: GlobalConfiguration) void { const sys = config.sys orelse .{ .source = .HSI, .freq = 8 * MHz }; - if (sys.freq > 72_000_000) { - @compileError(comptimePrint("Sys frequency is too high. Max frequency: 72 MHz, got {} MHz", sys.freq / MHz)); - } + comptime { + if (sys.freq > 72_000_000) { + @compileError(comptimePrint("Sys frequency is too high. Max frequency: 72 MHz, got {} MHz", .{sys.freq / MHz})); + } - if (config.pll) |pll| { - if (pll.freq > 72 * MHz) { - @compileError(comptimePrint("PLL frequency is too high. Max frequency: 72 MHz, got {} MHz", pll.freq / MHz)); + if (config.pll) |pll| { + if (pll.freq > 72 * MHz) { + @compileError(comptimePrint("PLL frequency is too high. Max frequency: 72 MHz, got {} MHz", .{pll.freq / MHz})); + } } - } - if (sys.source == .PLL and !config.pll) { - @compileError("PLL used as source for sys but not configured"); + if (sys.source == .PLL) { + if (config.pll) |pll| { + if (pll.freq != sys.freq) { + @compileError(comptimePrint("Incompatible sys frequency {} MHz with PLL source {} MHz", .{ sys.freq / MHz, pll.freq / MHz })); + } + } else { + @compileError("PLL used as source for sys but not configured"); + } + } } - const hsi_enabled = hsi_blk: { if (sys.source == .HSI) { if (sys.freq != 8 * MHz) { - @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSI source 8 MHz", sys.freq / MHz)); + @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSI source 8 MHz", .{sys.freq / MHz})); } break :hsi_blk true; } @@ -107,7 +114,7 @@ pub const GlobalConfiguration = struct { if (pll_enabled) { // we need to turn off the pll to configure it RCC.CR.modify(.{ .PLLON = 0 }); - while (RCC.CR.read().PLLREADY != 0) {} + while (RCC.CR.read().PLLRDY != 0) {} const pll_config = config.pll.?; switch (pll_config.source) { @@ -118,28 +125,30 @@ pub const GlobalConfiguration = struct { .HSE => { const mul = pll_config.freq / (8 * MHz); RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 0, .PLLMUL = getPLLmul(mul) }); - @compileError("TODO: figure out HSE frequency. Probably 8MHz"); + @compileError("TODO: figure out HSE frequency. Probably 16MHz"); }, .HSE_DIV_2 => { const mul = pll_config.freq / (8 * MHz); RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 1, .PLLMUL = getPLLmul(mul) }); - @compileError("TODO: figure out HSE frequency. Probably 8MHz"); + @compileError("TODO: figure out HSE frequency. Probably 16MHz"); }, } RCC.CR.modify(.{ .PLLON = 1 }); - while (RCC.CR.read().PLLREADY != 1) {} + while (RCC.CR.read().PLLRDY != 1) {} } else { RCC.CR.modify(.{ .PLLON = 0 }); - while (RCC.CR.read().PLLREADY != 0) {} + while (RCC.CR.read().PLLRDY != 0) {} } const ahb_freq: u32 = ahb_blk: { if (config.ahb_freq) |f| { - const divisor = sys.freq / f; - // for some reason 32 is not a valid prescaler for AHB - if (!isValidPrescaler(divisor, 512) or divisor == 32) { - @compileError(comptimePrint("AHB frequency is too high. Max frequency: {} Hz, got {}", sys.freq / 512, f)); + comptime { + const divisor = sys.freq / f; + // for some reason 32 is not a valid prescaler for AHB + if (!isValidPrescaler(divisor, 512) or divisor == 32) { + @compileError(comptimePrint("AHB frequency is too low. Min frequency: {} Hz, got {}", .{ sys.freq / 512, f })); + } } break :ahb_blk f; } @@ -148,9 +157,11 @@ pub const GlobalConfiguration = struct { const apb1_freq: u32 = apb1_blk: { if (config.apb1_freq) |f| { - const divisor = ahb_freq / f; - if (!isValidPrescaler(divisor, 16)) { - @compileError(comptimePrint("Invalid frequency for APB1: {}", f)); + comptime { + const divisor = ahb_freq / f; + if (!isValidPrescaler(divisor, 16)) { + @compileError(comptimePrint("Invalid frequency for APB1: {}, {}", .{ f, divisor })); + } } break :apb1_blk f; } @@ -159,21 +170,25 @@ pub const GlobalConfiguration = struct { const apb2_freq: u32 = apb2_blk: { if (config.apb2_freq) |f| { - const divisor = ahb_freq / f; - if (!isValidPrescaler(divisor, 16)) { - @compileError(comptimePrint("Invalid frequency for APB1: {}", f)); + comptime { + const divisor = ahb_freq / f; + if (!isValidPrescaler(divisor, 16)) { + @compileError(comptimePrint("Invalid frequency for APB1: {}", .{f})); + } } break :apb2_blk f; } break :apb2_blk ahb_freq; }; - if (apb1_freq > 36_000_000) { - @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", apb1_freq / 1_000_000)); - } + comptime { + if (apb1_freq > 36_000_000) { + @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", .{apb1_freq / MHz})); + } - if (apb2_freq > 72_000_000) { - @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", apb2_freq / 1_000_000)); + if (apb2_freq > 72_000_000) { + @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", .{apb2_freq / MHz})); + } } switch (sys.source) { @@ -232,7 +247,7 @@ fn getHPREdiv(comptime d: u32) u4 { 128 => 0b1101, 256 => 0b1101, 512 => 0b1111, - else => @compileError("Invalid HPRE"), + else => 0b000, }; } @@ -243,14 +258,15 @@ fn getAPPREdiv(comptime d: u32) u3 { 4 => 0b101, 8 => 0b110, 16 => 0b111, - else => @compileError("Invalid APRE"), + else => 0b000, }; } fn getPLLmul(comptime m: u32) u4 { - if (m < 2 or m > 16) { - @compileError("Invalid PLL mul"); + comptime { + if (m < 2 or m > 16) { + @compileError(comptimePrint("Invalid PLL mul: {}", .{m})); + } } - return @as(u4, m - 2); } From f499929659f15bc4e1d5c69666288fdc76240a54 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 29 Sep 2023 10:12:39 -0300 Subject: [PATCH 04/11] flash control --- src/hals/STM32F103/clocks.zig | 10 ++++++++++ src/hals/STM32F103/hal.zig | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index f65451f..5452fb1 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -7,6 +7,7 @@ const comptimePrint = std.fmt.comptimePrint; const microzig = @import("microzig"); const peripherals = microzig.chip.peripherals; const RCC = peripherals.RCC; +const FLASH = peripherals.FLASH; const MHz = 1_000_000; @@ -97,6 +98,15 @@ pub const GlobalConfiguration = struct { const pll_enabled = config.pll != null; + FLASH.ACR.modify(.{ .PRFTBE = 1 }); + if (sys.freq <= 24 * MHz) { + FLASH.ACR.modify(.{ .LATENCY = 0b000 }); + } else if (sys.freq <= 48 * MHz) { + FLASH.ACR.modify(.{ .LATENCY = 0b001 }); + } else { + FLASH.ACR.modify(.{ .LATENCY = 0b010 }); + } + // NOTE: HSI has to be enabled until sys clock is changed if (config.hsi_trim) |trim| { diff --git a/src/hals/STM32F103/hal.zig b/src/hals/STM32F103/hal.zig index fc5c708..1b8353a 100644 --- a/src/hals/STM32F103/hal.zig +++ b/src/hals/STM32F103/hal.zig @@ -1,4 +1,9 @@ pub const pins = @import("pins.zig"); pub const clocks = @import("clocks.zig"); -pub fn init() void {} +const microzig = @import("microzig"); +const FLASH = microzig.chip.peripherals.FLASH; + +pub fn init() void { + FLASH.ACR.modify(.{ .PRFTBE = 1 }); +} From 8a625d9b64c95ff3b07652eea9db53596ff6d370 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 29 Sep 2023 11:05:40 -0300 Subject: [PATCH 05/11] a few design improvements --- src/hals/STM32F103/clocks.zig | 45 +++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index 5452fb1..965665a 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -36,6 +36,8 @@ pub const PLLConfig = struct { pub const GlobalConfiguration = struct { sys: ?SysConfig = null, hsi_trim: ?u5 = null, + // frequency of external oscillator. Usually 8 MHz + hse_freq: u32 = 8 * MHz, pll: ?PLLConfig = null, ahb_freq: ?u32 = null, apb1_freq: ?u32 = null, @@ -45,31 +47,46 @@ pub const GlobalConfiguration = struct { const sys = config.sys orelse .{ .source = .HSI, .freq = 8 * MHz }; comptime { - if (sys.freq > 72_000_000) { + if (sys.freq > 72 * MHz) { @compileError(comptimePrint("Sys frequency is too high. Max frequency: 72 MHz, got {} MHz", .{sys.freq / MHz})); } + if (config.hse_freq < 4 * MHz or config.hse_freq > 16 * MHz) { + @compileError(comptimePrint("Invalid HSE oscillator: {}. Valid range is from 4 MHz to 16 MHz", .{config.hse_freq / MHz})); + } + if (config.pll) |pll| { if (pll.freq > 72 * MHz) { @compileError(comptimePrint("PLL frequency is too high. Max frequency: 72 MHz, got {} MHz", .{pll.freq / MHz})); } } - if (sys.source == .PLL) { - if (config.pll) |pll| { - if (pll.freq != sys.freq) { - @compileError(comptimePrint("Incompatible sys frequency {} MHz with PLL source {} MHz", .{ sys.freq / MHz, pll.freq / MHz })); + const source = @as(SysConfig.Source, sys.source); + switch (source) { + .HSI => { + if (sys.freq != 8 * MHz) { + @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSI source 8 MHz", .{sys.freq / MHz})); } - } else { - @compileError("PLL used as source for sys but not configured"); - } + }, + .HSE => { + if (sys.freq != config.hse_freq) { + @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSE source {} MHz", .{ sys.freq / MHz, config.hse_freq / MHz })); + } + }, + .PLL => { + if (config.pll) |pll| { + if (pll.freq != sys.freq) { + @compileError(comptimePrint("Incompatible sys frequency {} MHz with PLL source {} MHz", .{ sys.freq / MHz, pll.freq / MHz })); + } + } else { + @compileError("PLL used as source for sys but not configured"); + } + }, } } + const hsi_enabled = hsi_blk: { if (sys.source == .HSI) { - if (sys.freq != 8 * MHz) { - @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSI source 8 MHz", .{sys.freq / MHz})); - } break :hsi_blk true; } @@ -133,14 +150,12 @@ pub const GlobalConfiguration = struct { RCC.CFGR.modify(.{ .PLLSRC = 0, .PLLMUL = getPLLmul(mul) }); }, .HSE => { - const mul = pll_config.freq / (8 * MHz); + const mul = pll_config.freq / config.hse_freq; RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 0, .PLLMUL = getPLLmul(mul) }); - @compileError("TODO: figure out HSE frequency. Probably 16MHz"); }, .HSE_DIV_2 => { - const mul = pll_config.freq / (8 * MHz); + const mul = pll_config.freq / (config.hse_freq / 2); RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 1, .PLLMUL = getPLLmul(mul) }); - @compileError("TODO: figure out HSE frequency. Probably 16MHz"); }, } From 9712ed068ca2050257c0be59eea500c52f3fb5ec Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 29 Sep 2023 12:52:42 -0300 Subject: [PATCH 06/11] added HSE as a valid source --- src/hals/STM32F103/clocks.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index 965665a..120e190 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -151,11 +151,11 @@ pub const GlobalConfiguration = struct { }, .HSE => { const mul = pll_config.freq / config.hse_freq; - RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 0, .PLLMUL = getPLLmul(mul) }); + RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLXTPRE = 0, .PLLMUL = getPLLmul(mul) }); }, .HSE_DIV_2 => { const mul = pll_config.freq / (config.hse_freq / 2); - RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLTXPRE = 1, .PLLMUL = getPLLmul(mul) }); + RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLXTPRE = 1, .PLLMUL = getPLLmul(mul) }); }, } From 2234532bb81cd38816787aa723f4499c29e70f4b Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 30 Sep 2023 10:59:34 -0300 Subject: [PATCH 07/11] removed switch statement for getting port --- src/hals/STM32F103/gpio.zig | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/hals/STM32F103/gpio.zig b/src/hals/STM32F103/gpio.zig index 811a80c..03c0a97 100644 --- a/src/hals/STM32F103/gpio.zig +++ b/src/hals/STM32F103/gpio.zig @@ -2,17 +2,14 @@ const std = @import("std"); const assert = std.debug.assert; const microzig = @import("microzig"); -pub const peripherals = microzig.chip.peripherals; +const peripherals = microzig.chip.peripherals; const GPIOA = peripherals.GPIOA; const GPIOB = peripherals.GPIOB; -const GPIOC = peripherals.GPIOC; -const GPIOD = peripherals.GPIOD; -const GPIOE = peripherals.GPIOE; -const GPIOF = peripherals.GPIOF; -const GPIOG = peripherals.GPIOG; +const GPIO = microzig.chip.types.peripherals.GPIOA; -const GPIO = @TypeOf(GPIOA); +// NOTE: Apparently GPIO ports are not one next to the other +const GPIOoffset = @intFromPtr(GPIOB) - @intFromPtr(GPIOA); const log = std.log.scoped(.gpio); @@ -94,19 +91,10 @@ pub const Pin = packed struct(u8) { return @as(u16, 1) << gpio.number; } - // NOTE: Im not sure I like this - // We could probably calculate an offset from GPIOA? - pub fn get_port(gpio: Pin) GPIO { - return switch (gpio.port) { - 0 => GPIOA, - 1 => GPIOB, - 2 => GPIOC, - 3 => GPIOD, - 4 => GPIOE, - 5 => GPIOF, - 6 => GPIOG, - 7 => @panic("The STM32 only has ports 0..6 (A..G)"), - }; + pub fn get_port(gpio: Pin) *volatile GPIO { + assert(gpio.port < 7); + const port: *volatile GPIO = @ptrFromInt(@intFromPtr(GPIOA) + (GPIOoffset * gpio.port)); + return port; } pub inline fn set_mode(gpio: Pin, mode: Mode) void { From 43b0ebfdcd2ad981be699f3e0baf624e4d4108a8 Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 30 Sep 2023 10:59:49 -0300 Subject: [PATCH 08/11] better options --- src/hals/STM32F103/clocks.zig | 39 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index 120e190..b16aeb2 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -79,10 +79,22 @@ pub const GlobalConfiguration = struct { @compileError(comptimePrint("Incompatible sys frequency {} MHz with PLL source {} MHz", .{ sys.freq / MHz, pll.freq / MHz })); } } else { - @compileError("PLL used as source for sys but not configured"); + @compileError("PLL used as sys source but not configured"); } }, } + + if (config.ahb_freq > 72 * MHz) { + @compileError(comptimePrint("AHB frequency is too high. Max frequency: 72 MHz, got {} MHz", .{config.ahb_freq / MHz})); + } + + if (config.apb1_freq > 36 * MHz) { + @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", .{config.apb1_freq / MHz})); + } + + if (config.apb2_freq > 72 * MHz) { + @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", .{config.apb2_freq / MHz})); + } } const hsi_enabled = hsi_blk: { @@ -113,8 +125,6 @@ pub const GlobalConfiguration = struct { break :hse_blk false; }; - const pll_enabled = config.pll != null; - FLASH.ACR.modify(.{ .PRFTBE = 1 }); if (sys.freq <= 24 * MHz) { FLASH.ACR.modify(.{ .LATENCY = 0b000 }); @@ -138,12 +148,11 @@ pub const GlobalConfiguration = struct { while (RCC.CR.read().HSERDY != 0) {} } - if (pll_enabled) { + if (config.pll) |pll_config| { // we need to turn off the pll to configure it RCC.CR.modify(.{ .PLLON = 0 }); while (RCC.CR.read().PLLRDY != 0) {} - const pll_config = config.pll.?; switch (pll_config.source) { .HSI_DIV_2 => { const mul = pll_config.freq / (4 * MHz); @@ -190,7 +199,10 @@ pub const GlobalConfiguration = struct { } break :apb1_blk f; } - break :apb1_blk ahb_freq; + break :apb1_blk if (ahb_freq <= 36 * MHz) + ahb_freq + else + 36 * MHz; }; const apb2_freq: u32 = apb2_blk: { @@ -203,18 +215,13 @@ pub const GlobalConfiguration = struct { } break :apb2_blk f; } - break :apb2_blk ahb_freq; + break :apb2_blk if (ahb_freq <= 72 * MHz) + ahb_freq + else + 72 * MHz; }; - comptime { - if (apb1_freq > 36_000_000) { - @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", .{apb1_freq / MHz})); - } - - if (apb2_freq > 72_000_000) { - @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", .{apb2_freq / MHz})); - } - } + comptime {} switch (sys.source) { .HSI => { From 18c87685ec8d1fabc9af2a4faea6cc609d190e63 Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 30 Sep 2023 11:08:14 -0300 Subject: [PATCH 09/11] fixed a mistake --- src/hals/STM32F103/clocks.zig | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index b16aeb2..edd0cd6 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -84,16 +84,22 @@ pub const GlobalConfiguration = struct { }, } - if (config.ahb_freq > 72 * MHz) { - @compileError(comptimePrint("AHB frequency is too high. Max frequency: 72 MHz, got {} MHz", .{config.ahb_freq / MHz})); + if (config.ahb_freq) |f| { + if (f > 72 * MHz) { + @compileError(comptimePrint("AHB frequency is too high. Max frequency: 72 MHz, got {} MHz", .{f / MHz})); + } } - if (config.apb1_freq > 36 * MHz) { - @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", .{config.apb1_freq / MHz})); + if (config.apb1_freq) |f| { + if (f > 36 * MHz) { + @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", .{f / MHz})); + } } - if (config.apb2_freq > 72 * MHz) { - @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", .{config.apb2_freq / MHz})); + if (config.apb2_freq) |f| { + if (f > 72 * MHz) { + @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", .{f / MHz})); + } } } From ea9bf59f9aa833cba3f8b11c891cbbba3a035182 Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 30 Sep 2023 12:43:31 -0300 Subject: [PATCH 10/11] better config options --- src/hals/STM32F103/clocks.zig | 195 ++++++++++++++-------------------- 1 file changed, 81 insertions(+), 114 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index edd0cd6..ba9a04d 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -37,41 +37,82 @@ pub const GlobalConfiguration = struct { sys: ?SysConfig = null, hsi_trim: ?u5 = null, // frequency of external oscillator. Usually 8 MHz - hse_freq: u32 = 8 * MHz, - pll: ?PLLConfig = null, + hse_freq: ?u32 = null, ahb_freq: ?u32 = null, apb1_freq: ?u32 = null, apb2_freq: ?u32 = null, + pll: ?PLLConfig = null, pub fn apply(comptime config: GlobalConfiguration) void { const sys = config.sys orelse .{ .source = .HSI, .freq = 8 * MHz }; + comptime var pll_config: ?PLLConfig = null; + comptime var pll_mul = 0; + + comptime var hsi_enabled = false; + comptime var hse_enabled = false; + + comptime var hse_freq = config.hse_freq orelse 8 * MHz; + + comptime var ahb_freq = config.ahb_freq orelse sys.freq; + comptime var ahb_div = sys.freq / ahb_freq; + + comptime var apb1_freq = config.apb1_freq orelse if (ahb_freq <= 36 * MHz) ahb_freq else 36 * MHz; + comptime var apb1_div = ahb_freq / apb1_freq; + + comptime var apb2_freq = config.apb2_freq orelse if (ahb_freq <= 72 * MHz) ahb_freq else 72 * MHz; + comptime var apb2_div = ahb_freq / apb1_freq; + + // Do a comptime validation of config comptime { if (sys.freq > 72 * MHz) { @compileError(comptimePrint("Sys frequency is too high. Max frequency: 72 MHz, got {} MHz", .{sys.freq / MHz})); } - if (config.hse_freq < 4 * MHz or config.hse_freq > 16 * MHz) { - @compileError(comptimePrint("Invalid HSE oscillator: {}. Valid range is from 4 MHz to 16 MHz", .{config.hse_freq / MHz})); + if (hse_freq < 4 * MHz or hse_freq > 16 * MHz) { + @compileError(comptimePrint("Invalid HSE oscillator: {}. Valid range is from 4 MHz to 16 MHz", .{hse_freq / MHz})); } if (config.pll) |pll| { + pll_config = pll; if (pll.freq > 72 * MHz) { @compileError(comptimePrint("PLL frequency is too high. Max frequency: 72 MHz, got {} MHz", .{pll.freq / MHz})); } + + var source_freq = 0; + switch (pll.source) { + .HSI_DIV_2 => { + source_freq = 4 * MHz; + hsi_enabled = true; + }, + .HSE_DIV_2 => { + source_freq = hse_freq / 2; + hse_enabled = true; + }, + .HSE => { + source_freq = hse_freq; + hse_enabled = true; + }, + } + + pll_mul = pll.freq / source_freq; + if (!isValidPLLmul(pll_mul)) { + @compileError(comptimePrint("Invalid PLL multiplier {}", .{pll_mul})); + } } - const source = @as(SysConfig.Source, sys.source); - switch (source) { + switch (sys.source) { .HSI => { if (sys.freq != 8 * MHz) { @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSI source 8 MHz", .{sys.freq / MHz})); } + hsi_enabled = true; }, .HSE => { - if (sys.freq != config.hse_freq) { - @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSE source {} MHz", .{ sys.freq / MHz, config.hse_freq / MHz })); + if (sys.freq != hse_freq) { + @compileError(comptimePrint("Incompatible sys frequency {} MHz with HSE source {} MHz", .{ sys.freq / MHz, hse_freq / MHz })); } + hse_enabled = true; }, .PLL => { if (config.pll) |pll| { @@ -79,58 +120,39 @@ pub const GlobalConfiguration = struct { @compileError(comptimePrint("Incompatible sys frequency {} MHz with PLL source {} MHz", .{ sys.freq / MHz, pll.freq / MHz })); } } else { - @compileError("PLL used as sys source but not configured"); + pll_config = .{ .source = .HSE, .freq = sys.freq }; + hse_enabled = true; } }, } - if (config.ahb_freq) |f| { - if (f > 72 * MHz) { - @compileError(comptimePrint("AHB frequency is too high. Max frequency: 72 MHz, got {} MHz", .{f / MHz})); - } - } - - if (config.apb1_freq) |f| { - if (f > 36 * MHz) { - @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", .{f / MHz})); - } + if (ahb_freq > 72 * MHz) { + @compileError(comptimePrint("AHB frequency is too high. Max frequency: 72 MHz, got {} MHz", .{ahb_freq / MHz})); } - if (config.apb2_freq) |f| { - if (f > 72 * MHz) { - @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", .{f / MHz})); - } + // for some reason 32 is not a valid prescaler + if (!isValidPrescaler(ahb_div, 512) or ahb_div == 32) { + @compileError(comptimePrint("Invalid frequency for AHB: {} Hz.", .{ahb_freq})); } - } - const hsi_enabled = hsi_blk: { - if (sys.source == .HSI) { - break :hsi_blk true; + if (apb1_freq > 36 * MHz) { + @compileError(comptimePrint("APB1 frequency is too high. Max frequency: 36 MHz, got {} MHz", .{apb1_freq / MHz})); } - if (config.pll) |pll| { - if (pll.source == .HSI_DIV_2) { - break :hsi_blk true; - } + if (!isValidPrescaler(apb1_div, 16)) { + @compileError(comptimePrint("Invalid frequency for APB1: {}.\nValid prescalers: 1, 2, 4, 18 and 16. Got {}", .{ apb1_freq, apb1_div })); } - break :hsi_blk false; - }; - - const hse_enabled = hse_blk: { - if (sys.source == .HSE) { - break :hse_blk true; + if (apb2_freq > 72 * MHz) { + @compileError(comptimePrint("APB2 frequency is too high. Max frequency: 72 MHz, got {} MHz", .{apb2_freq / MHz})); } - if (config.pll) |pll| { - if (pll.source == .HSE_DIV_2 or pll.source == .HSE) { - break :hse_blk true; - } + if (!isValidPrescaler(apb2_div, 16)) { + @compileError(comptimePrint("Invalid frequency for APB2: {}.\nValid prescalers: 1, 2, 4, 8 and 16. Got {}", .{ apb2_freq, apb2_div })); } + } - break :hse_blk false; - }; - + // Apply config FLASH.ACR.modify(.{ .PRFTBE = 1 }); if (sys.freq <= 24 * MHz) { FLASH.ACR.modify(.{ .LATENCY = 0b000 }); @@ -154,23 +176,20 @@ pub const GlobalConfiguration = struct { while (RCC.CR.read().HSERDY != 0) {} } - if (config.pll) |pll_config| { + if (pll_config) |pll| { // we need to turn off the pll to configure it RCC.CR.modify(.{ .PLLON = 0 }); while (RCC.CR.read().PLLRDY != 0) {} - switch (pll_config.source) { + switch (pll.source) { .HSI_DIV_2 => { - const mul = pll_config.freq / (4 * MHz); - RCC.CFGR.modify(.{ .PLLSRC = 0, .PLLMUL = getPLLmul(mul) }); + RCC.CFGR.modify(.{ .PLLSRC = 0, .PLLMUL = getPLLmul(pll_mul) }); }, .HSE => { - const mul = pll_config.freq / config.hse_freq; - RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLXTPRE = 0, .PLLMUL = getPLLmul(mul) }); + RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLXTPRE = 0, .PLLMUL = getPLLmul(pll_mul) }); }, .HSE_DIV_2 => { - const mul = pll_config.freq / (config.hse_freq / 2); - RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLXTPRE = 1, .PLLMUL = getPLLmul(mul) }); + RCC.CFGR.modify(.{ .PLLSRC = 1, .PLLXTPRE = 1, .PLLMUL = getPLLmul(pll_mul) }); }, } @@ -181,54 +200,6 @@ pub const GlobalConfiguration = struct { while (RCC.CR.read().PLLRDY != 0) {} } - const ahb_freq: u32 = ahb_blk: { - if (config.ahb_freq) |f| { - comptime { - const divisor = sys.freq / f; - // for some reason 32 is not a valid prescaler for AHB - if (!isValidPrescaler(divisor, 512) or divisor == 32) { - @compileError(comptimePrint("AHB frequency is too low. Min frequency: {} Hz, got {}", .{ sys.freq / 512, f })); - } - } - break :ahb_blk f; - } - break :ahb_blk sys.freq; - }; - - const apb1_freq: u32 = apb1_blk: { - if (config.apb1_freq) |f| { - comptime { - const divisor = ahb_freq / f; - if (!isValidPrescaler(divisor, 16)) { - @compileError(comptimePrint("Invalid frequency for APB1: {}, {}", .{ f, divisor })); - } - } - break :apb1_blk f; - } - break :apb1_blk if (ahb_freq <= 36 * MHz) - ahb_freq - else - 36 * MHz; - }; - - const apb2_freq: u32 = apb2_blk: { - if (config.apb2_freq) |f| { - comptime { - const divisor = ahb_freq / f; - if (!isValidPrescaler(divisor, 16)) { - @compileError(comptimePrint("Invalid frequency for APB1: {}", .{f})); - } - } - break :apb2_blk f; - } - break :apb2_blk if (ahb_freq <= 72 * MHz) - ahb_freq - else - 72 * MHz; - }; - - comptime {} - switch (sys.source) { .HSI => { while (RCC.CR.read().HSIRDY != 1) {} @@ -248,19 +219,16 @@ pub const GlobalConfiguration = struct { .PPRE2 = 0b111, }); - const hpre = sys.freq / ahb_freq; - RCC.CFGR.modify(.{ .HPRE = getHPREdiv(hpre) }); + RCC.CFGR.modify(.{ .HPRE = getHPREdiv(ahb_div) }); // HACK: Ummmmmmm what? const source_num = @as(u2, @intFromEnum(@as(SysConfig.Source, sys.source))); RCC.CFGR.modify(.{ .SW = source_num }); while (RCC.CFGR.read().SWS != source_num) {} - const ppre1 = ahb_freq / apb1_freq; - const ppre2 = ahb_freq / apb2_freq; RCC.CFGR.modify(.{ - .PPRE1 = getAPPREdiv(ppre1), - .PPRE2 = getAPPREdiv(ppre2), + .PPRE1 = getAPPREdiv(apb1_div), + .PPRE2 = getAPPREdiv(apb2_div), }); if (!hsi_enabled) { @@ -270,10 +238,14 @@ pub const GlobalConfiguration = struct { } }; -fn isValidPrescaler(comptime d: u32, comptime max: u8) bool { +fn isValidPrescaler(comptime d: u32, comptime max: u16) bool { return d <= max and std.math.isPowerOfTwo(d); } +fn isValidPLLmul(comptime m: u32) bool { + return m >= 2 and m <= 16; +} + fn getHPREdiv(comptime d: u32) u4 { return switch (d) { 1 => 0b0000, @@ -285,7 +257,7 @@ fn getHPREdiv(comptime d: u32) u4 { 128 => 0b1101, 256 => 0b1101, 512 => 0b1111, - else => 0b000, + else => @panic("Invalid prescaler"), }; } @@ -296,15 +268,10 @@ fn getAPPREdiv(comptime d: u32) u3 { 4 => 0b101, 8 => 0b110, 16 => 0b111, - else => 0b000, + else => @panic("Invalid prescaler"), }; } fn getPLLmul(comptime m: u32) u4 { - comptime { - if (m < 2 or m > 16) { - @compileError(comptimePrint("Invalid PLL mul: {}", .{m})); - } - } return @as(u4, m - 2); } From c10e3e66f4ca8eb93b31e7e0b46868489cc0ab63 Mon Sep 17 00:00:00 2001 From: Francisco Date: Sat, 30 Sep 2023 13:14:01 -0300 Subject: [PATCH 11/11] fixed a few bugs --- src/hals/STM32F103/clocks.zig | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/hals/STM32F103/clocks.zig b/src/hals/STM32F103/clocks.zig index ba9a04d..34f904b 100644 --- a/src/hals/STM32F103/clocks.zig +++ b/src/hals/STM32F103/clocks.zig @@ -47,21 +47,21 @@ pub const GlobalConfiguration = struct { const sys = config.sys orelse .{ .source = .HSI, .freq = 8 * MHz }; comptime var pll_config: ?PLLConfig = null; - comptime var pll_mul = 0; + comptime var pll_mul: u32 = 0; comptime var hsi_enabled = false; comptime var hse_enabled = false; - comptime var hse_freq = config.hse_freq orelse 8 * MHz; + comptime var hse_freq: u32 = config.hse_freq orelse 8 * MHz; - comptime var ahb_freq = config.ahb_freq orelse sys.freq; - comptime var ahb_div = sys.freq / ahb_freq; + comptime var ahb_freq: u32 = config.ahb_freq orelse sys.freq; + comptime var ahb_div: u32 = sys.freq / ahb_freq; - comptime var apb1_freq = config.apb1_freq orelse if (ahb_freq <= 36 * MHz) ahb_freq else 36 * MHz; + comptime var apb1_freq: u32 = config.apb1_freq orelse if (ahb_freq <= 36 * MHz) ahb_freq else 36 * MHz; comptime var apb1_div = ahb_freq / apb1_freq; - comptime var apb2_freq = config.apb2_freq orelse if (ahb_freq <= 72 * MHz) ahb_freq else 72 * MHz; - comptime var apb2_div = ahb_freq / apb1_freq; + comptime var apb2_freq: u32 = config.apb2_freq orelse if (ahb_freq <= 72 * MHz) ahb_freq else 72 * MHz; + comptime var apb2_div: u32 = ahb_freq / apb2_freq; // Do a comptime validation of config comptime { @@ -121,6 +121,7 @@ pub const GlobalConfiguration = struct { } } else { pll_config = .{ .source = .HSE, .freq = sys.freq }; + pll_mul = sys.freq / hse_freq; hse_enabled = true; } },