Skip to content

Commit 88aaa5f

Browse files
authored
Regz: Fix embassy stride > 4 (#906)
This should address issue #416
1 parent deb03e7 commit 88aaa5f

File tree

5 files changed

+186
-73
lines changed

5 files changed

+186
-73
lines changed

port/stmicro/stm32/src/hals/STM32F103/exti.zig

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,37 +69,37 @@ pub fn set_line(line: u4, port: gpio.Port) void {
6969
pub fn set_line_edge(line: u5, edge: TriggerEdge) void {
7070
switch (edge) {
7171
.None => {
72-
EXTI.RTSR.raw &= ~(@as(u32, 1) << line);
73-
EXTI.FTSR.raw &= ~(@as(u32, 1) << line);
72+
EXTI.@"RTSR[0]".raw &= ~(@as(u32, 1) << line);
73+
EXTI.@"FTSR[0]".raw &= ~(@as(u32, 1) << line);
7474
},
7575
.rising => {
76-
EXTI.RTSR.raw |= (@as(u32, 1) << line);
77-
EXTI.FTSR.raw &= ~(@as(u32, 1) << line);
76+
EXTI.@"RTSR[0]".raw |= (@as(u32, 1) << line);
77+
EXTI.@"FTSR[0]".raw &= ~(@as(u32, 1) << line);
7878
},
7979
.falling => {
80-
EXTI.RTSR.raw &= ~(@as(u32, 1) << line);
81-
EXTI.FTSR.raw |= (@as(u32, 1) << line);
80+
EXTI.@"RTSR[0]".raw &= ~(@as(u32, 1) << line);
81+
EXTI.@"FTSR[0]".raw |= (@as(u32, 1) << line);
8282
},
8383
.both => {
84-
EXTI.RTSR.raw |= (@as(u32, 1) << line);
85-
EXTI.FTSR.raw |= (@as(u32, 1) << line);
84+
EXTI.@"RTSR[0]".raw |= (@as(u32, 1) << line);
85+
EXTI.@"FTSR[0]".raw |= (@as(u32, 1) << line);
8686
},
8787
}
8888
}
8989

9090
pub fn set_event(line: u5, enable: bool) void {
9191
if (enable) {
92-
EXTI.EMR.raw |= (@as(u32, 1) << line);
92+
EXTI.@"EMR[0]".raw |= (@as(u32, 1) << line);
9393
} else {
94-
EXTI.EMR.raw &= ~(@as(u32, 1) << line);
94+
EXTI.@"EMR[0]".raw &= ~(@as(u32, 1) << line);
9595
}
9696
}
9797

9898
pub fn set_interrupt(line: u5, enable: bool) void {
9999
if (enable) {
100-
EXTI.IMR.raw |= (@as(u32, 1) << line);
100+
EXTI.@"IMR[0]".raw |= (@as(u32, 1) << line);
101101
} else {
102-
EXTI.IMR.raw &= ~(@as(u32, 1) << line);
102+
EXTI.@"IMR[0]".raw &= ~(@as(u32, 1) << line);
103103
}
104104
}
105105

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

112112
///check for pending lines (for both events and interrupts)
113113
pub inline fn pending() pendingLine {
114-
return @bitCast(@as(u20, @intCast(EXTI.PR.raw)));
114+
return @bitCast(@as(u20, @intCast(EXTI.@"PR[0]".raw)));
115115
}
116116
///clears all pending lines returned by: `pending()`.
117117
pub inline fn clear_pending(pendings: pendingLine) void {
118-
EXTI.PR.raw = @as(u20, @bitCast(pendings));
118+
EXTI.@"PR[0]".raw = @as(u20, @bitCast(pendings));
119119
}

port/stmicro/stm32/src/hals/STM32L47X/lcd.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ const LCD_RAM = extern struct {
2222
COM3H: LCD_COM_H,
2323
};
2424

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

2729
pub fn init_lcd() void {

tools/regz/src/Database.zig

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ pub const Register = struct {
130130
struct_id: ?StructID,
131131
name: []const u8,
132132
description: ?[]const u8,
133+
ref_type: ?[]const u8,
133134
size_bits: u64,
134135
offset_bytes: u64,
135136
count: ?u64,
@@ -147,17 +148,19 @@ pub const Register = struct {
147148
pub fn from_row(allocator: Allocator, row: zqlite.Row) !Register {
148149
const name = try allocator.dupe(u8, row.text(2));
149150
const description: ?[]const u8 = if (row.nullableText(3)) |text| try allocator.dupe(u8, text) else null;
151+
const ref_type: ?[]const u8 = if (row.nullableText(4)) |text| try allocator.dupe(u8, text) else null;
150152
return Register{
151153
.id = @enumFromInt(row.int(0)),
152154
.struct_id = if (row.nullableInt(1)) |value| @enumFromInt(value) else null,
153155
.name = name,
154156
.description = description,
155-
.size_bits = @intCast(row.int(4)),
156-
.offset_bytes = @intCast(row.int(5)),
157-
.count = if (row.nullableInt(6)) |value| @intCast(value) else null,
158-
.access = std.meta.stringToEnum(Access, row.text(7)) orelse return error.InvalidAccess,
159-
.reset_mask = if (row.nullableInt(8)) |value| @intCast(value) else null,
160-
.reset_value = if (row.nullableInt(9)) |value| @intCast(value) else null,
157+
.ref_type = ref_type,
158+
.size_bits = @intCast(row.int(5)),
159+
.offset_bytes = @intCast(row.int(6)),
160+
.count = if (row.nullableInt(7)) |value| @intCast(value) else null,
161+
.access = std.meta.stringToEnum(Access, row.text(8)) orelse return error.InvalidAccess,
162+
.reset_mask = if (row.nullableInt(9)) |value| @intCast(value) else null,
163+
.reset_value = if (row.nullableInt(10)) |value| @intCast(value) else null,
161164
};
162165
}
163166

@@ -1705,6 +1708,7 @@ pub const CreateRegisterOptions = struct {
17051708
// make name required for now
17061709
name: []const u8,
17071710
description: ?[]const u8 = null,
1711+
ref_type: ?[]const u8 = null,
17081712
/// offset is in bytes
17091713
offset_bytes: u64,
17101714
/// size is in bits
@@ -1736,13 +1740,14 @@ pub fn create_register(db: *Database, parent: StructID, opts: CreateRegisterOpti
17361740
const register_id: RegisterID = blk: {
17371741
const row = try db.conn.row(
17381742
\\INSERT INTO registers
1739-
\\ (name, description, offset_bytes, size_bits, count, access, reset_mask, reset_value)
1743+
\\ (name, description, ref_type, offset_bytes, size_bits, count, access, reset_mask, reset_value)
17401744
\\VALUES
1741-
\\ (?, ?, ?, ?, ?, ?, ?, ?)
1745+
\\ (?, ?, ?, ?, ?, ?, ?, ?, ?)
17421746
\\RETURNING id
17431747
, .{
17441748
opts.name,
17451749
opts.description,
1750+
opts.ref_type,
17461751
opts.offset_bytes,
17471752
opts.size_bits,
17481753
opts.count,

tools/regz/src/embassy.zig

Lines changed: 143 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -306,32 +306,122 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
306306
});
307307

308308
for (obj.object.get("items").?.array.items) |item| {
309+
var register_ids: std.ArrayList(Database.RegisterID) = .empty;
310+
defer register_ids.deinit(allocator);
309311
const register_name = item.object.get("name").?.string;
310312
const description: ?[]const u8 = if (item.object.get("description")) |desc| desc.string else null;
311-
const byte_offset = item.object.get("byte_offset").?.integer;
313+
const byte_offset: u64 = @intCast(item.object.get("byte_offset").?.integer);
312314
const item_bit_size = if (item.object.get("bit_size")) |v| v.integer else 32;
315+
const maybe_count: ?u64, const maybe_stride: ?u64 = if (item.object.get("array")) |array| blk: {
316+
if (array.object.get("len")) |count| {
317+
if (count.integer == 1) break :blk .{ null, null };
318+
if (array.object.get("stride")) |stride| {
319+
if (stride.integer > 4) {
320+
break :blk .{ @intCast(count.integer), @intCast(stride.integer) };
321+
}
322+
}
323+
break :blk .{ @intCast(count.integer), null };
324+
}
313325

314-
const register_id = try db.create_register(group_id, .{
315-
.name = register_name,
316-
.description = description,
317-
.offset_bytes = @intCast(byte_offset),
318-
.size_bits = @intCast(item_bit_size),
319-
.count = if (item.object.get("array")) |array| blk: {
320-
if (array.object.get("len")) |count| {
321-
// ensure stride is always 4 for now, assuming that
322-
// it's in bytes
323-
const stride = array.object.get("stride").?.integer;
324-
if (stride != 4) {
325-
std.log.warn("ignoring register array with unsupported stride: {} != 4 for register {s} in {s} in {s}", .{ stride, register_name, key["block/".len..], name });
326-
break :blk null;
326+
break :blk .{ null, null };
327+
} else .{ null, null };
328+
329+
// This register can be a cluster. In this case we can reference its type only.
330+
// We still need to handle the stride. This is the reason we need to compute size
331+
// of cluster.
332+
if (item.object.get("block")) |block| {
333+
const ref_type = block.string;
334+
const block_key = try std.fmt.allocPrint(allocator, "block/{s}", .{ref_type});
335+
const block_value = (register_file.value.object.get(block_key) orelse continue).object;
336+
var max_bytes: u64 = 0;
337+
for (block_value.get("items").?.array.items) |nested_item| {
338+
// Let's assume we do not recurse on block
339+
const offset: u64 = @intCast(nested_item.object.get("byte_offset").?.integer);
340+
if (nested_item.object.get("array")) |array| {
341+
if (array.object.get("len")) |count| {
342+
if (array.object.get("stride")) |stride| {
343+
max_bytes = @max(offset + 4 + @as(u64, @intCast(stride.integer * (count.integer - 1))), max_bytes);
344+
continue;
345+
}
327346
}
347+
}
348+
max_bytes = @max(offset + 4, max_bytes);
349+
}
328350

329-
break :blk @intCast(count.integer);
351+
if (maybe_stride == max_bytes) {
352+
// We have a contiguous cluster array
353+
_ = try db.create_register(group_id, .{
354+
.name = register_name,
355+
.description = description,
356+
.ref_type = ref_type,
357+
.offset_bytes = @intCast(byte_offset),
358+
.size_bits = max_bytes * 8,
359+
.count = maybe_count,
360+
});
361+
continue;
362+
} else if (maybe_stride) |stride| {
363+
// We have spread cluster
364+
for (0..maybe_count.?) |id| {
365+
const register_part_name = try std.fmt.allocPrint(allocator, "{s}[{d}]", .{
366+
register_name,
367+
id,
368+
});
369+
_ = try db.create_register(group_id, .{
370+
.name = register_part_name,
371+
.description = description,
372+
.ref_type = ref_type,
373+
.offset_bytes = byte_offset + (id * stride),
374+
.size_bits = max_bytes * 8,
375+
.count = null,
376+
});
330377
}
378+
continue;
379+
} else if (maybe_stride == null) {
380+
// We have a single cluster
381+
_ = try db.create_register(group_id, .{
382+
.name = register_name,
383+
.description = description,
384+
.ref_type = ref_type,
385+
.offset_bytes = @intCast(byte_offset),
386+
.size_bits = max_bytes * 8,
387+
.count = null,
388+
});
389+
continue;
390+
}
391+
// No match default to u32
392+
// At this point it should be unreachable.
393+
// I leave this comment as a placeholder for other special cases.
394+
}
331395

332-
break :blk null;
333-
} else null,
334-
});
396+
// Not a cluster but a fieldset
397+
if (maybe_stride) |stride| {
398+
if (maybe_count) |count| {
399+
// We spread the register as it jumps over other registers
400+
for (0..count) |id| {
401+
const register_part_name = try std.fmt.allocPrint(allocator, "{s}[{d}]", .{
402+
register_name,
403+
id,
404+
});
405+
const register_id = try db.create_register(group_id, .{
406+
.name = register_part_name,
407+
.description = description,
408+
.offset_bytes = byte_offset + (id * stride),
409+
.size_bits = @intCast(item_bit_size),
410+
.count = null,
411+
});
412+
try register_ids.append(allocator, register_id);
413+
}
414+
}
415+
} else {
416+
const register_id = try db.create_register(group_id, .{
417+
.name = register_name,
418+
.description = description,
419+
.offset_bytes = @intCast(byte_offset),
420+
.size_bits = @intCast(item_bit_size),
421+
.count = maybe_count,
422+
});
423+
try register_ids.append(allocator, register_id);
424+
}
335425

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

358448
array_count = if (object_map.get("len")) |len| @intCast(len.integer) else null;
359-
array_stride = if (object_map.get("stride")) |stride| @intCast(stride.integer) else null;
449+
array_stride = if (object_map.get("stride")) |field_stride| @intCast(field_stride.integer) else null;
360450

361451
// This category where there is an array of items, but it is given by
362452
// individual offsets as opposed to a count + stride. This is used when strides are
@@ -365,30 +455,32 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
365455
if (object_map.get("offsets")) |positions| {
366456
for (positions.array.items, 0..) |position, idx| {
367457
const field_name_irregular_stride = try std.fmt.allocPrint(allocator, "{s}[{}]", .{ field_name, idx });
368-
369-
try db.add_register_field(register_id, .{
370-
.name = field_name_irregular_stride,
371-
.description = field_description,
372-
.offset_bits = @intCast(position.integer + bit_offset),
373-
.size_bits = @intCast(bit_size),
374-
.enum_id = enum_id,
375-
.count = null,
376-
.stride = null,
377-
});
458+
for (register_ids.items) |register_id| {
459+
try db.add_register_field(register_id, .{
460+
.name = field_name_irregular_stride,
461+
.description = field_description,
462+
.offset_bits = @intCast(position.integer + bit_offset),
463+
.size_bits = @intCast(bit_size),
464+
.enum_id = enum_id,
465+
.count = null,
466+
.stride = null,
467+
});
468+
}
378469
}
379470
continue :next_field;
380471
}
381472
}
382-
383-
try db.add_register_field(register_id, .{
384-
.name = field_name,
385-
.description = field_description,
386-
.offset_bits = @intCast(bit_offset),
387-
.size_bits = @intCast(bit_size),
388-
.enum_id = enum_id,
389-
.count = array_count,
390-
.stride = array_stride,
391-
});
473+
for (register_ids.items) |register_id| {
474+
try db.add_register_field(register_id, .{
475+
.name = field_name,
476+
.description = field_description,
477+
.offset_bits = @intCast(bit_offset),
478+
.size_bits = @intCast(bit_size),
479+
.enum_id = enum_id,
480+
.count = array_count,
481+
.stride = array_stride,
482+
});
483+
}
392484
},
393485
.array => |arr| {
394486
// This case is for discontinuous fields where the first few bits are
@@ -411,18 +503,19 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
411503
var array_stride: ?u8 = null;
412504
if (field.object.get("array")) |array| {
413505
array_count = if (array.object.get("len")) |len| @intCast(len.integer) else null;
414-
array_stride = if (array.object.get("stride")) |stride| @intCast(stride.integer) else null;
506+
array_stride = if (array.object.get("stride")) |field_stride| @intCast(field_stride.integer) else null;
507+
}
508+
for (register_ids.items) |register_id| {
509+
try db.add_register_field(register_id, .{
510+
.name = non_contiguous_field_name,
511+
.description = field_description,
512+
.offset_bits = @intCast(bit_offset),
513+
.size_bits = @intCast(bit_size),
514+
.enum_id = enum_id,
515+
.count = array_count,
516+
.stride = array_stride,
517+
});
415518
}
416-
417-
try db.add_register_field(register_id, .{
418-
.name = non_contiguous_field_name,
419-
.description = field_description,
420-
.offset_bits = @intCast(bit_offset),
421-
.size_bits = @intCast(bit_size),
422-
.enum_id = enum_id,
423-
.count = array_count,
424-
.stride = array_stride,
425-
});
426519
}
427520
},
428521
else => |val| {
@@ -603,4 +696,3 @@ const std = @import("std");
603696
const Database = @import("Database.zig");
604697
const Arch = @import("arch.zig").Arch;
605698
const arm = @import("arch/arm.zig");
606-
const FS_Directory = @import("FS_Directory.zig");

0 commit comments

Comments
 (0)