runtime: implement acpki RTIO output

This commit is contained in:
Sebastien Bourdeauducq 2020-08-04 17:32:43 +08:00
parent 537f4968eb
commit b915176b29
3 changed files with 90 additions and 4 deletions

1
src/Cargo.lock generated
View File

@ -428,6 +428,7 @@ dependencies = [
"num-derive", "num-derive",
"num-traits", "num-traits",
"unwind", "unwind",
"vcell",
"void", "void",
] ]

View File

@ -24,6 +24,7 @@ async-recursion = "0.3"
fatfs = { version = "0.3", features = ["core_io"], default-features = false } fatfs = { version = "0.3", features = ["core_io"], default-features = false }
log_buffer = { version = "1.2" } log_buffer = { version = "1.2" }
libm = { version = "0.2", features = ["unstable"] } libm = { version = "0.2", features = ["unstable"] }
vcell = "0.1"
libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" } libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
libsupport_zynq = { default-features = false, features = ["alloc_core"], git = "https://git.m-labs.hk/M-Labs/zc706.git" } libsupport_zynq = { default-features = false, features = ["alloc_core"], git = "https://git.m-labs.hk/M-Labs/zc706.git" }

View File

@ -1,9 +1,18 @@
use cslice::CSlice; use cslice::CSlice;
use vcell::VolatileCell;
use libcortex_a9::asm;
use crate::artiq_raise; use crate::artiq_raise;
use crate::pl::csr; use crate::pl::csr;
pub const RTIO_O_STATUS_WAIT: i32 = 1;
pub const RTIO_O_STATUS_UNDERFLOW: i32 = 2;
pub const RTIO_O_STATUS_DESTINATION_UNREACHABLE: i32 = 4;
pub const RTIO_I_STATUS_WAIT_EVENT: i32 = 1;
pub const RTIO_I_STATUS_OVERFLOW: i32 = 2;
pub const RTIO_I_STATUS_WAIT_STATUS: i32 = 4;
pub const RTIO_I_STATUS_DESTINATION_UNREACHABLE: i32 = 8;
#[repr(C)] #[repr(C)]
pub struct TimestampedData { pub struct TimestampedData {
@ -11,9 +20,40 @@ pub struct TimestampedData {
data: i32, data: i32,
} }
#[repr(C, align(32))]
struct Transaction {
request_cmd: i8,
padding0: i8,
padding1: i8,
padding2: i8,
request_target: i32,
request_timestamp: i64,
request_data: i64,
padding: i64,
reply_status: VolatileCell<i32>,
reply_data: VolatileCell<i32>,
reply_timestamp: VolatileCell<u64>
}
static mut TRANSACTION_BUFFER: Transaction = Transaction {
request_cmd: 0,
padding0: 0,
padding1: 0,
padding2: 0,
request_target: 0,
request_timestamp: 0,
request_data: 0,
padding: 0,
reply_status: VolatileCell::new(0),
reply_data: VolatileCell::new(0),
reply_timestamp: VolatileCell::new(0)
};
pub extern fn init() { pub extern fn init() {
unsafe { unsafe {
csr::rtio_core::reset_write(1); csr::rtio_core::reset_write(1);
csr::rtio::engine_addr_base_write(&TRANSACTION_BUFFER as *const Transaction as u32);
csr::rtio::enable_write(1);
} }
} }
@ -30,22 +70,65 @@ pub extern fn get_counter() -> i64 {
} }
pub extern fn now_mu() -> i64 { pub extern fn now_mu() -> i64 {
unimplemented!(); unsafe { TRANSACTION_BUFFER.request_timestamp }
} }
pub extern fn at_mu(t: i64) { pub extern fn at_mu(t: i64) {
unimplemented!(); unsafe { TRANSACTION_BUFFER.request_timestamp = t }
} }
pub extern fn delay_mu(dt: i64) { pub extern fn delay_mu(dt: i64) {
unimplemented!(); unsafe { TRANSACTION_BUFFER.request_timestamp += dt }
}
#[inline(never)]
unsafe fn process_exceptional_status(channel: i32, status: i32) {
let timestamp = now_mu();
if status & RTIO_O_STATUS_WAIT != 0 {
// FIXME: this is a kludge and probably buggy (kernel interrupted?)
while csr::rtio::o_status_read() as i32 & RTIO_O_STATUS_WAIT != 0 {}
}
if status & RTIO_O_STATUS_UNDERFLOW != 0 {
artiq_raise!("RTIOUnderflow",
"RTIO underflow at {0} mu, channel {1}, slack {2} mu",
timestamp, channel as i64, timestamp - get_counter());
}
if status & RTIO_O_STATUS_DESTINATION_UNREACHABLE != 0 {
artiq_raise!("RTIODestinationUnreachable",
"RTIO destination unreachable, output, at {0} mu, channel {1}",
timestamp, channel as i64, 0);
}
} }
pub extern fn output(target: i32, data: i32) { pub extern fn output(target: i32, data: i32) {
unimplemented!(); unsafe {
// Clear status so we can observe response
TRANSACTION_BUFFER.reply_status.set(0);
TRANSACTION_BUFFER.request_cmd = 0;
TRANSACTION_BUFFER.request_target = target;
TRANSACTION_BUFFER.request_data = data as i64;
asm::dmb();
asm::sev();
let mut status;
loop {
status = TRANSACTION_BUFFER.reply_status.get();
if status != 0 {
break
}
}
let status = status & !0x10000;
if status != 0 {
process_exceptional_status(target >> 8, status);
}
}
} }
pub extern fn output_wide(target: i32, data: CSlice<i32>) { pub extern fn output_wide(target: i32, data: CSlice<i32>) {
// TODO
unimplemented!(); unimplemented!();
} }
@ -62,5 +145,6 @@ pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedD
} }
pub fn write_log(data: &[i8]) { pub fn write_log(data: &[i8]) {
// TODO
unimplemented!(); unimplemented!();
} }