Skip to content

Commit 0ed66b3

Browse files
ikskuhFelix "xq" Queißner
andauthored
Several fixes and cleanups for RP2xxx (#630)
* Fixes default vector table not being aligned to 256 in RAM images. * Fixes Pio.can_add_program_at_offset not finding a position for any program except the first. * Fixes immutable slice bug in Pio.Assembler * Makes I2C.apply unfailable * Makes fn get_regs() for some peripherials public, optimizes codegen for GPIOs by making some functions inline * Fixes build error in i2c_bus_scan.zig * Fixes src/mlx90640.zig * Fixes pcf8574.zig * Fixes src/hd44780.zig --------- Co-authored-by: Felix "xq" Queißner <[email protected]>
1 parent 79d5400 commit 0ed66b3

File tree

11 files changed

+50
-23
lines changed

11 files changed

+50
-23
lines changed

core/src/cpus/cortex_m.zig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,9 @@ pub const startup_logic = struct {
652652

653653
@memcpy(ram_vectors[0..vector_count], flash_vector[0..vector_count]);
654654

655-
peripherals.scb.VTOR = @intFromPtr(&ram_vectors);
655+
const vtor_addr: u32 = @intFromPtr(&ram_vectors);
656+
std.debug.assert(std.mem.isAligned(vtor_addr, 256));
657+
peripherals.scb.VTOR = vtor_addr;
656658
}
657659
}
658660

@@ -662,7 +664,8 @@ pub const startup_logic = struct {
662664
const VectorTable = microzig.chip.VectorTable;
663665

664666
// will be imported by microzig.zig to allow system startup.
665-
pub const _vector_table: VectorTable = blk: {
667+
// must be aligned to 256 as VTOR ignores the lower 8 bits of the address.
668+
pub const _vector_table: VectorTable align(256) = blk: {
666669
var tmp: VectorTable = .{
667670
.initial_stack_pointer = microzig.config.end_of_stack,
668671
.Reset = .{ .c = microzig.cpu.startup_logic._start },

examples/raspberrypi/rp2xxx/src/i2c_bus_scan.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub fn main() !void {
3535
pin.set_function(.i2c);
3636
}
3737

38-
try i2c0.apply(.{
38+
i2c0.apply(.{
3939
.clock_config = rp2xxx.clock_config,
4040
});
4141

examples/raspberrypi/rp2xxx/src/mlx90640.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn init() !void {
7676
.clock_config = rpxxxx.clock_config,
7777
});
7878

79-
try i2c0.apply(i2c.Config{ .clock_config = rpxxxx.clock_config });
79+
i2c0.apply(i2c.Config{ .clock_config = rpxxxx.clock_config });
8080

8181
rpxxxx.uart.init_logger(uart);
8282
pin_config.apply();

examples/raspberrypi/rp2xxx/src/rp2040_only/hd44780.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub fn main() !void {
3131
pin.set_function(.i2c);
3232
}
3333

34-
try i2c0.apply(.{
34+
i2c0.apply(.{
3535
.clock_config = rp2040.clock_config,
3636
});
3737
var expander = PCF8574(.{ .Datagram_Device = I2C_Device }).init(i2c_device);

examples/raspberrypi/rp2xxx/src/rp2040_only/pcf8574.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn main() !void {
2323
pin.set_function(.i2c);
2424
}
2525

26-
try i2c0.apply(.{
26+
i2c0.apply(.{
2727
.clock_config = rp2040.clock_config,
2828
});
2929
var expander = PCF8574(.{ .Datagram_Device = I2C_Device }).init(i2c_device);

port/raspberrypi/rp2xxx/src/hal/dma.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub const Channel = enum(u4) {
100100
al3_read_addr_trig: u32,
101101
};
102102

103-
fn get_regs(chan: Channel) *volatile Regs {
103+
pub inline fn get_regs(chan: Channel) *volatile Regs {
104104
const regs = @as(*volatile [num_channels]Regs, @ptrCast(&DMA.CH0_READ_ADDR));
105105
return &regs[@intFromEnum(chan)];
106106
}

port/raspberrypi/rp2xxx/src/hal/gpio.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,22 +318,22 @@ pub const Pin = enum(u6) {
318318
.RP2350 => *volatile [48]PadsReg,
319319
};
320320

321-
fn get_regs(gpio: Pin) *volatile Regs {
321+
pub inline fn get_regs(gpio: Pin) *volatile Regs {
322322
const regs = @as(RegsArray, @ptrCast(&IO_BANK0.GPIO0_STATUS));
323323
return &regs[@intFromEnum(gpio)];
324324
}
325325

326-
fn get_pads_reg(gpio: Pin) *volatile PadsReg {
326+
pub inline fn get_pads_reg(gpio: Pin) *volatile PadsReg {
327327
const regs = @as(PadsRegArray, @ptrCast(&PADS_BANK0.GPIO0));
328328
return &regs[@intFromEnum(gpio)];
329329
}
330330

331331
/// Only relevant for RP2350 which has 48 GPIOs
332-
fn is_upper(gpio: Pin) bool {
332+
pub inline fn is_upper(gpio: Pin) bool {
333333
return @intFromEnum(gpio) > 31;
334334
}
335335

336-
pub fn mask(gpio: Pin) u32 {
336+
pub inline fn mask(gpio: Pin) u32 {
337337
const bitshift_val: u5 = switch (chip) {
338338
.RP2040 => @intCast(@intFromEnum(gpio)),
339339
.RP2350 =>

port/raspberrypi/rp2xxx/src/hal/i2c.zig

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ pub const instance = struct {
216216
pub const I2C = enum(u1) {
217217
_,
218218

219-
fn get_regs(i2c: I2C) *volatile I2cRegs {
219+
pub inline fn get_regs(i2c: I2C) *volatile I2cRegs {
220220
return switch (@intFromEnum(i2c)) {
221221
0 => I2C0,
222222
1 => I2C1,
@@ -246,7 +246,7 @@ pub const I2C = enum(u1) {
246246
/// - TX_EMPTY_CTRL is always enabled for easy detection of TX finished
247247
/// - TX and RX FIFO detection thresholds set to 1, this makes polling for TX finished/RX ready much simpler
248248
/// - DREQ signalling is always enabled, harmless if DMA isn't configured to listen for this
249-
pub fn apply(i2c: I2C, comptime config: Config) ConfigError!void {
249+
pub fn apply(i2c: I2C, comptime config: Config) void {
250250
i2c.disable();
251251
const regs = i2c.get_regs();
252252
regs.IC_CON.write(.{
@@ -273,8 +273,11 @@ pub const I2C = enum(u1) {
273273
});
274274

275275
const peripheral_block_freq = (comptime config.clock_config.get_frequency(.clk_sys)) orelse @compileError("clk_sys must be set for I²C");
276+
277+
const timings = comptime translate_baudrate(config.baud_rate, peripheral_block_freq) catch @compileError("baud_rate is not possible with the provided clock_config");
278+
276279
// set_baudrate() enables I2C block before returning
277-
try i2c.set_baudrate(config.baud_rate, peripheral_block_freq);
280+
i2c.set_computed_baudrate(timings);
278281
}
279282

280283
/// Disables I2C, returns peripheral registers to reset state.
@@ -289,13 +292,23 @@ pub const I2C = enum(u1) {
289292
/// pin rise/fall time as that is board specific, so actual baud rates may be
290293
/// slightly lower than specified.
291294
pub fn set_baudrate(i2c: I2C, baud_rate: u32, freq_in: u32) ConfigError!void {
292-
const reg_vals = try translate_baudrate(baud_rate, freq_in);
295+
const timings = try translate_baudrate(baud_rate, freq_in);
296+
i2c.set_computed_baudrate(timings);
297+
}
298+
299+
/// Configures I2C to run at a specified baud rate given a peripheral clock frequency.
300+
///
301+
/// Validates configuration to ensure it's both within I2C spec, and the peripheral
302+
/// block's configuration capabilities. Note that this does NOT take into account
303+
/// pin rise/fall time as that is board specific, so actual baud rates may be
304+
/// slightly lower than specified.
305+
pub fn set_computed_baudrate(i2c: I2C, timings: TimingRegisterValues) void {
293306
i2c.disable();
294307
const regs = i2c.get_regs();
295-
regs.IC_FS_SCL_HCNT.write(.{ .IC_FS_SCL_HCNT = reg_vals.scl_hcnt });
296-
regs.IC_FS_SCL_LCNT.write(.{ .IC_FS_SCL_LCNT = reg_vals.scl_lcnt });
297-
regs.IC_FS_SPKLEN.write(.{ .IC_FS_SPKLEN = reg_vals.spklen });
298-
regs.IC_SDA_HOLD.modify(.{ .IC_SDA_TX_HOLD = reg_vals.sda_tx_hold_count });
308+
regs.IC_FS_SCL_HCNT.write(.{ .IC_FS_SCL_HCNT = timings.scl_hcnt });
309+
regs.IC_FS_SCL_LCNT.write(.{ .IC_FS_SCL_LCNT = timings.scl_lcnt });
310+
regs.IC_FS_SPKLEN.write(.{ .IC_FS_SPKLEN = timings.spklen });
311+
regs.IC_SDA_HOLD.modify(.{ .IC_SDA_TX_HOLD = timings.sda_tx_hold_count });
299312
i2c.enable();
300313
}
301314

port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ pub const Diagnostics = struct {
7272
}
7373
};
7474

75+
/// Creates a copy of a slice at comptime that is guaranteed to be immutable.
76+
fn comptime_copy(comptime T: type, comptime slice: []const T) []const T {
77+
const arr: [slice.len]T = slice[0..slice.len].*;
78+
return &arr;
79+
}
80+
7581
pub fn assemble_impl(comptime chip: Chip, comptime source: []const u8, diags: *?Diagnostics, options: AssembleOptions) !Output {
7682
const tokens = try tokenizer.tokenize(chip, source, diags, options.tokenize);
7783
const encoder_output = try encoder.encode(chip, tokens.slice(), diags, options.encode);
@@ -87,9 +93,9 @@ pub fn assemble_impl(comptime chip: Chip, comptime source: []const u8, diags: *?
8793
.name = define.name,
8894
.value = define.value,
8995
}) catch unreachable;
90-
break :blk tmp.constSlice();
96+
break :blk comptime_copy(Define, tmp.slice());
9197
},
92-
.programs = programs.constSlice(),
98+
.programs = comptime_copy(Program, programs.slice()),
9399
};
94100
}
95101

port/raspberrypi/rp2xxx/src/hal/pio/common.zig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,12 @@ pub fn PioImpl(EnumType: type, chip: Chip) type {
133133
if (origin != offset)
134134
return false;
135135

136+
// Will never fit in the first place:
137+
if (offset + program.instructions.len > 32)
138+
return false;
139+
136140
const used_mask = UsedInstructionSpace(chip).val[@intFromEnum(self)];
137-
const program_mask = program.get_mask();
141+
const program_mask = (program.get_mask() << offset);
138142

139143
// We can add the program if the masks don't overlap, if there is
140144
// overlap the result of a bitwise AND will have a non-zero result
@@ -537,6 +541,7 @@ pub fn PioImpl(EnumType: type, chip: Chip) type {
537541

538542
// TODO: check program settings vs pin mapping
539543
const offset = try self.add_program(program);
544+
540545
self.sm_init(sm, offset, .{
541546
.clkdiv = options.clkdiv,
542547
.shift = options.shift,

0 commit comments

Comments
 (0)