Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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: 5 additions & 2 deletions core/src/cpus/cortex_m.zig
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,9 @@ pub const startup_logic = struct {

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

peripherals.scb.VTOR = @intFromPtr(&ram_vectors);
const vtor_addr: u32 = @intFromPtr(&ram_vectors);
std.debug.assert(std.mem.isAligned(vtor_addr, 256));
peripherals.scb.VTOR = vtor_addr;
}
}

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

// will be imported by microzig.zig to allow system startup.
pub const _vector_table: VectorTable = blk: {
// must be aligned to 256 as VTOR ignores the lower 8 bits of the address.
pub const _vector_table: VectorTable align(256) = blk: {
var tmp: VectorTable = .{
.initial_stack_pointer = microzig.config.end_of_stack,
.Reset = .{ .c = microzig.cpu.startup_logic._start },
Expand Down
2 changes: 1 addition & 1 deletion port/raspberrypi/rp2xxx/src/hal/dma.zig
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub const Channel = enum(u4) {
al3_read_addr_trig: u32,
};

fn get_regs(chan: Channel) *volatile Regs {
pub inline fn get_regs(chan: Channel) *volatile Regs {
const regs = @as(*volatile [num_channels]Regs, @ptrCast(&DMA.CH0_READ_ADDR));
return &regs[@intFromEnum(chan)];
}
Expand Down
8 changes: 4 additions & 4 deletions port/raspberrypi/rp2xxx/src/hal/gpio.zig
Original file line number Diff line number Diff line change
Expand Up @@ -318,22 +318,22 @@ pub const Pin = enum(u6) {
.RP2350 => *volatile [48]PadsReg,
};

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

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

/// Only relevant for RP2350 which has 48 GPIOs
fn is_upper(gpio: Pin) bool {
pub inline fn is_upper(gpio: Pin) bool {
return @intFromEnum(gpio) > 31;
}

pub fn mask(gpio: Pin) u32 {
pub inline fn mask(gpio: Pin) u32 {
const bitshift_val: u5 = switch (chip) {
.RP2040 => @intCast(@intFromEnum(gpio)),
.RP2350 =>
Expand Down
29 changes: 21 additions & 8 deletions port/raspberrypi/rp2xxx/src/hal/i2c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub const instance = struct {
pub const I2C = enum(u1) {
_,

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

const peripheral_block_freq = (comptime config.clock_config.get_frequency(.clk_sys)) orelse @compileError("clk_sys must be set for I²C");

const timings = comptime translate_baudrate(config.baud_rate, peripheral_block_freq) catch @compileError("baud_rate is not possible with the provided clock_config");

// set_baudrate() enables I2C block before returning
try i2c.set_baudrate(config.baud_rate, peripheral_block_freq);
i2c.set_computed_baudrate(timings);
}

/// Disables I2C, returns peripheral registers to reset state.
Expand All @@ -289,13 +292,23 @@ pub const I2C = enum(u1) {
/// pin rise/fall time as that is board specific, so actual baud rates may be
/// slightly lower than specified.
pub fn set_baudrate(i2c: I2C, baud_rate: u32, freq_in: u32) ConfigError!void {
const reg_vals = try translate_baudrate(baud_rate, freq_in);
const timings = try translate_baudrate(baud_rate, freq_in);
i2c.set_computed_baudrate(timings);
}

/// Configures I2C to run at a specified baud rate given a peripheral clock frequency.
///
/// Validates configuration to ensure it's both within I2C spec, and the peripheral
/// block's configuration capabilities. Note that this does NOT take into account
/// pin rise/fall time as that is board specific, so actual baud rates may be
/// slightly lower than specified.
pub fn set_computed_baudrate(i2c: I2C, timings: TimingRegisterValues) void {
i2c.disable();
const regs = i2c.get_regs();
regs.IC_FS_SCL_HCNT.write(.{ .IC_FS_SCL_HCNT = reg_vals.scl_hcnt });
regs.IC_FS_SCL_LCNT.write(.{ .IC_FS_SCL_LCNT = reg_vals.scl_lcnt });
regs.IC_FS_SPKLEN.write(.{ .IC_FS_SPKLEN = reg_vals.spklen });
regs.IC_SDA_HOLD.modify(.{ .IC_SDA_TX_HOLD = reg_vals.sda_tx_hold_count });
regs.IC_FS_SCL_HCNT.write(.{ .IC_FS_SCL_HCNT = timings.scl_hcnt });
regs.IC_FS_SCL_LCNT.write(.{ .IC_FS_SCL_LCNT = timings.scl_lcnt });
regs.IC_FS_SPKLEN.write(.{ .IC_FS_SPKLEN = timings.spklen });
regs.IC_SDA_HOLD.modify(.{ .IC_SDA_TX_HOLD = timings.sda_tx_hold_count });
i2c.enable();
}

Expand Down
10 changes: 8 additions & 2 deletions port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ pub const Diagnostics = struct {
}
};

/// Creates a copy of a slice at comptime that is guaranteed to be immutable.
fn comptime_copy(comptime T: type, comptime slice: []const T) []const T {
const arr: [slice.len]T = slice[0..slice.len].*;
return &arr;
}

pub fn assemble_impl(comptime chip: Chip, comptime source: []const u8, diags: *?Diagnostics, options: AssembleOptions) !Output {
const tokens = try tokenizer.tokenize(chip, source, diags, options.tokenize);
const encoder_output = try encoder.encode(chip, tokens.slice(), diags, options.encode);
Expand All @@ -87,9 +93,9 @@ pub fn assemble_impl(comptime chip: Chip, comptime source: []const u8, diags: *?
.name = define.name,
.value = define.value,
}) catch unreachable;
break :blk tmp.constSlice();
break :blk comptime_copy(Define, tmp.slice());
},
.programs = programs.constSlice(),
.programs = comptime_copy(Program, programs.slice()),
};
}

Expand Down
7 changes: 6 additions & 1 deletion port/raspberrypi/rp2xxx/src/hal/pio/common.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,12 @@ pub fn PioImpl(EnumType: type, chip: Chip) type {
if (origin != offset)
return false;

// Will never fit in the first place:
if (offset + program.instructions.len > 32)
return false;

const used_mask = UsedInstructionSpace(chip).val[@intFromEnum(self)];
const program_mask = program.get_mask();
const program_mask = (program.get_mask() << offset);

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

// TODO: check program settings vs pin mapping
const offset = try self.add_program(program);

self.sm_init(sm, offset, .{
.clkdiv = options.clkdiv,
.shift = options.shift,
Expand Down
2 changes: 1 addition & 1 deletion port/raspberrypi/rp2xxx/src/hal/uart.zig
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ pub const UART = enum(u1) {
return .{ .context = uart };
}

fn get_regs(uart: UART) *volatile UartRegs {
pub inline fn get_regs(uart: UART) *volatile UartRegs {
return switch (@intFromEnum(uart)) {
0 => UART0_reg,
1 => UART1_reg,
Expand Down
Loading