forked from M-Labs/artiq-zynq
164 lines
4.6 KiB
Rust
164 lines
4.6 KiB
Rust
#![no_std]
|
|
#![feature(c_variadic)]
|
|
#![feature(const_btree_new)]
|
|
#![feature(const_in_array_repeat_expressions)]
|
|
#![feature(naked_functions)]
|
|
#![feature(asm)]
|
|
|
|
#[macro_use]
|
|
extern crate alloc;
|
|
|
|
use alloc::{collections::BTreeMap, string::String};
|
|
|
|
use io::{Cursor, ProtoRead};
|
|
use libasync::block_async;
|
|
use libconfig::Config;
|
|
use log::{error, warn};
|
|
#[cfg(has_drtiosat)]
|
|
pub use pl::csr::drtiosat as rtio_core;
|
|
#[cfg(has_rtio_core)]
|
|
pub use pl::csr::rtio_core;
|
|
use void::Void;
|
|
|
|
pub mod eh_artiq;
|
|
pub mod i2c;
|
|
pub mod irq;
|
|
pub mod kernel;
|
|
pub mod rpc;
|
|
#[cfg(ki_impl = "csr")]
|
|
#[path = "rtio_csr.rs"]
|
|
pub mod rtio;
|
|
#[cfg(ki_impl = "acp")]
|
|
#[path = "rtio_acp.rs"]
|
|
pub mod rtio;
|
|
#[rustfmt::skip]
|
|
#[path = "../../../build/pl.rs"]
|
|
pub mod pl;
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct RPCException {
|
|
pub id: u32,
|
|
pub message: u32,
|
|
pub param: [i64; 3],
|
|
pub file: u32,
|
|
pub line: i32,
|
|
pub column: i32,
|
|
pub function: u32,
|
|
}
|
|
|
|
pub static mut SEEN_ASYNC_ERRORS: u8 = 0;
|
|
|
|
pub const ASYNC_ERROR_COLLISION: u8 = 1 << 0;
|
|
pub const ASYNC_ERROR_BUSY: u8 = 1 << 1;
|
|
pub const ASYNC_ERROR_SEQUENCE_ERROR: u8 = 1 << 2;
|
|
|
|
pub unsafe fn get_async_errors() -> u8 {
|
|
let errors = SEEN_ASYNC_ERRORS;
|
|
SEEN_ASYNC_ERRORS = 0;
|
|
errors
|
|
}
|
|
|
|
fn wait_for_async_rtio_error() -> nb::Result<(), Void> {
|
|
unsafe {
|
|
#[cfg(has_rtio_core)]
|
|
let errors = rtio_core::async_error_read();
|
|
#[cfg(has_drtiosat)]
|
|
let errors = rtio_core::protocol_error_read();
|
|
if errors != 0 {
|
|
Ok(())
|
|
} else {
|
|
Err(nb::Error::WouldBlock)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn report_async_rtio_errors() {
|
|
loop {
|
|
let _ = block_async!(wait_for_async_rtio_error()).await;
|
|
unsafe {
|
|
#[cfg(has_rtio_core)]
|
|
let errors = rtio_core::async_error_read();
|
|
#[cfg(has_drtiosat)]
|
|
let errors = rtio_core::protocol_error_read();
|
|
if errors & ASYNC_ERROR_COLLISION != 0 {
|
|
let channel = rtio_core::collision_channel_read();
|
|
error!(
|
|
"RTIO collision involving channel 0x{:04x}:{}",
|
|
channel,
|
|
resolve_channel_name(channel as u32)
|
|
);
|
|
}
|
|
if errors & ASYNC_ERROR_BUSY != 0 {
|
|
let channel = rtio_core::busy_channel_read();
|
|
error!(
|
|
"RTIO busy error involving channel 0x{:04x}:{}",
|
|
channel,
|
|
resolve_channel_name(channel as u32)
|
|
);
|
|
}
|
|
if errors & ASYNC_ERROR_SEQUENCE_ERROR != 0 {
|
|
let channel = rtio_core::sequence_error_channel_read();
|
|
error!(
|
|
"RTIO sequence error involving channel 0x{:04x}:{}",
|
|
channel,
|
|
resolve_channel_name(channel as u32)
|
|
);
|
|
}
|
|
SEEN_ASYNC_ERRORS = errors;
|
|
#[cfg(has_rtio_core)]
|
|
rtio_core::async_error_write(errors);
|
|
#[cfg(has_drtiosat)]
|
|
rtio_core::protocol_error_write(errors);
|
|
}
|
|
}
|
|
}
|
|
|
|
static mut RTIO_DEVICE_MAP: BTreeMap<u32, String> = BTreeMap::new();
|
|
|
|
fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> {
|
|
let mut device_map: BTreeMap<u32, String> = BTreeMap::new();
|
|
let _ = cfg
|
|
.read("device_map")
|
|
.and_then(|raw_bytes| {
|
|
let mut bytes_cr = Cursor::new(raw_bytes);
|
|
let size = bytes_cr.read_u32().unwrap();
|
|
for _ in 0..size {
|
|
let channel = bytes_cr.read_u32().unwrap();
|
|
let device_name = bytes_cr.read_string().unwrap();
|
|
if let Some(old_entry) = device_map.insert(channel, device_name.clone()) {
|
|
warn!(
|
|
"conflicting device map entries for RTIO channel {}: '{}' and '{}'",
|
|
channel, old_entry, device_name
|
|
);
|
|
}
|
|
}
|
|
Ok(())
|
|
})
|
|
.or_else(|err| {
|
|
warn!(
|
|
"error reading device map ({}), device names will not be available in RTIO error messages",
|
|
err
|
|
);
|
|
Err(err)
|
|
});
|
|
device_map
|
|
}
|
|
|
|
fn _resolve_channel_name(channel: u32, device_map: &BTreeMap<u32, String>) -> String {
|
|
match device_map.get(&channel) {
|
|
Some(val) => val.clone(),
|
|
None => String::from("unknown"),
|
|
}
|
|
}
|
|
|
|
pub fn resolve_channel_name(channel: u32) -> String {
|
|
_resolve_channel_name(channel, unsafe { &RTIO_DEVICE_MAP })
|
|
}
|
|
|
|
pub fn setup_device_map(cfg: &Config) {
|
|
unsafe {
|
|
RTIO_DEVICE_MAP = read_device_map(cfg);
|
|
}
|
|
}
|