Skip to content
Draft
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
4 changes: 4 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
.url = "git+https://codeberg.org/mattnite/boxzer.git#4021540de4b07c11102dd4d46383ce0066f838bb",
.hash = "boxzer-0.1.0--ed-MPrnAAAQAwXnfMJuSkgAsw4FseHEHKcn7OMKXGZS",
},
.serial = .{
.url = "git+https://github.com/ZigEmbeddedGroup/serial.git?ref=master#fbd7389ff8bbc9fa362aa74081588755b5d028a0",
.hash = "serial-0.0.1-PoeRzF60AAAN8Iu0yXTIX-t3DVzsnmN7vWHKM2HA2Zbq",
},
},
.paths = .{
"README.md",
Expand Down
4 changes: 2 additions & 2 deletions core/src/cpus/cortex_m.zig
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ pub inline fn enable_fpu() void {

/// The RAM vector table used. You can swap interrupt handlers at runtime here.
/// Available when using a RAM vector table or a RAM image.
pub var ram_vector_table: VectorTable align(256) = if (using_ram_vector_table or is_ram_image)
pub var ram_vector_table: VectorTable align(128) = if (using_ram_vector_table or is_ram_image)
startup_logic.generate_vector_table()
else
@compileError("`ram_vector_table` is not available. Consider adding .cpu = .{ .ram_vector_table = true }" ++
Expand Down Expand Up @@ -834,7 +834,7 @@ pub const startup_logic = struct {
fn default_exception_handler(comptime name: []const u8) microzig.interrupt.Handler {
return switch (builtin.mode) {
.Debug => .{ .c = DebugExceptionHandler(name).handle },
else => .{ .c = ReleaseExceptionHandler.handle },
else => .{ .c = DebugExceptionHandler(name).handle },
};
}

Expand Down
140 changes: 115 additions & 25 deletions port/raspberrypi/rp2xxx/src/hal/dma.zig
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,69 @@ pub const DMA_WriteTarget = struct {
addr: u32,
};

pub const RingConfig = union(enum) {
disabled,
read: RingSize,
write: RingSize,
};

pub const TransferMode = enum(u4) {
/// When MODE is 0x0, the transfer count decrements with each transfer,
/// until 0, and then the channel triggers the next channel indicated by
/// CTRL_CHAIN_TO.
default = 0x0,

/// When MODE is 0x1, the transfer count decrements with each transfer until 0,
/// and then the channel re-triggers itself, in addition to the trigger indicated by
/// CTRL_CHAIN_TO. This is useful for e.g. an endless ring-buffer DMA with
/// periodic interrupts.
trigger_self = 0x1,

/// When MODE is 0xf, the transfer count does not decrement. The DMA channel
/// performs an endless sequence of transfers, never triggering other channels or
/// raising interrupts, until an ABORT is raised.
endless = 0xF,
};

pub const RingSize = enum(u4) {
// disabled = 0,
@"2" = 1,
@"4" = 2,
@"8" = 3,
@"16" = 4,
@"32" = 5,
@"64" = 6,
@"128" = 7,
@"256" = 8,
@"512" = 9,
@"1024" = 10,
@"2048" = 11,
@"4096" = 12,
@"8192" = 13,
@"16384" = 14,
@"32768" = 15,
};

pub const IncrementMode = enum {
none,
increment,
decrement,
increment_x2,

inline fn get_read_value(mode: IncrementMode) u1 {
return switch (mode) {
.none, .increment_x2 => 0,
.increment, .decrement => 1,
};
}
inline fn get_read_rev_value(mode: IncrementMode) u1 {
return switch (mode) {
.none, .increment => 0,
.decrement, .increment_x2 => 1,
};
}
};

pub const ChannelError = error{AlreadyClaimed};

pub const Channel = enum(u4) {
Expand Down Expand Up @@ -109,18 +172,22 @@ pub const Channel = enum(u4) {
trigger: bool = true,
data_size: DataSize,
enable: bool,
read_increment: bool,
write_increment: bool,
read_increment: IncrementMode,
write_increment: IncrementMode,
dreq: Dreq,

chain_to: ?Channel = null,

high_priority: bool = false,

// TODO:
// chain to
// ring
// byte swapping
ring: RingConfig = .disabled,
swap_bytes: bool = false,

sniffer_enabled: bool = false,

irq_quiet: bool = false,

mode: TransferMode = .default,
};

pub fn setup_transfer_raw(
Expand All @@ -130,31 +197,54 @@ pub const Channel = enum(u4) {
count: u32,
config: TransferConfig,
) void {
std.debug.assert(config.chain_to != chan); // A channel can never link to itself, use "ENDLESS" count instead.
std.debug.assert(count <= std.math.maxInt(u28)); // Must fit into 28 bits

const CountField = packed struct(u32) {
count: u28,
mode: TransferMode,
};
const count_field: CountField = .{
.count = @intCast(count),
.mode = config.mode,
};
const count_val: u32 = @bitCast(count_field);

const regs = chan.get_regs();
regs.read_addr = read_addr;
regs.write_addr = write_addr;
regs.trans_count = count;
regs.trans_count = count_val;
const chain_to = config.chain_to orelse chan;

const TrigType = @TypeOf(microzig.chip.peripherals.DMA.CH0_CTRL_TRIG).underlying_type;

const new_cfg: TrigType = .{
.EN = @intFromBool(config.enable),
.DATA_SIZE = config.data_size,
.INCR_READ = config.read_increment.get_read_value(),
.INCR_READ_REV = config.read_increment.get_read_rev_value(),
.INCR_WRITE = config.write_increment.get_read_value(),
.INCR_WRITE_REV = config.write_increment.get_read_rev_value(),
.TREQ_SEL = config.dreq,
.CHAIN_TO = @intFromEnum(chain_to),
.HIGH_PRIORITY = @intFromBool(config.high_priority),
.RING_SEL = switch (config.ring) {
.disabled, .read => 0,
.write => 1,
},
.RING_SIZE = switch (config.ring) {
.disabled => .RING_NONE,
.read, .write => |size| @enumFromInt(@intFromEnum(size)),
},
.BSWAP = @intFromBool(config.swap_bytes),
.SNIFF_EN = @intFromBool(config.sniffer_enabled),
.IRQ_QUIET = @intFromBool(config.irq_quiet),
};

if (config.trigger) {
regs.ctrl_trig.modify(.{
.EN = @intFromBool(config.enable),
.DATA_SIZE = config.data_size,
.INCR_READ = @intFromBool(config.read_increment),
.INCR_WRITE = @intFromBool(config.write_increment),
.TREQ_SEL = config.dreq,
.CHAIN_TO = @intFromEnum(chain_to),
.HIGH_PRIORITY = @intFromBool(config.high_priority),
});
regs.ctrl_trig.write(new_cfg);
} else {
regs.al1_ctrl.modify(.{
.EN = @intFromBool(config.enable),
.DATA_SIZE = config.data_size,
.INCR_READ = @intFromBool(config.read_increment),
.INCR_WRITE = @intFromBool(config.write_increment),
.TREQ_SEL = config.dreq,
.CHAIN_TO = @intFromEnum(chain_to),
.HIGH_PRIORITY = @intFromBool(config.high_priority),
});
regs.al1_ctrl.write(new_cfg);
}
}

Expand Down
2 changes: 2 additions & 0 deletions port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub const Program = struct {
wrap: ?u5,

pub fn get_mask(program: Program) u32 {
if (program.instructions.len == 32)
return 0xFFFF_FFFF;
return (@as(u32, 1) << @as(u5, @intCast(program.instructions.len))) - 1;
}
};
Expand Down
21 changes: 16 additions & 5 deletions port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig
Original file line number Diff line number Diff line change
Expand Up @@ -501,12 +501,23 @@ pub fn Encoder(comptime chip: Chip, comptime options: Options) type {
var instr_index: ?u5 = program.origin orelse 0;
for (self.tokens[self.index..]) |token| {
switch (token.data) {
.label => |label| try program.labels.append(.{
.name = label.name,
.public = label.public,
.index = instr_index.?,
}),
.label => |label| {
if (instr_index == null) {
diags.* = Diagnostics.init(token.index, "label not addressable (out of instructions)", .{});
return error.Overflow;
}
try program.labels.append(.{
.name = label.name,
.public = label.public,
.index = instr_index.?,
});
},
.instruction, .word => {
if (instr_index == null) {
diags.* = Diagnostics.init(token.index, "out of instructions", .{});
return error.Overflow;
}

const result, const ov = @addWithOverflow(instr_index.?, 1);
instr_index = if (ov != 0) null else result;
},
Expand Down
27 changes: 21 additions & 6 deletions port/raspberrypi/rp2xxx/src/hal/pio/common.zig
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,22 @@ pub fn PioImpl(EnumType: type, chip: Chip) type {
}

pub fn find_offset_for_program(self: EnumType, program: Program) !u5 {
return if (program.origin) |origin|
if (self.can_add_program_at_offset(program, origin))
origin
else
error.NoSpace
else for (0..(32 - program.instructions.len)) |i| {
std.log.info("<find_offset_for_program origin=\"{?}\" instr=\"{}\">", .{ program.origin, program.instructions.len });
defer std.log.info("</find_offset_for_program>", .{});

if (program.origin) |origin| {
if (!self.can_add_program_at_offset(program, origin))
return error.NoSpace;
return origin;
}

if (program.instructions.len == 32) {
if (!self.can_add_program_at_offset(program, 0))
return error.NoSpace;
return 0;
}

return for (0..(32 - program.instructions.len)) |i| {
const offset = @as(u5, @intCast(i));
if (self.can_add_program_at_offset(program, offset))
break offset;
Expand Down Expand Up @@ -194,6 +204,7 @@ pub fn PioImpl(EnumType: type, chip: Chip) type {
//defer lock.unlock();

const offset = try self.find_offset_for_program(program);
std.log.info("add_program offset = {}", .{offset});
try self.add_program_at_offset_unlocked(program, offset);
return offset;
}
Expand Down Expand Up @@ -526,9 +537,13 @@ pub fn PioImpl(EnumType: type, chip: Chip) type {
const config_count = if (options.pin_mappings.side_set) |side_set| side_set.count() else 0;
assert(expected_side_set_pins == config_count);

std.log.info("<add_program>", .{});

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

std.log.info("</add_program>", .{});

try self.sm_init(sm, offset, .{
.clkdiv = options.clkdiv,
.shift = options.shift,
Expand Down
Loading