ksupport: move async error reporting to runtime
This commit is contained in:
@@ -11,7 +11,6 @@ build_zynq = { path = "../libbuild_zynq" }
|
||||
[dependencies]
|
||||
cslice = "0.3"
|
||||
log = "0.4"
|
||||
nb = "0.1"
|
||||
core_io = { git = "https://git.m-labs.hk/M-Labs/rs-core_io.git", rev = "e9d3edf027", features = ["collections"] }
|
||||
byteorder = { version = "1.3", default-features = false }
|
||||
void = { version = "1", default-features = false }
|
||||
|
||||
@@ -14,7 +14,7 @@ use log::{debug, error, info};
|
||||
|
||||
use super::{CHANNEL_0TO1, CHANNEL_1TO0, CHANNEL_SEM, INIT_LOCK, KERNEL_CHANNEL_0TO1, KERNEL_CHANNEL_1TO0,
|
||||
KERNEL_IMAGE, Message, api::resolve, dma, rpc::rpc_send_async};
|
||||
use crate::{eh_artiq, get_async_errors};
|
||||
use crate::eh_artiq;
|
||||
|
||||
// linker symbols
|
||||
extern "C" {
|
||||
@@ -183,8 +183,7 @@ pub extern "C" fn main_core1() {
|
||||
}
|
||||
}
|
||||
info!("kernel finished");
|
||||
let async_errors = unsafe { get_async_errors() };
|
||||
core1_tx.send(Message::KernelFinished(async_errors));
|
||||
core1_tx.send(Message::KernelFinished);
|
||||
}
|
||||
_ => error!("Core1 received unexpected message: {:?}", message),
|
||||
}
|
||||
@@ -199,8 +198,7 @@ pub fn terminate(
|
||||
) -> ! {
|
||||
{
|
||||
let core1_tx = unsafe { KERNEL_CHANNEL_1TO0.as_mut().unwrap() };
|
||||
let errors = unsafe { get_async_errors() };
|
||||
core1_tx.send(Message::KernelException(exceptions, stack_pointers, backtrace, errors));
|
||||
core1_tx.send(Message::KernelException(exceptions, stack_pointers, backtrace));
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
||||
@@ -45,12 +45,11 @@ pub enum Message {
|
||||
LoadCompleted,
|
||||
LoadFailed,
|
||||
StartRequest,
|
||||
KernelFinished(u8),
|
||||
KernelFinished,
|
||||
KernelException(
|
||||
&'static [Option<eh_artiq::Exception<'static>>],
|
||||
&'static [eh_artiq::StackPointerBacktrace],
|
||||
&'static [(usize, usize)],
|
||||
u8,
|
||||
),
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
|
||||
@@ -8,13 +8,10 @@
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
use libasync::block_async;
|
||||
use log::error;
|
||||
#[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 irq;
|
||||
@@ -34,117 +31,3 @@ pub struct RPCException {
|
||||
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 RTIO_DEVICE_MAP: OnceLock<BTreeMap<u32, String>> = OnceLock::new();
|
||||
|
||||
fn read_device_map() -> BTreeMap<u32, String> {
|
||||
let mut device_map: BTreeMap<u32, String> = BTreeMap::new();
|
||||
let _ = libconfig::read("device_map")
|
||||
.and_then(|raw_bytes| {
|
||||
let mut bytes_cr = Cursor::new(raw_bytes);
|
||||
let size = bytes_cr.read_u32::<NativeEndian>().unwrap();
|
||||
for _ in 0..size {
|
||||
let channel = bytes_cr.read_u32::<NativeEndian>().unwrap();
|
||||
let device_name = bytes_cr.read_string::<NativeEndian>().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
|
||||
}
|
||||
|
||||
pub fn resolve_channel_name(channel: u32) -> String {
|
||||
match RTIO_DEVICE_MAP
|
||||
.get()
|
||||
.expect("cannot get device map before it is set up")
|
||||
.get(&channel)
|
||||
{
|
||||
Some(val) => val.clone(),
|
||||
None => String::from("unknown"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_device_map() {
|
||||
RTIO_DEVICE_MAP
|
||||
.set(read_device_map())
|
||||
.expect("device map can only be initialized once");
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ futures = { version = "0.3", default-features = false, features = ["async-await"
|
||||
async-recursion = "1.1"
|
||||
log_buffer = { version = "1.2" }
|
||||
vcell = "0.1"
|
||||
nb = "0.1"
|
||||
|
||||
libboard_zynq = { path = "@@ZYNQ_RS@@/libboard_zynq", features = ["ipv6", "async"]}
|
||||
libsupport_zynq = { path = "@@ZYNQ_RS@@/libsupport_zynq", default-features = false, features = ["alloc_core"] }
|
||||
|
||||
@@ -12,7 +12,8 @@ use io::Cursor;
|
||||
use ksupport::kernel;
|
||||
#[cfg(has_drtio)]
|
||||
use ksupport::rpc;
|
||||
use libasync::{smoltcp::{Sockets, TcpStream},
|
||||
use libasync::{block_async,
|
||||
smoltcp::{Sockets, TcpStream},
|
||||
task};
|
||||
#[cfg(has_drtio)]
|
||||
use libboard_artiq::drtioaux::Packet;
|
||||
@@ -35,10 +36,15 @@ use libcortex_a9::{mutex::Mutex,
|
||||
use log::{error, info, warn};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
#[cfg(has_drtiosat)]
|
||||
use pl::csr::drtiosat as rtio_core;
|
||||
#[cfg(has_rtio_core)]
|
||||
use pl::csr::rtio_core;
|
||||
#[cfg(has_drtio)]
|
||||
use tar_no_std::TarArchiveRef;
|
||||
use void::Void;
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
#[cfg(any(has_rtio_core, has_drtiosat, has_drtio))]
|
||||
use crate::pl;
|
||||
use crate::{analyzer, mgmt, moninj, proto_async::*, rpc_async, rtio_dma, rtio_mgt};
|
||||
#[cfg(has_drtio)]
|
||||
@@ -117,6 +123,73 @@ enum Reply {
|
||||
ClockFailure = 15,
|
||||
}
|
||||
|
||||
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 CACHE_STORE: Mutex<BTreeMap<String, Vec<i32>>> = Mutex::new(BTreeMap::new());
|
||||
|
||||
pub static RESTART_IDLE: Semaphore = Semaphore::new(1, 1);
|
||||
@@ -286,14 +359,16 @@ async fn handle_run_kernel(
|
||||
}
|
||||
}
|
||||
}
|
||||
kernel::Message::KernelFinished(async_errors) => {
|
||||
kernel::Message::KernelFinished => {
|
||||
let async_errors = unsafe { get_async_errors() };
|
||||
if let Some(stream) = stream {
|
||||
write_header(stream, Reply::KernelFinished).await?;
|
||||
write_i8(stream, async_errors as i8).await?;
|
||||
}
|
||||
break;
|
||||
}
|
||||
kernel::Message::KernelException(exceptions, stack_pointers, backtrace, async_errors) => {
|
||||
kernel::Message::KernelException(exceptions, stack_pointers, backtrace) => {
|
||||
let async_errors = unsafe { get_async_errors() };
|
||||
match stream {
|
||||
Some(stream) => {
|
||||
// only send the exception data to host if there is host,
|
||||
@@ -993,6 +1068,7 @@ pub fn main() {
|
||||
#[cfg(has_drtio_routing)]
|
||||
drtio_routing::interconnect_disable_all();
|
||||
|
||||
task::spawn(report_async_rtio_errors());
|
||||
rtio_mgt::startup(&up_destinations);
|
||||
libboard_artiq::setup_device_map();
|
||||
|
||||
|
||||
@@ -143,8 +143,6 @@ pub fn main_core0() {
|
||||
#[cfg(has_grabber)]
|
||||
task::spawn(grabber::grabber_thread());
|
||||
|
||||
task::spawn(ksupport::report_async_rtio_errors());
|
||||
|
||||
#[cfg(has_cxp_grabber)]
|
||||
{
|
||||
cxp_phys::setup();
|
||||
|
||||
@@ -10,8 +10,7 @@ pub mod drtio {
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
|
||||
use ksupport::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS,
|
||||
kernel::Message as KernelMessage};
|
||||
use ksupport::kernel::Message as KernelMessage;
|
||||
use libasync::task;
|
||||
#[cfg(has_drtio_eem)]
|
||||
use libboard_artiq::drtio_eem;
|
||||
@@ -25,7 +24,11 @@ pub mod drtio {
|
||||
use log::{error, info, warn};
|
||||
|
||||
use super::*;
|
||||
use crate::{analyzer::remote_analyzer::RemoteBuffer, comms::ROUTING_TABLE, rtio_dma::remote_dma, subkernel};
|
||||
use crate::{analyzer::remote_analyzer::RemoteBuffer,
|
||||
comms::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, ROUTING_TABLE,
|
||||
SEEN_ASYNC_ERRORS},
|
||||
rtio_dma::remote_dma,
|
||||
subkernel};
|
||||
|
||||
#[cfg(has_drtio_eem)]
|
||||
const DRTIO_EEM_LINKNOS: core::ops::Range<usize> =
|
||||
|
||||
Reference in New Issue
Block a user