Skip to content

Commit e8b0a8e

Browse files
committed
Make pins_v2.zig adaptable to multiple chips
Previously pins_v2 was only available on the F303 and L47x, and only implemented for 7 GPIO ports on the later. This makes the pins api available to any number of pins (soft limited to 11 due to comptime LUT size). Importer can provide the available number of ports. This also makes the api available for stm32f429
1 parent 185e350 commit e8b0a8e

4 files changed

Lines changed: 510 additions & 431 deletions

File tree

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
const PinCommon = @import("../common/pins_v2.zig");
1+
const PinCommon = @import("../common/pins_v2.zig").get_pins(.{
2+
.portcount = 7,
3+
});
24
pub const GlobalConfiguration = PinCommon.GlobalConfiguration;

port/stmicro/stm32/src/hals/STM32F429.zig

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ const Digital_IO = microzig.drivers.base.Digital_IO;
3030

3131
const State = Digital_IO.State;
3232

33+
pub const pins = @import("./common/pins_v2.zig").get_pins(.{
34+
.portcount = 11,
35+
});
36+
3337
pub const clock = struct {
3438
pub const Domain = enum {
3539
cpu,
@@ -47,56 +51,63 @@ pub const clock_frequencies = .{
4751
.apb2 = 16_000_000,
4852
};
4953

50-
pub fn parse_pin(comptime spec: []const u8) type {
51-
const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}{Pin}\" scheme.";
52-
53-
if (spec[0] != 'P')
54-
@compileError(invalid_format_msg);
55-
if (spec[1] < 'A' or spec[1] > 'K')
56-
@compileError(invalid_format_msg);
57-
58-
const pin_number: comptime_int = std.fmt.parseInt(u4, spec[2..], 10) catch @compileError(invalid_format_msg);
59-
60-
return struct {
61-
/// 'A'...'K'
62-
const gpio_port_name = spec[1..2];
63-
const gpio_port = @field(peripherals, "GPIO" ++ gpio_port_name);
64-
const suffix = std.fmt.comptimePrint("{d}", .{pin_number});
65-
};
66-
}
54+
// TODO: There should be a common rcc with stuff like this, just like pins_v2.zig
55+
pub const rcc = struct {
56+
const util = @import("common/util.zig");
57+
const _rcc = microzig.chip.peripherals.RCC;
6758

68-
fn set_reg_field(reg: anytype, comptime field_name: anytype, value: anytype) void {
69-
var temp = reg.read();
70-
@field(temp, field_name) = value;
71-
reg.write(temp);
72-
}
59+
// Any peripheral that must be enable in RCC.
60+
pub const Peripherals = util.create_peripheral_enum(&.{
61+
"GPIO",
62+
});
7363

74-
pub const gpio = struct {
75-
pub fn set_output(comptime pin: type) void {
76-
const AHB1ENR: *volatile @TypeOf(RCC.AHB1ENR) = &RCC.AHB1ENR;
77-
const MODER: *volatile @TypeOf(@field(pin.gpio_port, "MODER")) = &@field(pin.gpio_port, "MODER");
78-
set_reg_field(AHB1ENR, "GPIO" ++ pin.gpio_port_name ++ "EN", 1);
79-
set_reg_field(MODER, "MODER[" ++ pin.suffix ++ "]", .Output);
64+
///configure the power and clock registers before enabling the RTC
65+
///this function also can be called from `rtc.enable()`
66+
pub fn enable_rtc(on: bool) void {
67+
_rcc.BDCR.modify(.{ .RTCEN = @intFromBool(on) });
8068
}
8169

82-
pub fn set_input(comptime pin: type) void {
83-
const AHB1ENR: *volatile @TypeOf(RCC.AHB1ENR) = &RCC.AHB1ENR;
84-
const MODER: *volatile @TypeOf(@field(pin.gpio_port, "MODER")) = &@field(pin.gpio_port, "MODER");
85-
set_reg_field(AHB1ENR, "GPIO" ++ pin.gpio_port_name ++ "EN", 1);
86-
set_reg_field(MODER, "MODER[" ++ pin.suffix ++ "]", .Input);
70+
pub fn set_clock(comptime peri: Peripherals, state: u1) void {
71+
const peri_name = @tagName(peri);
72+
const field = peri_name ++ "EN";
73+
if (util.match_name(peri_name, &.{"RTC"})) {
74+
enable_rtc(state != 0);
75+
return;
76+
}
77+
const rcc_register_name = comptime if (util.match_name(peri_name, &.{
78+
"OTGHSULPI",
79+
"OTGHS",
80+
"ETHMACPTP",
81+
"ETHMACRX",
82+
"ETHMACTX",
83+
"ETHMAC",
84+
"DMA2D",
85+
"DMA2",
86+
"DMA1",
87+
"CCMDATARAM",
88+
"BKPSRAM",
89+
"CRC",
90+
"GPIOK",
91+
"GPIOJ",
92+
"GPIOI",
93+
"GPIOH",
94+
"GPIOG",
95+
"GPIOF",
96+
"GPIOE",
97+
"GPIOD",
98+
"GPIOC",
99+
"GPIOB",
100+
"GPIOA",
101+
})) "AHB1ENR" else "AHB1ENR";
102+
103+
@field(_rcc, rcc_register_name).modify_one(field, state);
87104
}
88105

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

95-
pub fn write(comptime pin: type, state: State) void {
96-
const BSRR: *volatile @TypeOf(pin.gpio_port.BSRR) = &pin.gpio_port.BSRR;
97-
switch (state) {
98-
.low => set_reg_field(BSRR, "BR[" ++ pin.suffix ++ "]", 1),
99-
.high => set_reg_field(BSRR, "BS[" ++ pin.suffix ++ "]", 1),
100-
}
110+
pub fn disable_clock(comptime peri: Peripherals) void {
111+
set_clock(peri, 0);
101112
}
102113
};
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
const PinCommon = @import("../common/pins_v2.zig");
1+
const PinCommon = @import("../common/pins_v2.zig").get_pins(.{
2+
.portcount = 8,
3+
});
24
pub const GlobalConfiguration = PinCommon.GlobalConfiguration;

0 commit comments

Comments
 (0)