Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions examples/stmicro/stm32/src/blinky.zig
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ pub fn main() !void {
pins.LD10,
};
break :res .{ pins, all_leds };
} else if (comptime microzig.config.board_name != null and std.mem.eql(u8, microzig.config.board_name.?, "STM32F429IDISCOVERY")) {
const pins = board.leds_config.apply();
const all_leds = .{
pins.LD3,
pins.LD4,
};
break :res .{ pins, all_leds };
} else if (comptime microzig.config.board_name != null and std.mem.eql(u8, microzig.config.board_name.?, "STM32L476DISCOVERY")) {
const pins = board.leds_config.apply();
const all_leds = .{
Expand Down
4 changes: 4 additions & 0 deletions port/stmicro/stm32/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ pub fn init(dep: *std.Build.Dependency) Self {
.name = "STM32F429IDISCOVERY",
.root_source_file = b.path("src/boards/STM32F429IDISCOVERY.zig"),
},
.hal = microzig.HardwareAbstractionLayer{
.root_source_file = b.path("src/hals/STM32F429.zig"),
.imports = hal_imports,
},
}),
},
};
Expand Down
11 changes: 11 additions & 0 deletions port/stmicro/stm32/src/boards/STM32F429IDISCOVERY.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
pub const microzig = @import("microzig");

pub const hal = microzig.hal;

pub const cpu_frequency = 16_000_000;

pub const pin_map = .{
Expand All @@ -10,3 +14,10 @@ pub const pin_map = .{
// User button
.B1 = "PA0",
};

pub const leds_config = (hal.pins.GlobalConfiguration{
.GPIOG = .{
.PIN13 = .{ .name = "LD3", .mode = .{ .output = .{ .resistor = .Floating, .o_type = .PushPull } } },
.PIN14 = .{ .name = "LD4", .mode = .{ .output = .{ .resistor = .Floating, .o_type = .PushPull } } },
},
});
1 change: 1 addition & 0 deletions port/stmicro/stm32/src/hals/STM32F103.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub const backup = @import("./STM32F103/backup.zig");
pub const rtc = @import("./STM32F103/rtc.zig");
pub const dma = @import("./STM32F103/dma.zig");
pub const time = @import("./STM32F103/time.zig");
pub const enums = @import("./common/enums.zig");
const util = @import("./common/util.zig");

//temporary solution
Expand Down
2 changes: 1 addition & 1 deletion port/stmicro/stm32/src/hals/STM32F303.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub const i2c = @import("STM32F303/i2c.zig");
pub const spi = @import("STM32F303/spi.zig");
pub const pins = @import("STM32F303/pins.zig");
pub const dma = @import("./STM32F303/dma.zig");
pub const enums = @import("./common//enums.zig");
pub const enums = @import("./common/enums.zig");
pub const systick_timer = @import("./common/systick_timer.zig");
pub const systick = @import("./common/systick.zig");

Expand Down
102 changes: 61 additions & 41 deletions port/stmicro/stm32/src/hals/STM32F429.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
//! default AHB prescaler = /1 (= values 0..7):
//!
//! ```
//! RCC.CFGR.modify(.{ .HPRE = 0 });
//! RCC.CFGR.modify(.{ .HPRE = .Div1 });
//! ```
//!
//! so also HCLK = 16 MHz.
//! And with the default APB1 prescaler = /1:
//!
//! ```
//! RCC.CFGR.modify(.{ .PPRE1 = 0 });
//! RCC.CFGR.modify(.{ .PPRE1 = .Div1 });
//! ```
//!
//! results in PCLK1 = 16 MHz.
Expand All @@ -22,9 +22,17 @@

const std = @import("std");
const microzig = @import("microzig");
const peripherals = microzig.peripherals;
const mmio = microzig.mmio;
const peripherals = microzig.chip.peripherals;
const RCC = peripherals.RCC;

pub const pins = @import("./common/pins_v2.zig");
pub const enums = @import("./common/enums.zig");

const Digital_IO = microzig.drivers.base.Digital_IO;

const State = Digital_IO.State;

pub const clock = struct {
pub const Domain = enum {
cpu,
Expand All @@ -42,51 +50,63 @@ pub const clock_frequencies = .{
.apb2 = 16_000_000,
};

pub fn parse_pin(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.";

if (spec[0] != 'P')
@compileError(invalid_format_msg);
if (spec[1] < 'A' or spec[1] > 'K')
@compileError(invalid_format_msg);

const pin_number: comptime_int = std.fmt.parseInt(u4, spec[2..], 10) catch @compileError(invalid_format_msg);
// TODO: There should be a common rcc with stuff like this, just like pins_v2.zig
pub const rcc = struct {
const util = @import("common/util.zig");
const _rcc = microzig.chip.peripherals.RCC;

return struct {
/// 'A'...'K'
const gpio_port_name = spec[1..2];
const gpio_port = @field(peripherals, "GPIO" ++ gpio_port_name);
const suffix = std.fmt.comptimePrint("{d}", .{pin_number});
};
}

fn set_reg_field(reg: anytype, comptime field_name: anytype, value: anytype) void {
var temp = reg.read();
@field(temp, field_name) = value;
reg.write(temp);
}
// Any peripheral that must be enable in RCC.
pub const Peripherals = util.create_peripheral_enum(&.{
"GPIO",
});

pub const gpio = struct {
pub fn set_output(comptime pin: type) void {
set_reg_field(RCC.AHB1ENR, "GPIO" ++ pin.gpio_port_name ++ "EN", 1);
set_reg_field(@field(pin.gpio_port, "MODER"), "MODER" ++ pin.suffix, 0b01);
///configure the power and clock registers before enabling the RTC
///this function also can be called from `rtc.enable()`
pub fn enable_rtc(on: bool) void {
_rcc.BDCR.modify(.{ .RTCEN = @intFromBool(on) });
}

pub fn set_input(comptime pin: type) void {
set_reg_field(RCC.AHB1ENR, "GPIO" ++ pin.gpio_port_name ++ "EN", 1);
set_reg_field(@field(pin.gpio_port, "MODER"), "MODER" ++ pin.suffix, 0b00);
pub fn set_clock(comptime peri: Peripherals, state: u1) void {
const peri_name = @tagName(peri);
const field = peri_name ++ "EN";
if (util.match_name(peri_name, &.{"RTC"})) {
enable_rtc(state != 0);
return;
}
const rcc_register_name = comptime if (util.match_name(peri_name, &.{
"OTGHSULPI",
"OTGHS",
"ETHMACPTP",
"ETHMACRX",
"ETHMACTX",
"ETHMAC",
"DMA2D",
"DMA2",
"DMA1",
"CCMDATARAM",
"BKPSRAM",
"CRC",
"GPIOK",
"GPIOJ",
"GPIOI",
"GPIOH",
"GPIOG",
"GPIOF",
"GPIOE",
"GPIOD",
"GPIOC",
"GPIOB",
"GPIOA",
})) "AHB1ENR" else "AHB1ENR";

@field(_rcc, rcc_register_name).modify_one(field, state);
}

pub fn read(comptime pin: type) microzig.gpio.State {
const idr_reg = pin.gpio_port.IDR;
const reg_value = @field(idr_reg.read(), "IDR" ++ pin.suffix); // TODO extract to getRegField()?
return @as(microzig.gpio.State, @enumFromInt(reg_value));
pub fn enable_clock(comptime peri: Peripherals) void {
set_clock(peri, 1);
}

pub fn write(comptime pin: type, state: microzig.gpio.State) void {
switch (state) {
.low => set_reg_field(pin.gpio_port.BSRR, "BR" ++ pin.suffix, 1),
.high => set_reg_field(pin.gpio_port.BSRR, "BS" ++ pin.suffix, 1),
}
pub fn disable_clock(comptime peri: Peripherals) void {
set_clock(peri, 0);
}
};
1 change: 0 additions & 1 deletion port/stmicro/stm32/src/hals/common/bdma_v2.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const dma_common = @import("dma_common.zig");
const enums = @import("../common/enums.zig");
pub const Instances = enums.DMA_Type;

const hal = microzig.hal;
const DMA_Peripheral = microzig.chip.types.peripherals.bdma_v2.DMA;

pub const Error = error{
Expand Down
65 changes: 31 additions & 34 deletions port/stmicro/stm32/src/hals/common/enums.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,17 @@ const util = @import("util.zig");
const microzig = @import("microzig");

// Any peripheral that must be enable in RCC.
pub const Peripherals = util.create_peripheral_enum(&.{
"DMA",
"USBRAM",
"FLASH",
"CRC",
"SDIO",
"AFIO",
"GPIO",
"ADC",
"TIM",
"SPI",
"USART",
"WWDG",
"UART",
"I2C",
"CAN",
"BKP",
"PWR",
"DAC",
"RTC",
"USB",
"LPUART",
});
pub const Peripherals = util.create_peripheral_enum();

pub const UART_Type = util.sub_peripheral_enum(Peripherals, &.{ "USART", "UART", "LPUART" }, null);
pub const I2C_Type = util.sub_peripheral_enum(Peripherals, &.{"I2C"}, null);
pub const SPI_Type = util.sub_peripheral_enum(Peripherals, &.{"SPI"}, null);
pub const DMA_Type = util.sub_peripheral_enum(Peripherals, &.{"DMA"}, null);
pub const TIMGP16_Type = util.sub_peripheral_enum(Peripherals, &.{"TIM"}, "TIM_GP16");
pub const ADC_Type = util.sub_peripheral_enum(Peripherals, &.{"ADC"}, null);
pub const UART_Type = util.sub_peripheral_enum(Peripherals, .{ "USART", "UART", "LPUART" }, null);
pub const I2C_Type = util.sub_peripheral_enum(Peripherals, .{"I2C"}, null);
pub const SPI_Type = util.sub_peripheral_enum(Peripherals, .{"SPI"}, null);
pub const DMA_Type = util.sub_peripheral_enum(Peripherals, .{"DMA"}, null);
pub const TIMGP16_Type = util.sub_peripheral_enum(Peripherals, .{"TIM"}, "TIM_GP16");
pub const ADC_Type = util.sub_peripheral_enum(Peripherals, .{"ADC"}, null);
pub const CAN_Type = util.sub_peripheral_enum(Peripherals, .{"CAN"}, null);
pub const SAL_Type = util.sub_peripheral_enum(Peripherals, .{"SAL"}, null);
pub const I2S_Type = util.sub_peripheral_enum(Peripherals, .{"I2S"}, null);

pub fn to_peripheral(comptime val: anytype) Peripherals {
return switch (@TypeOf(val)) {
Expand All @@ -42,6 +23,9 @@ pub fn to_peripheral(comptime val: anytype) Peripherals {
DMA_Type,
TIMGP16_Type,
ADC_Type,
CAN_Type,
SAL_Type,
I2S_Type,
=> @as(Peripherals, @enumFromInt(@intFromEnum(val))),
else => @panic("Value must be one of the sur peripheral enum define below"),
};
Expand All @@ -52,12 +36,25 @@ pub fn get_regs(comptime T: type, comptime val: anytype) *volatile T {
return @field(microzig.chip.peripherals, @tagName(periph_enum));
}

fn get_field_index(comptime T: type, comptime val: T) u32 {
inline for (0.., @typeInfo(T).@"enum".fields) |i, field| {
if (field.value == @intFromEnum(val)) {
return i;
}
}
}

// This function is basically useless, it doesn't even give the number of the paripheral
pub fn base_perihperal_index(comptime val: anytype) u32 {
return switch (@TypeOf(val)) {
UART_Type => @intFromEnum(val) - @intFromEnum(Peripherals.USART1),
I2C_Type => @intFromEnum(val) - @intFromEnum(Peripherals.I2C1),
SPI_Type => @intFromEnum(val) - @intFromEnum(Peripherals.SPI1),
DMA_Type => @intFromEnum(val) - @intFromEnum(Peripherals.DMA1),
else => @panic("Index peripheral is only for multiple index peripherals"),
UART_Type => get_field_index(UART_Type, val),
I2C_Type => get_field_index(I2C_Type, val),
SPI_Type => get_field_index(I2C_Type, val),
DMA_Type => get_field_index(I2C_Type, val),
ADC_Type => get_field_index(I2C_Type, val),
CAN_Type => get_field_index(I2C_Type, val),
SAL_Type => get_field_index(I2C_Type, val),
I2S_Type => get_field_index(I2C_Type, val),
else => @panic("Index peripheral is only for multiple index peripherals"), // TODO: Whats against implementing this for all?
};
}
Loading
Loading