DMA API, and time API improvements from SYCL 2023 workshop (#63)

wch-ch32v003
Matt Knight 1 year ago committed by GitHub
parent 7b7caa9eb4
commit 316e241a88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,7 +7,8 @@ const DMA = chip.peripherals.DMA;
const hw = @import("hw.zig"); const hw = @import("hw.zig");
var claimed_channels: u12 = 0; const num_channels = 12;
var claimed_channels = std.PackedIntArray(bool, num_channels).initAllTo(false);
pub const Dreq = enum(u6) { pub const Dreq = enum(u6) {
uart0_tx = 20, uart0_tx = 20,
@ -15,31 +16,38 @@ pub const Dreq = enum(u6) {
_, _,
}; };
pub fn num(n: u4) Channel { pub fn channel(n: u4) Channel {
assert(n < 12); assert(n < num_channels);
return @intToEnum(Channel, n); return @intToEnum(Channel, n);
} }
pub fn claim_unused_channel() ?Channel {} pub fn claim_unused_channel() ?Channel {
for (0..num_channels) |i| {
if (claimed_channels.get(i)) {
claimed_channels.set(i, true);
return channel(i);
}
}
return null;
}
pub const Channel = enum(u4) { pub const Channel = enum(u4) {
_, _,
/// panics if the channel is already claimed /// panics if the channel is already claimed
pub fn claim(channel: Channel) void { pub fn claim(chan: Channel) void {
_ = channel; if (chan.is_claimed())
@panic("TODO"); @panic("channel is already claimed!");
} }
pub fn unclaim(channel: Channel) void { pub fn unclaim(chan: Channel) void {
_ = channel; claimed_channels.set(@enumToInt(chan), false);
@panic("TODO");
} }
pub fn is_claimed(channel: Channel) bool { pub fn is_claimed(chan: Channel) bool {
_ = channel; return claimed_channels.get(@enumToInt(chan));
@panic("TODO");
} }
const Regs = extern struct { const Regs = extern struct {
@ -67,9 +75,9 @@ pub const Channel = enum(u4) {
al3_trans_count: u32, al3_trans_count: u32,
}; };
fn get_regs(channel: Channel) *volatile Regs { fn get_regs(chan: Channel) *volatile Regs {
const regs = @ptrCast(*volatile [12]Regs, &DMA.CH0_READ_ADDR); const regs = @ptrCast(*volatile [12]Regs, &DMA.CH0_READ_ADDR);
return &regs[@enumToInt(channel)]; return &regs[@enumToInt(chan)];
} }
pub const TransferConfig = struct { pub const TransferConfig = struct {
@ -86,13 +94,13 @@ pub const Channel = enum(u4) {
}; };
pub fn trigger_transfer( pub fn trigger_transfer(
channel: Channel, chan: Channel,
write_addr: u32, write_addr: u32,
read_addr: u32, read_addr: u32,
count: u32, count: u32,
config: TransferConfig, config: TransferConfig,
) void { ) void {
const regs = channel.get_regs(); const regs = chan.get_regs();
regs.read_addr = read_addr; regs.read_addr = read_addr;
regs.write_addr = write_addr; regs.write_addr = write_addr;
regs.trans_count = count; regs.trans_count = count;
@ -109,23 +117,23 @@ pub const Channel = enum(u4) {
}); });
} }
pub fn set_irq0_enabled(channel: Channel, enabled: bool) void { pub fn set_irq0_enabled(chan: Channel, enabled: bool) void {
if (enabled) { if (enabled) {
const inte0_set = hw.set_alias_raw(&DMA.INTE0); const inte0_set = hw.set_alias_raw(&DMA.INTE0);
inte0_set.* = @as(u32, 1) << @enumToInt(channel); inte0_set.* = @as(u32, 1) << @enumToInt(chan);
} else { } else {
const inte0_clear = hw.clear_alias_raw(&DMA.INTE0); const inte0_clear = hw.clear_alias_raw(&DMA.INTE0);
inte0_clear.* = @as(u32, 1) << @enumToInt(channel); inte0_clear.* = @as(u32, 1) << @enumToInt(chan);
} }
} }
pub fn acknowledge_irq0(channel: Channel) void { pub fn acknowledge_irq0(chan: Channel) void {
const ints0_set = hw.set_alias_raw(&DMA.INTS0); const ints0_set = hw.set_alias_raw(&DMA.INTS0);
ints0_set.* = @as(u32, 1) << @enumToInt(channel); ints0_set.* = @as(u32, 1) << @enumToInt(chan);
} }
pub fn is_busy(channel: Channel) bool { pub fn is_busy(chan: Channel) bool {
const regs = channel.get_regs(); const regs = chan.get_regs();
return regs.ctrl_trig.read().BUSY == 1; return regs.ctrl_trig.read().BUSY == 1;
} }
}; };

@ -6,14 +6,58 @@ const TIMER = microzig.chip.peripherals.TIMER;
pub const Absolute = enum(u64) { pub const Absolute = enum(u64) {
_, _,
pub fn reached(time: Absolute) bool { pub fn from_us(us: u64) Absolute {
const now = get_time_since_boot(); return @intToEnum(Absolute, us);
return now.to_us() >= time.to_us();
} }
pub fn to_us(time: Absolute) u64 { pub fn to_us(time: Absolute) u64 {
return @enumToInt(time); return @enumToInt(time);
} }
pub fn is_reached_by(deadline: Absolute, point: Absolute) bool {
return deadline.to_us() <= point.to_us();
}
pub fn is_reached(time: Absolute) bool {
const now = get_time_since_boot();
return time.is_reached_by(now);
}
pub fn diff(future: Absolute, past: Absolute) Duration {
return Duration.from_us(future.to_us() - past.to_us());
}
pub fn add_duration(time: Absolute, dur: Duration) Absolute {
return Absolute.from_us(time.to_us() + dur.to_us());
}
};
pub const Duration = enum(u64) {
_,
pub fn from_us(us: u64) Duration {
return @intToEnum(Duration, us);
}
pub fn from_ms(ms: u64) Duration {
return from_us(1000 * ms);
}
pub fn to_us(duration: Duration) u64 {
return @enumToInt(duration);
}
pub fn less_than(self: Duration, other: Duration) bool {
return self.to_us() < other.to_us();
}
pub fn minus(self: Duration, other: Duration) Duration {
return from_us(self.to_us() - other.to_us());
}
pub fn plus(self: Duration, other: Duration) Duration {
return from_us(self.to_us() + other.to_us());
}
}; };
pub fn get_time_since_boot() Absolute { pub fn get_time_since_boot() Absolute {
@ -39,5 +83,5 @@ pub fn sleep_ms(time_ms: u32) void {
pub fn sleep_us(time_us: u64) void { pub fn sleep_us(time_us: u64) void {
const end_time = make_timeout_us(time_us); const end_time = make_timeout_us(time_us);
while (!end_time.reached()) {} while (!end_time.is_reached()) {}
} }

Loading…
Cancel
Save