Skip to content
Merged
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
28 changes: 14 additions & 14 deletions port/stmicro/stm32/src/hals/STM32F103/exti.zig
Original file line number Diff line number Diff line change
Expand Up @@ -69,37 +69,37 @@ pub fn set_line(line: u4, port: gpio.Port) void {
pub fn set_line_edge(line: u5, edge: TriggerEdge) void {
switch (edge) {
.None => {
EXTI.RTSR.raw &= ~(@as(u32, 1) << line);
EXTI.FTSR.raw &= ~(@as(u32, 1) << line);
EXTI.@"RTSR[0]".raw &= ~(@as(u32, 1) << line);
EXTI.@"FTSR[0]".raw &= ~(@as(u32, 1) << line);
},
.rising => {
EXTI.RTSR.raw |= (@as(u32, 1) << line);
EXTI.FTSR.raw &= ~(@as(u32, 1) << line);
EXTI.@"RTSR[0]".raw |= (@as(u32, 1) << line);
EXTI.@"FTSR[0]".raw &= ~(@as(u32, 1) << line);
},
.falling => {
EXTI.RTSR.raw &= ~(@as(u32, 1) << line);
EXTI.FTSR.raw |= (@as(u32, 1) << line);
EXTI.@"RTSR[0]".raw &= ~(@as(u32, 1) << line);
EXTI.@"FTSR[0]".raw |= (@as(u32, 1) << line);
},
.both => {
EXTI.RTSR.raw |= (@as(u32, 1) << line);
EXTI.FTSR.raw |= (@as(u32, 1) << line);
EXTI.@"RTSR[0]".raw |= (@as(u32, 1) << line);
EXTI.@"FTSR[0]".raw |= (@as(u32, 1) << line);
},
}
}

pub fn set_event(line: u5, enable: bool) void {
if (enable) {
EXTI.EMR.raw |= (@as(u32, 1) << line);
EXTI.@"EMR[0]".raw |= (@as(u32, 1) << line);
} else {
EXTI.EMR.raw &= ~(@as(u32, 1) << line);
EXTI.@"EMR[0]".raw &= ~(@as(u32, 1) << line);
}
}

pub fn set_interrupt(line: u5, enable: bool) void {
if (enable) {
EXTI.IMR.raw |= (@as(u32, 1) << line);
EXTI.@"IMR[0]".raw |= (@as(u32, 1) << line);
} else {
EXTI.IMR.raw &= ~(@as(u32, 1) << line);
EXTI.@"IMR[0]".raw &= ~(@as(u32, 1) << line);
}
}

Expand All @@ -111,9 +111,9 @@ pub inline fn software_trigger(line: u5) void {

///check for pending lines (for both events and interrupts)
pub inline fn pending() pendingLine {
return @bitCast(@as(u20, @intCast(EXTI.PR.raw)));
return @bitCast(@as(u20, @intCast(EXTI.@"PR[0]".raw)));
}
///clears all pending lines returned by: `pending()`.
pub inline fn clear_pending(pendings: pendingLine) void {
EXTI.PR.raw = @as(u20, @bitCast(pendings));
EXTI.@"PR[0]".raw = @as(u20, @bitCast(pendings));
}
2 changes: 2 additions & 0 deletions port/stmicro/stm32/src/hals/STM32L47X/lcd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const LCD_RAM = extern struct {
COM3H: LCD_COM_H,
};

// LCD RAM is not correctly defined in the stm32-data from embassy
// The high segments occupy the full 32 bit but is limited a few lsb.
const ram: *volatile LCD_RAM = @ptrCast(&LCD.RAM_COM);

pub fn init_lcd() void {
Expand Down
21 changes: 13 additions & 8 deletions tools/regz/src/Database.zig
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ pub const Register = struct {
struct_id: ?StructID,
name: []const u8,
description: ?[]const u8,
ref_type: ?[]const u8,
size_bits: u64,
offset_bytes: u64,
count: ?u64,
Expand All @@ -147,17 +148,19 @@ pub const Register = struct {
pub fn from_row(allocator: Allocator, row: zqlite.Row) !Register {
const name = try allocator.dupe(u8, row.text(2));
const description: ?[]const u8 = if (row.nullableText(3)) |text| try allocator.dupe(u8, text) else null;
const ref_type: ?[]const u8 = if (row.nullableText(4)) |text| try allocator.dupe(u8, text) else null;
return Register{
.id = @enumFromInt(row.int(0)),
.struct_id = if (row.nullableInt(1)) |value| @enumFromInt(value) else null,
.name = name,
.description = description,
.size_bits = @intCast(row.int(4)),
.offset_bytes = @intCast(row.int(5)),
.count = if (row.nullableInt(6)) |value| @intCast(value) else null,
.access = std.meta.stringToEnum(Access, row.text(7)) orelse return error.InvalidAccess,
.reset_mask = if (row.nullableInt(8)) |value| @intCast(value) else null,
.reset_value = if (row.nullableInt(9)) |value| @intCast(value) else null,
.ref_type = ref_type,
.size_bits = @intCast(row.int(5)),
.offset_bytes = @intCast(row.int(6)),
.count = if (row.nullableInt(7)) |value| @intCast(value) else null,
.access = std.meta.stringToEnum(Access, row.text(8)) orelse return error.InvalidAccess,
.reset_mask = if (row.nullableInt(9)) |value| @intCast(value) else null,
.reset_value = if (row.nullableInt(10)) |value| @intCast(value) else null,
};
}

Expand Down Expand Up @@ -1705,6 +1708,7 @@ pub const CreateRegisterOptions = struct {
// make name required for now
name: []const u8,
description: ?[]const u8 = null,
ref_type: ?[]const u8 = null,
/// offset is in bytes
offset_bytes: u64,
/// size is in bits
Expand Down Expand Up @@ -1736,13 +1740,14 @@ pub fn create_register(db: *Database, parent: StructID, opts: CreateRegisterOpti
const register_id: RegisterID = blk: {
const row = try db.conn.row(
\\INSERT INTO registers
\\ (name, description, offset_bytes, size_bits, count, access, reset_mask, reset_value)
\\ (name, description, ref_type, offset_bytes, size_bits, count, access, reset_mask, reset_value)
\\VALUES
\\ (?, ?, ?, ?, ?, ?, ?, ?)
\\ (?, ?, ?, ?, ?, ?, ?, ?, ?)
\\RETURNING id
, .{
opts.name,
opts.description,
opts.ref_type,
opts.offset_bytes,
opts.size_bits,
opts.count,
Expand Down
194 changes: 143 additions & 51 deletions tools/regz/src/embassy.zig
Original file line number Diff line number Diff line change
Expand Up @@ -306,32 +306,122 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
});

for (obj.object.get("items").?.array.items) |item| {
var register_ids: std.ArrayList(Database.RegisterID) = .empty;
defer register_ids.deinit(allocator);
const register_name = item.object.get("name").?.string;
const description: ?[]const u8 = if (item.object.get("description")) |desc| desc.string else null;
const byte_offset = item.object.get("byte_offset").?.integer;
const byte_offset: u64 = @intCast(item.object.get("byte_offset").?.integer);
const item_bit_size = if (item.object.get("bit_size")) |v| v.integer else 32;
const maybe_count: ?u64, const maybe_stride: ?u64 = if (item.object.get("array")) |array| blk: {
if (array.object.get("len")) |count| {
if (count.integer == 1) break :blk .{ null, null };
if (array.object.get("stride")) |stride| {
if (stride.integer > 4) {
break :blk .{ @intCast(count.integer), @intCast(stride.integer) };
}
}
break :blk .{ @intCast(count.integer), null };
}

const register_id = try db.create_register(group_id, .{
.name = register_name,
.description = description,
.offset_bytes = @intCast(byte_offset),
.size_bits = @intCast(item_bit_size),
.count = if (item.object.get("array")) |array| blk: {
if (array.object.get("len")) |count| {
// ensure stride is always 4 for now, assuming that
// it's in bytes
const stride = array.object.get("stride").?.integer;
if (stride != 4) {
std.log.warn("ignoring register array with unsupported stride: {} != 4 for register {s} in {s} in {s}", .{ stride, register_name, key["block/".len..], name });
break :blk null;
break :blk .{ null, null };
} else .{ null, null };

// This register can be a cluster. In this case we can reference its type only.
// We still need to handle the stride. This is the reason we need to compute size
// of cluster.
if (item.object.get("block")) |block| {
const ref_type = block.string;
const block_key = try std.fmt.allocPrint(allocator, "block/{s}", .{ref_type});
const block_value = (register_file.value.object.get(block_key) orelse continue).object;
var max_bytes: u64 = 0;
for (block_value.get("items").?.array.items) |nested_item| {
// Let's assume we do not recurse on block
const offset: u64 = @intCast(nested_item.object.get("byte_offset").?.integer);
if (nested_item.object.get("array")) |array| {
if (array.object.get("len")) |count| {
if (array.object.get("stride")) |stride| {
max_bytes = @max(offset + 4 + @as(u64, @intCast(stride.integer * (count.integer - 1))), max_bytes);
continue;
}
}
}
max_bytes = @max(offset + 4, max_bytes);
}

break :blk @intCast(count.integer);
if (maybe_stride == max_bytes) {
// We have a contiguous cluster array
_ = try db.create_register(group_id, .{
.name = register_name,
.description = description,
.ref_type = ref_type,
.offset_bytes = @intCast(byte_offset),
.size_bits = max_bytes * 8,
.count = maybe_count,
});
continue;
} else if (maybe_stride) |stride| {
// We have spread cluster
for (0..maybe_count.?) |id| {
const register_part_name = try std.fmt.allocPrint(allocator, "{s}[{d}]", .{
register_name,
id,
});
_ = try db.create_register(group_id, .{
.name = register_part_name,
.description = description,
.ref_type = ref_type,
.offset_bytes = byte_offset + (id * stride),
.size_bits = max_bytes * 8,
.count = null,
});
}
continue;
} else if (maybe_stride == null) {
// We have a single cluster
_ = try db.create_register(group_id, .{
.name = register_name,
.description = description,
.ref_type = ref_type,
.offset_bytes = @intCast(byte_offset),
.size_bits = max_bytes * 8,
.count = null,
});
continue;
}
// No match default to u32
// At this point it should be unreachable.
// I leave this comment as a placeholder for other special cases.
}

break :blk null;
} else null,
});
// Not a cluster but a fieldset
if (maybe_stride) |stride| {
if (maybe_count) |count| {
// We spread the register as it jumps over other registers
for (0..count) |id| {
const register_part_name = try std.fmt.allocPrint(allocator, "{s}[{d}]", .{
register_name,
id,
});
const register_id = try db.create_register(group_id, .{
.name = register_part_name,
.description = description,
.offset_bytes = byte_offset + (id * stride),
.size_bits = @intCast(item_bit_size),
.count = null,
});
try register_ids.append(allocator, register_id);
}
}
} else {
const register_id = try db.create_register(group_id, .{
.name = register_name,
.description = description,
.offset_bytes = @intCast(byte_offset),
.size_bits = @intCast(item_bit_size),
.count = maybe_count,
});
try register_ids.append(allocator, register_id);
}

if (item.object.get("fieldset")) |fieldset| blk: {
const fieldset_key = try std.fmt.allocPrint(allocator, "fieldset/{s}", .{fieldset.string});
Expand All @@ -356,7 +446,7 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
// these are evenly spaced and much nicer to work with.

array_count = if (object_map.get("len")) |len| @intCast(len.integer) else null;
array_stride = if (object_map.get("stride")) |stride| @intCast(stride.integer) else null;
array_stride = if (object_map.get("stride")) |field_stride| @intCast(field_stride.integer) else null;

// This category where there is an array of items, but it is given by
// individual offsets as opposed to a count + stride. This is used when strides are
Expand All @@ -365,30 +455,32 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
if (object_map.get("offsets")) |positions| {
for (positions.array.items, 0..) |position, idx| {
const field_name_irregular_stride = try std.fmt.allocPrint(allocator, "{s}[{}]", .{ field_name, idx });

try db.add_register_field(register_id, .{
.name = field_name_irregular_stride,
.description = field_description,
.offset_bits = @intCast(position.integer + bit_offset),
.size_bits = @intCast(bit_size),
.enum_id = enum_id,
.count = null,
.stride = null,
});
for (register_ids.items) |register_id| {
try db.add_register_field(register_id, .{
.name = field_name_irregular_stride,
.description = field_description,
.offset_bits = @intCast(position.integer + bit_offset),
.size_bits = @intCast(bit_size),
.enum_id = enum_id,
.count = null,
.stride = null,
});
}
}
continue :next_field;
}
}

try db.add_register_field(register_id, .{
.name = field_name,
.description = field_description,
.offset_bits = @intCast(bit_offset),
.size_bits = @intCast(bit_size),
.enum_id = enum_id,
.count = array_count,
.stride = array_stride,
});
for (register_ids.items) |register_id| {
try db.add_register_field(register_id, .{
.name = field_name,
.description = field_description,
.offset_bits = @intCast(bit_offset),
.size_bits = @intCast(bit_size),
.enum_id = enum_id,
.count = array_count,
.stride = array_stride,
});
}
},
.array => |arr| {
// This case is for discontinuous fields where the first few bits are
Expand All @@ -411,18 +503,19 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
var array_stride: ?u8 = null;
if (field.object.get("array")) |array| {
array_count = if (array.object.get("len")) |len| @intCast(len.integer) else null;
array_stride = if (array.object.get("stride")) |stride| @intCast(stride.integer) else null;
array_stride = if (array.object.get("stride")) |field_stride| @intCast(field_stride.integer) else null;
}
for (register_ids.items) |register_id| {
try db.add_register_field(register_id, .{
.name = non_contiguous_field_name,
.description = field_description,
.offset_bits = @intCast(bit_offset),
.size_bits = @intCast(bit_size),
.enum_id = enum_id,
.count = array_count,
.stride = array_stride,
});
}

try db.add_register_field(register_id, .{
.name = non_contiguous_field_name,
.description = field_description,
.offset_bits = @intCast(bit_offset),
.size_bits = @intCast(bit_size),
.enum_id = enum_id,
.count = array_count,
.stride = array_stride,
});
}
},
else => |val| {
Expand Down Expand Up @@ -603,4 +696,3 @@ const std = @import("std");
const Database = @import("Database.zig");
const Arch = @import("arch.zig").Arch;
const arm = @import("arch/arm.zig");
const FS_Directory = @import("FS_Directory.zig");
Loading