diff --git a/src/core/clock.zig b/src/core/clock.zig index a7d8b64..71056bd 100644 --- a/src/core/clock.zig +++ b/src/core/clock.zig @@ -1,5 +1,6 @@ const std = @import("std"); const micro = @import("microzig.zig"); +const chip = @import("chip"); /// An enumeration of clock sources. pub const Source = enum { @@ -10,6 +11,9 @@ pub const Source = enum { cpu, }; +/// A struct containing the frequency in hertz for each clock domain +pub const Clocks = std.enums.EnumFieldStruct(chip.clock.Domain, u32, null); + /// Is `true` when microzig has a clock frequency available. /// Clock can be provided by several clock sources pub const has_clock = (clock_source_type != void); @@ -30,16 +34,16 @@ pub const source: Source = switch (clock_source_type) { /// Ensures that microzig has a clock available. This will @compileError when no clock is available, otherwise, it will be a no-op. pub fn ensure() void { if (!has_clock) - @compileError("microzig requires the clock frequency to perform this operation. Please export a const or var cpu_frequency from your root file that contains the cpu frequency in hertz!"); + @compileError("microzig requires the clock frequency to perform this operation. Please export a const or var clock_frequencies from your root file that contains the clock frequency for all chip clock domains in hertz!"); } -/// Returns the current cpu frequency in hertz. -pub inline fn get() u32 { +/// Returns the Clocks struct, with all clock domains frequencies in hertz. +pub inline fn get() Clocks { ensure(); return @field(clock_source_type, freq_decl_name); } -const freq_decl_name = "cpu_frequency"; +const freq_decl_name = "clock_frequencies"; const no_clock_source_type = opaque {}; const clock_source_type = if (@hasDecl(micro.app, freq_decl_name)) diff --git a/src/modules/boards/arduino-nano/arduino-nano.zig b/src/modules/boards/arduino-nano/arduino-nano.zig index 16ade81..96490f8 100644 --- a/src/modules/boards/arduino-nano/arduino-nano.zig +++ b/src/modules/boards/arduino-nano/arduino-nano.zig @@ -1,6 +1,8 @@ pub const chip = @import("chip"); -pub const cpu_frequency = 16_000_000; +pub const clock_frequencies = .{ + .cpu = 16_000_000, +}; pub const pin_map = .{ // Port A diff --git a/src/modules/boards/mbed-lpc1768/mbed-lpc1768.zig b/src/modules/boards/mbed-lpc1768/mbed-lpc1768.zig index 03a5fbb..6c5ff9d 100644 --- a/src/modules/boards/mbed-lpc1768/mbed-lpc1768.zig +++ b/src/modules/boards/mbed-lpc1768/mbed-lpc1768.zig @@ -1,7 +1,9 @@ pub const chip = @import("chip"); pub const micro = @import("microzig"); -pub const cpu_frequency: u32 = 100_000_000; // 100 MHz +pub const clock_frequencies = .{ + .cpu = 100_000_000, // 100 Mhz +}; pub fn debugWrite(string: []const u8) void { const clk_pin = micro.Pin("DIP5"); diff --git a/src/modules/boards/stm32f4discovery/stm32f4discovery.zig b/src/modules/boards/stm32f4discovery/stm32f4discovery.zig index 8fdf824..7703b1d 100644 --- a/src/modules/boards/stm32f4discovery/stm32f4discovery.zig +++ b/src/modules/boards/stm32f4discovery/stm32f4discovery.zig @@ -1,8 +1,6 @@ pub const chip = @import("chip"); pub const micro = @import("microzig"); -pub const cpu_frequency = 16_000_000; - pub const pin_map = .{ // LED cross, connected to GPIOD bits 12..15 // N orange diff --git a/src/modules/chips/atmega328p/atmega328p.zig b/src/modules/chips/atmega328p/atmega328p.zig index 43022a8..9375a6d 100644 --- a/src/modules/chips/atmega328p/atmega328p.zig +++ b/src/modules/chips/atmega328p/atmega328p.zig @@ -11,6 +11,12 @@ const Port = enum(u8) { D = 3, }; +pub const clock = struct { + pub const Domain = enum { + cpu, + }; +}; + pub fn parsePin(comptime spec: []const u8) type { const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}{Pin}\" scheme."; @@ -94,14 +100,14 @@ pub fn Uart(comptime index: usize) type { const Self = @This(); fn computeDivider(baud_rate: u32) !u12 { - const pclk = micro.clock.get(); + const pclk = micro.clock.get().cpu; const divider = ((pclk + (8 * baud_rate)) / (16 * baud_rate)) - 1; return std.math.cast(u12, divider) catch return error.UnsupportedBaudRate; } fn computeBaudRate(divider: u12) u32 { - return micro.clock.get() / (16 * @as(u32, divider) + 1); + return micro.clock.get().cpu / (16 * @as(u32, divider) + 1); } pub fn init(config: micro.uart.Config) !Self { diff --git a/src/modules/chips/lpc1768/lpc1768.zig b/src/modules/chips/lpc1768/lpc1768.zig index 2ca08d7..93a88a4 100644 --- a/src/modules/chips/lpc1768/lpc1768.zig +++ b/src/modules/chips/lpc1768/lpc1768.zig @@ -5,7 +5,15 @@ const regs = chip.registers; pub usingnamespace chip; -pub const cpu_frequency: u32 = 100_000_000; // 100 MHz +pub const clock = struct { + pub const Domain = enum { + cpu, + }; +}; + +pub const clock_frequencies = .{ + .cpu = 100_000_000, // 100 Mhz +}; pub const PinTarget = enum(u2) { func00 = 0b00, @@ -156,11 +164,11 @@ pub fn Uart(comptime index: usize) type { //UARTn.FCR.modify(.{ .FIFOEN = .UARTN_FIFOS_ARE_DISA }); micro.debug.writer().print("clock: {} baud: {} ", .{ - micro.clock.get(), + micro.clock.get().cpu, config.baud_rate, }) catch {}; - const pclk = micro.clock.get() / 4; + const pclk = micro.clock.get().cpu / 4; const divider = (pclk / (16 * config.baud_rate)); const regval = std.math.cast(u16, divider) orelse return error.UnsupportedBaudRate; diff --git a/src/modules/chips/stm32f303/stm32f303.zig b/src/modules/chips/stm32f303/stm32f303.zig index 4bbfb0f..4b8ff37 100644 --- a/src/modules/chips/stm32f303/stm32f303.zig +++ b/src/modules/chips/stm32f303/stm32f303.zig @@ -43,6 +43,24 @@ const regs = chip.registers; pub usingnamespace chip; pub const cpu = @import("cpu"); + +pub const clock = struct { + pub const Domain = enum { + cpu, + ahb, + apb1, + apb2, + }; +}; + +// Default clock frequencies after reset, see top comment for calculation +pub const clock_frequencies = .{ + .cpu = 8_000_000, + .ahb = 8_000_000, + .apb1 = 8_000_000, + .apb2 = 8_000_000, +}; + pub fn parsePin(comptime spec: []const u8) type { const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}{Pin}\" scheme."; @@ -170,7 +188,7 @@ pub fn Uart(comptime index: usize) type { // if the board doesn't configure e.g. an HSE external crystal. // TODO: Do some checks to see if the baud rate is too high (or perhaps too low) // TODO: Do a rounding div, instead of a truncating div? - const usartdiv = @intCast(u16, @divTrunc(micro.board.cpu_frequency, config.baud_rate)); + const usartdiv = @intCast(u16, @divTrunc(micro.clock.get().apb1, config.baud_rate)); regs.USART1.BRR.raw = usartdiv; // Above, ignore the BRR struct fields DIV_Mantissa and DIV_Fraction, // those seem to be for another chipset; .svd file bug? diff --git a/src/modules/chips/stm32f407/stm32f407.zig b/src/modules/chips/stm32f407/stm32f407.zig index 689e77d..17f4039 100644 --- a/src/modules/chips/stm32f407/stm32f407.zig +++ b/src/modules/chips/stm32f407/stm32f407.zig @@ -39,11 +39,22 @@ const regs = chip.registers; pub usingnamespace chip; +pub const clock = struct { + pub const Domain = enum { + cpu, + ahb, + apb1, + apb2, + }; +}; + // Default clock frequencies after reset, see top comment for calculation -// TODO: these would need to change when we support multiple clock configurations -pub const ahb_frequency = 16_000_000; -pub const apb1_frequency = 16_000_000; -pub const apb2_frequency = 16_000_000; +pub const clock_frequencies = .{ + .cpu = 16_000_000, + .ahb = 16_000_000, + .apb1 = 16_000_000, + .apb2 = 16_000_000, +}; pub fn parsePin(comptime spec: []const u8) type { const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}{Pin}\" scheme."; @@ -227,7 +238,7 @@ pub fn Uart(comptime index: usize) type { // TODO: We assume the default OVER8=0 configuration above (i.e. 16x oversampling). // TODO: Do some checks to see if the baud rate is too high (or perhaps too low) // TODO: Do a rounding div, instead of a truncating div? - const usartdiv = @intCast(u16, @divTrunc(apb1_frequency, config.baud_rate)); + const usartdiv = @intCast(u16, @divTrunc(micro.clock.get().apb1, config.baud_rate)); @field(regs, usart_name).BRR.raw = usartdiv; // enable USART, and its transmitter and receiver diff --git a/src/modules/chips/stm32f429/stm32f429.zig b/src/modules/chips/stm32f429/stm32f429.zig index 737a83f..d40d92b 100644 --- a/src/modules/chips/stm32f429/stm32f429.zig +++ b/src/modules/chips/stm32f429/stm32f429.zig @@ -27,6 +27,23 @@ const regs = chip.registers; pub usingnamespace chip; +pub const clock = struct { + pub const Domain = enum { + cpu, + ahb, + apb1, + apb2, + }; +}; + +// Default clock frequencies after reset, see top comment for calculation +pub const clock_frequencies = .{ + .cpu = 16_000_000, + .ahb = 16_000_000, + .apb1 = 16_000_000, + .apb2 = 16_000_000, +}; + pub fn parsePin(comptime spec: []const u8) type { const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}{Pin}\" scheme.";