forked from M-Labs/nac3
1
0
Fork 0

apply rustfmt policies to ddma code

This commit is contained in:
mwojcik 2023-03-27 15:53:32 +08:00
parent 90071f7620
commit 48721ca9cb
10 changed files with 390 additions and 321 deletions

View File

@ -141,32 +141,32 @@ pub enum Packet {
id: u32, id: u32,
last: bool, last: bool,
length: u16, length: u16,
trace: [u8; DMA_TRACE_MAX_SIZE] trace: [u8; DMA_TRACE_MAX_SIZE],
}, },
DmaAddTraceReply { DmaAddTraceReply {
succeeded: bool succeeded: bool,
}, },
DmaRemoveTraceRequest { DmaRemoveTraceRequest {
destination: u8, destination: u8,
id: u32 id: u32,
}, },
DmaRemoveTraceReply { DmaRemoveTraceReply {
succeeded: bool succeeded: bool,
}, },
DmaPlaybackRequest { DmaPlaybackRequest {
destination: u8, destination: u8,
id: u32, id: u32,
timestamp: u64 timestamp: u64,
}, },
DmaPlaybackReply { DmaPlaybackReply {
succeeded: bool succeeded: bool,
}, },
DmaPlaybackStatus { DmaPlaybackStatus {
destination: u8, destination: u8,
id: u32, id: u32,
error: u8, error: u8,
channel: u32, channel: u32,
timestamp: u64 timestamp: u64,
}, },
} }
@ -312,31 +312,31 @@ impl Packet {
length: length as u16, length: length as u16,
trace: trace, trace: trace,
} }
}, }
0xb1 => Packet::DmaAddTraceReply { 0xb1 => Packet::DmaAddTraceReply {
succeeded: reader.read_bool()? succeeded: reader.read_bool()?,
}, },
0xb2 => Packet::DmaRemoveTraceRequest { 0xb2 => Packet::DmaRemoveTraceRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32()? id: reader.read_u32()?,
}, },
0xb3 => Packet::DmaRemoveTraceReply { 0xb3 => Packet::DmaRemoveTraceReply {
succeeded: reader.read_bool()? succeeded: reader.read_bool()?,
}, },
0xb4 => Packet::DmaPlaybackRequest { 0xb4 => Packet::DmaPlaybackRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32()?, id: reader.read_u32()?,
timestamp: reader.read_u64()? timestamp: reader.read_u64()?,
}, },
0xb5 => Packet::DmaPlaybackReply { 0xb5 => Packet::DmaPlaybackReply {
succeeded: reader.read_bool()? succeeded: reader.read_bool()?,
}, },
0xb6 => Packet::DmaPlaybackStatus { 0xb6 => Packet::DmaPlaybackStatus {
destination: reader.read_u8()?, destination: reader.read_u8()?,
id: reader.read_u32()?, id: reader.read_u32()?,
error: reader.read_u8()?, error: reader.read_u8()?,
channel: reader.read_u32()?, channel: reader.read_u32()?,
timestamp: reader.read_u64()? timestamp: reader.read_u64()?,
}, },
ty => return Err(Error::UnknownPacket(ty)), ty => return Err(Error::UnknownPacket(ty)),
@ -531,7 +531,7 @@ impl Packet {
id, id,
last, last,
trace, trace,
length length,
} => { } => {
writer.write_u8(0xb0)?; writer.write_u8(0xb0)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
@ -558,7 +558,7 @@ impl Packet {
Packet::DmaPlaybackRequest { Packet::DmaPlaybackRequest {
destination, destination,
id, id,
timestamp timestamp,
} => { } => {
writer.write_u8(0xb4)?; writer.write_u8(0xb4)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
@ -574,7 +574,7 @@ impl Packet {
id, id,
error, error,
channel, channel,
timestamp timestamp,
} => { } => {
writer.write_u8(0xb6)?; writer.write_u8(0xb6)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;

View File

@ -26,9 +26,8 @@ use num_traits::{FromPrimitive, ToPrimitive};
use crate::pl; use crate::pl;
use crate::{analyzer, kernel, mgmt, moninj, use crate::{analyzer, kernel, mgmt, moninj,
proto_async::*, proto_async::*,
rpc, rpc, rtio_dma,
rtio_mgt::{self, resolve_channel_name}, rtio_mgt::{self, resolve_channel_name}};
rtio_dma};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error { pub enum Error {
@ -81,7 +80,6 @@ enum Reply {
static CACHE_STORE: Mutex<BTreeMap<String, Vec<i32>>> = Mutex::new(BTreeMap::new()); static CACHE_STORE: Mutex<BTreeMap<String, Vec<i32>>> = Mutex::new(BTreeMap::new());
async fn write_header(stream: &TcpStream, reply: Reply) -> Result<()> { async fn write_header(stream: &TcpStream, reply: Reply) -> Result<()> {
stream stream
.send_slice(&[0x5a, 0x5a, 0x5a, 0x5a, reply.to_u8().unwrap()]) .send_slice(&[0x5a, 0x5a, 0x5a, 0x5a, reply.to_u8().unwrap()])
@ -160,7 +158,7 @@ async fn handle_run_kernel(
_up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, _up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer timer: GlobalTimer,
) -> Result<()> { ) -> Result<()> {
control.borrow_mut().tx.async_send(kernel::Message::StartRequest).await; control.borrow_mut().tx.async_send(kernel::Message::StartRequest).await;
loop { loop {
@ -350,19 +348,19 @@ async fn handle_run_kernel(
Ok(rtio_dma::remote_dma::RemoteState::PlaybackEnded { Ok(rtio_dma::remote_dma::RemoteState::PlaybackEnded {
error, error,
channel, channel,
timestamp timestamp,
}) => kernel::Message::DmaAwaitRemoteReply { }) => kernel::Message::DmaAwaitRemoteReply {
timeout: false, timeout: false,
error: error, error: error,
channel: channel, channel: channel,
timestamp: timestamp timestamp: timestamp,
}, },
_ => kernel::Message::DmaAwaitRemoteReply { _ => kernel::Message::DmaAwaitRemoteReply {
timeout: true, timeout: true,
error: 0, error: 0,
channel: 0, channel: 0,
timestamp: 0 timestamp: 0,
} },
}; };
control.borrow_mut().tx.async_send(reply).await; control.borrow_mut().tx.async_send(reply).await;
} }
@ -428,7 +426,7 @@ async fn handle_connection(
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer timer: GlobalTimer,
) -> Result<()> { ) -> Result<()> {
stream.set_ack_delay(None); stream.set_ack_delay(None);
@ -452,7 +450,15 @@ async fn handle_connection(
load_kernel(&buffer, &control, Some(stream)).await?; load_kernel(&buffer, &control, Some(stream)).await?;
} }
Request::RunKernel => { Request::RunKernel => {
handle_run_kernel(Some(stream), &control, &up_destinations, aux_mutex, routing_table, timer).await?; handle_run_kernel(
Some(stream),
&control,
&up_destinations,
aux_mutex,
routing_table,
timer,
)
.await?;
} }
_ => { _ => {
error!("unexpected request from host: {:?}", request); error!("unexpected request from host: {:?}", request);
@ -528,7 +534,14 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
if let Ok(()) = task::block_on(load_kernel(&buffer, &control, None)) { if let Ok(()) = task::block_on(load_kernel(&buffer, &control, None)) {
info!("Starting startup kernel..."); info!("Starting startup kernel...");
let routing_table = drtio_routing_table.borrow(); let routing_table = drtio_routing_table.borrow();
let _ = task::block_on(handle_run_kernel(None, &control, &up_destinations, &aux_mutex, &routing_table, timer)); let _ = task::block_on(handle_run_kernel(
None,
&control,
&up_destinations,
&aux_mutex,
&routing_table,
timer,
));
info!("Startup kernel finished!"); info!("Startup kernel finished!");
} else { } else {
error!("Error loading startup kernel!"); error!("Error loading startup kernel!");

View File

@ -17,7 +17,7 @@ pub struct DmaRecorder {
pub name: String, pub name: String,
pub buffer: Vec<u8>, pub buffer: Vec<u8>,
pub duration: i64, pub duration: i64,
pub enable_ddma: bool pub enable_ddma: bool,
} }
static mut RECORDER: Option<DmaRecorder> = None; static mut RECORDER: Option<DmaRecorder> = None;
@ -51,7 +51,7 @@ pub extern "C" fn dma_record_start(name: CSlice<u8>) {
name, name,
buffer: Vec::new(), buffer: Vec::new(),
duration: 0, duration: 0,
enable_ddma: false enable_ddma: false,
}); });
} }
} }
@ -168,8 +168,13 @@ pub extern "C" fn dma_playback(timestamp: i64, ptr: i32) {
csr::cri_con::selected_write(1); csr::cri_con::selected_write(1);
csr::rtio_dma::enable_write(1); csr::rtio_dma::enable_write(1);
#[cfg(has_drtio)] #[cfg(has_drtio)]
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send( KERNEL_CHANNEL_1TO0
Message::DmaStartRemoteRequest{ id: ptr, timestamp: timestamp }); .as_mut()
.unwrap()
.send(Message::DmaStartRemoteRequest {
id: ptr,
timestamp: timestamp,
});
while csr::rtio_dma::enable_read() != 0 {} while csr::rtio_dma::enable_read() != 0 {}
csr::cri_con::selected_write(0); csr::cri_con::selected_write(0);
@ -199,10 +204,17 @@ pub extern "C" fn dma_playback(timestamp: i64, ptr: i32) {
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
{ {
KERNEL_CHANNEL_1TO0.as_mut().unwrap().send( KERNEL_CHANNEL_1TO0
Message::DmaAwaitRemoteRequest(ptr)); .as_mut()
.unwrap()
.send(Message::DmaAwaitRemoteRequest(ptr));
match KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv() { match KERNEL_CHANNEL_0TO1.as_mut().unwrap().recv() {
Message::DmaAwaitRemoteReply { timeout, error, channel, timestamp } => { Message::DmaAwaitRemoteReply {
timeout,
error,
channel,
timestamp,
} => {
if timeout { if timeout {
artiq_raise!( artiq_raise!(
"DMAError", "DMAError",

View File

@ -56,7 +56,7 @@ pub enum Message {
#[cfg(has_drtio)] #[cfg(has_drtio)]
DmaStartRemoteRequest { DmaStartRemoteRequest {
id: i32, id: i32,
timestamp: i64 timestamp: i64,
}, },
#[cfg(has_drtio)] #[cfg(has_drtio)]
DmaAwaitRemoteRequest(i32), DmaAwaitRemoteRequest(i32),
@ -65,7 +65,7 @@ pub enum Message {
timeout: bool, timeout: bool,
error: u8, error: u8,
channel: u32, channel: u32,
timestamp: u64 timestamp: u64,
}, },
#[cfg(has_drtio)] #[cfg(has_drtio)]

View File

@ -46,8 +46,8 @@ mod rtio;
#[path = "rtio_acp.rs"] #[path = "rtio_acp.rs"]
mod rtio; mod rtio;
mod rtio_clocking; mod rtio_clocking;
mod rtio_mgt;
mod rtio_dma; mod rtio_dma;
mod rtio_mgt;
static mut SEEN_ASYNC_ERRORS: u8 = 0; static mut SEEN_ASYNC_ERRORS: u8 = 0;

View File

@ -298,7 +298,11 @@ async fn handle_connection(
} }
} }
pub fn start(timer: GlobalTimer, aux_mutex: &Rc<Mutex<bool>>, routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>) { pub fn start(
timer: GlobalTimer,
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>,
) {
let aux_mutex = aux_mutex.clone(); let aux_mutex = aux_mutex.clone();
let routing_table = routing_table.clone(); let routing_table = routing_table.clone();
task::spawn(async move { task::spawn(async move {

View File

@ -1,12 +1,13 @@
use alloc::{collections::BTreeMap, rc::Rc, string::String, vec::Vec};
use alloc::{collections::BTreeMap, string::String, vec::Vec, rc::Rc};
use libcortex_a9::{mutex::Mutex, cache::dcci_slice};
use libboard_zynq::timer::GlobalTimer;
use libboard_artiq::drtio_routing::RoutingTable;
#[cfg(has_drtio)]
use libasync::task;
#[cfg(has_drtio)] #[cfg(has_drtio)]
use core::mem; use core::mem;
#[cfg(has_drtio)]
use libasync::task;
use libboard_artiq::drtio_routing::RoutingTable;
use libboard_zynq::timer::GlobalTimer;
use libcortex_a9::{cache::dcci_slice, mutex::Mutex};
use crate::kernel::DmaRecorder; use crate::kernel::DmaRecorder;
const ALIGNMENT: usize = 16 * 8; const ALIGNMENT: usize = 16 * 8;
@ -15,28 +16,29 @@ static DMA_RECORD_STORE: Mutex<BTreeMap<String, (u32, Vec<u8>, i64)>> = Mutex::n
#[cfg(has_drtio)] #[cfg(has_drtio)]
pub mod remote_dma { pub mod remote_dma {
use super::*;
use libboard_zynq::time::Milliseconds; use libboard_zynq::time::Milliseconds;
use log::error; use log::error;
use super::*;
use crate::rtio_mgt::drtio; use crate::rtio_mgt::drtio;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum RemoteState { pub enum RemoteState {
NotLoaded, NotLoaded,
Loaded, Loaded,
PlaybackEnded { error: u8, channel: u32, timestamp: u64 } PlaybackEnded { error: u8, channel: u32, timestamp: u64 },
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct RemoteTrace { struct RemoteTrace {
trace: Vec<u8>, trace: Vec<u8>,
pub state: RemoteState pub state: RemoteState,
} }
impl From<Vec<u8>> for RemoteTrace { impl From<Vec<u8>> for RemoteTrace {
fn from(trace: Vec<u8>) -> Self { fn from(trace: Vec<u8>) -> Self {
RemoteTrace { RemoteTrace {
trace: trace, trace: trace,
state: RemoteState::NotLoaded state: RemoteState::NotLoaded,
} }
} }
} }
@ -51,7 +53,7 @@ pub mod remote_dma {
struct TraceSet { struct TraceSet {
id: u32, id: u32,
done_count: Mutex<usize>, done_count: Mutex<usize>,
traces: Mutex<BTreeMap<u8, RemoteTrace>> traces: Mutex<BTreeMap<u8, RemoteTrace>>,
} }
impl TraceSet { impl TraceSet {
@ -63,26 +65,27 @@ pub mod remote_dma {
TraceSet { TraceSet {
id: id, id: id,
done_count: Mutex::new(0), done_count: Mutex::new(0),
traces: Mutex::new(trace_map) traces: Mutex::new(trace_map),
} }
} }
pub async fn await_done( pub async fn await_done(&self, timeout: Option<u64>, timer: GlobalTimer) -> Result<RemoteState, &'static str> {
&self,
timeout: Option<u64>,
timer: GlobalTimer
) -> Result<RemoteState, &'static str> {
let timeout_ms = Milliseconds(timeout.unwrap_or(10_000)); let timeout_ms = Milliseconds(timeout.unwrap_or(10_000));
let limit = timer.get_time() + timeout_ms; let limit = timer.get_time() + timeout_ms;
while (timer.get_time() < limit) & while (timer.get_time() < limit)
(*(self.done_count.async_lock().await) < self.traces.async_lock().await.len()) { & (*(self.done_count.async_lock().await) < self.traces.async_lock().await.len())
{
task::r#yield().await; task::r#yield().await;
} }
if timer.get_time() >= limit { if timer.get_time() >= limit {
error!("Remote DMA await done timed out"); error!("Remote DMA await done timed out");
return Err("Timed out waiting for results."); return Err("Timed out waiting for results.");
} }
let mut playback_state: RemoteState = RemoteState::PlaybackEnded { error: 0, channel: 0, timestamp: 0 }; let mut playback_state: RemoteState = RemoteState::PlaybackEnded {
error: 0,
channel: 0,
timestamp: 0,
};
let mut lock = self.traces.async_lock().await; let mut lock = self.traces.async_lock().await;
let trace_iter = lock.iter_mut(); let trace_iter = lock.iter_mut();
for (_dest, trace) in trace_iter { for (_dest, trace) in trace_iter {
@ -90,8 +93,12 @@ pub mod remote_dma {
RemoteState::PlaybackEnded { RemoteState::PlaybackEnded {
error: e, error: e,
channel: _c, channel: _c,
timestamp: _ts timestamp: _ts,
} => if e != 0 { playback_state = trace.state.clone(); }, } => {
if e != 0 {
playback_state = trace.state.clone();
}
}
_ => (), _ => (),
} }
trace.state = RemoteState::Loaded; trace.state = RemoteState::Loaded;
@ -103,7 +110,7 @@ pub mod remote_dma {
&mut self, &mut self,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer timer: GlobalTimer,
) { ) {
let mut lock = self.traces.async_lock().await; let mut lock = self.traces.async_lock().await;
let trace_iter = lock.iter_mut(); let trace_iter = lock.iter_mut();
@ -114,33 +121,24 @@ pub mod remote_dma {
timer, timer,
self.id, self.id,
*destination, *destination,
trace.get_trace() trace.get_trace(),
).await { )
.await
{
Ok(_) => trace.state = RemoteState::Loaded, Ok(_) => trace.state = RemoteState::Loaded,
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e) Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e),
} }
} }
*(self.done_count.async_lock().await) = 0; *(self.done_count.async_lock().await) = 0;
} }
pub async fn erase( pub async fn erase(&mut self, aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer) {
&mut self,
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer
) {
let lock = self.traces.async_lock().await; let lock = self.traces.async_lock().await;
let trace_iter = lock.keys(); let trace_iter = lock.keys();
for destination in trace_iter { for destination in trace_iter {
match drtio::ddma_send_erase( match drtio::ddma_send_erase(aux_mutex, routing_table, timer, self.id, *destination).await {
aux_mutex,
routing_table,
timer,
self.id,
*destination
).await {
Ok(_) => (), Ok(_) => (),
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e) Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e),
} }
} }
} }
@ -151,7 +149,7 @@ pub mod remote_dma {
trace.state = RemoteState::PlaybackEnded { trace.state = RemoteState::PlaybackEnded {
error: error, error: error,
channel: channel, channel: channel,
timestamp: timestamp timestamp: timestamp,
}; };
*(self.done_count.async_lock().await) += 1; *(self.done_count.async_lock().await) += 1;
} }
@ -161,7 +159,7 @@ pub mod remote_dma {
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
timestamp: u64 timestamp: u64,
) { ) {
let mut dest_list: Vec<u8> = Vec::new(); let mut dest_list: Vec<u8> = Vec::new();
{ {
@ -178,16 +176,10 @@ pub mod remote_dma {
// mutex lock must be dropped before sending a playback request to avoid a deadlock, // mutex lock must be dropped before sending a playback request to avoid a deadlock,
// if PlaybackStatus is sent from another satellite and the state must be updated. // if PlaybackStatus is sent from another satellite and the state must be updated.
for destination in dest_list { for destination in dest_list {
match drtio::ddma_send_playback( match drtio::ddma_send_playback(aux_mutex, routing_table, timer, self.id, destination, timestamp).await
aux_mutex, {
routing_table,
timer,
self.id,
destination,
timestamp
).await {
Ok(_) => (), Ok(_) => (),
Err(e) => error!("Error during remote DMA playback: {}", e) Err(e) => error!("Error during remote DMA playback: {}", e),
} }
} }
} }
@ -197,7 +189,8 @@ pub mod remote_dma {
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
destination: u8, up: bool destination: u8,
up: bool,
) { ) {
// update state of the destination, resend traces if it's up // update state of the destination, resend traces if it's up
if let Some(trace) = self.traces.lock().get_mut(&destination) { if let Some(trace) = self.traces.lock().get_mut(&destination) {
@ -208,10 +201,12 @@ pub mod remote_dma {
timer, timer,
self.id, self.id,
destination, destination,
trace.get_trace() trace.get_trace(),
).await { )
.await
{
Ok(_) => trace.state = RemoteState::Loaded, Ok(_) => trace.state = RemoteState::Loaded,
Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e) Err(e) => error!("Error adding DMA trace on destination {}: {}", destination, e),
} }
} else { } else {
trace.state = RemoteState::NotLoaded; trace.state = RemoteState::NotLoaded;
@ -226,32 +221,20 @@ pub mod remote_dma {
unsafe { TRACES.insert(id, TraceSet::new(id, traces)) }; unsafe { TRACES.insert(id, TraceSet::new(id, traces)) };
} }
pub async fn await_done( pub async fn await_done(id: u32, timeout: Option<u64>, timer: GlobalTimer) -> Result<RemoteState, &'static str> {
id: u32,
timeout: Option<u64>,
timer: GlobalTimer
) -> Result<RemoteState, &'static str> {
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() }; let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
trace_set.await_done(timeout, timer).await trace_set.await_done(timeout, timer).await
} }
pub async fn erase( pub async fn erase(aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer, id: u32) {
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32
) {
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() }; let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
trace_set.erase(aux_mutex, routing_table, timer).await; trace_set.erase(aux_mutex, routing_table, timer).await;
unsafe { TRACES.remove(&id); } unsafe {
TRACES.remove(&id);
}
} }
pub async fn upload_traces( pub async fn upload_traces(aux_mutex: &Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer, id: u32) {
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
id: u32
) {
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() }; let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
trace_set.upload_traces(aux_mutex, routing_table, timer).await; trace_set.upload_traces(aux_mutex, routing_table, timer).await;
} }
@ -261,19 +244,13 @@ pub mod remote_dma {
routing_table: &RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
timestamp: u64 timestamp: u64,
) { ) {
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() }; let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
trace_set.playback(aux_mutex, routing_table, timer, timestamp).await; trace_set.playback(aux_mutex, routing_table, timer, timestamp).await;
} }
pub async fn playback_done( pub async fn playback_done(id: u32, destination: u8, error: u8, channel: u32, timestamp: u64) {
id: u32,
destination: u8,
error: u8,
channel: u32,
timestamp: u64
) {
let trace_set = unsafe { TRACES.get_mut(&id).unwrap() }; let trace_set = unsafe { TRACES.get_mut(&id).unwrap() };
trace_set.playback_done(destination, error, channel, timestamp).await; trace_set.playback_done(destination, error, channel, timestamp).await;
} }
@ -283,17 +260,19 @@ pub mod remote_dma {
routing_table: &RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
destination: u8, destination: u8,
up: bool up: bool,
) { ) {
let trace_iter = unsafe { TRACES.values_mut() }; let trace_iter = unsafe { TRACES.values_mut() };
for trace_set in trace_iter { for trace_set in trace_iter {
trace_set.destination_changed(aux_mutex, routing_table, timer, destination, up).await; trace_set
.destination_changed(aux_mutex, routing_table, timer, destination, up)
.await;
} }
} }
} }
pub async fn put_record(
pub async fn put_record(_aux_mutex: &Rc<Mutex<bool>>, _aux_mutex: &Rc<Mutex<bool>>,
_routing_table: &RoutingTable, _routing_table: &RoutingTable,
_timer: GlobalTimer, _timer: GlobalTimer,
mut recorder: DmaRecorder, mut recorder: DmaRecorder,
@ -312,15 +291,14 @@ pub async fn put_record(_aux_mutex: &Rc<Mutex<bool>>,
while recorder.buffer[ptr] != 0 { while recorder.buffer[ptr] != 0 {
// ptr + 3 = tgt >> 24 (destination) // ptr + 3 = tgt >> 24 (destination)
let len = recorder.buffer[ptr] as usize; let len = recorder.buffer[ptr] as usize;
let destination = recorder.buffer[ptr+3]; let destination = recorder.buffer[ptr + 3];
if destination == 0 { if destination == 0 {
local_trace.extend(&recorder.buffer[ptr..ptr+len]); local_trace.extend(&recorder.buffer[ptr..ptr + len]);
}
else {
if let Some(remote_trace) = remote_traces.get_mut(&destination) {
remote_trace.extend(&recorder.buffer[ptr..ptr+len]);
} else { } else {
remote_traces.insert(destination, recorder.buffer[ptr..ptr+len].to_vec()); if let Some(remote_trace) = remote_traces.get_mut(&destination) {
remote_trace.extend(&recorder.buffer[ptr..ptr + len]);
} else {
remote_traces.insert(destination, recorder.buffer[ptr..ptr + len].to_vec());
} }
} }
// and jump to the next event // and jump to the next event
@ -357,9 +335,7 @@ pub async fn put_record(_aux_mutex: &Rc<Mutex<bool>>,
ptr ptr
} }
pub async fn erase(name: String, _aux_mutex: &Rc<Mutex<bool>>, pub async fn erase(name: String, _aux_mutex: &Rc<Mutex<bool>>, _routing_table: &RoutingTable, _timer: GlobalTimer) {
_routing_table: &RoutingTable, _timer: GlobalTimer
) {
let _entry = DMA_RECORD_STORE.lock().remove(&name); let _entry = DMA_RECORD_STORE.lock().remove(&name);
#[cfg(has_drtio)] #[cfg(has_drtio)]
if let Some((id, _v, _d)) = _entry { if let Some((id, _v, _d)) = _entry {

View File

@ -12,17 +12,17 @@ static mut RTIO_DEVICE_MAP: BTreeMap<u32, String> = BTreeMap::new();
#[cfg(has_drtio)] #[cfg(has_drtio)]
pub mod drtio { pub mod drtio {
use embedded_hal::blocking::delay::DelayMs;
use alloc::vec::Vec; use alloc::vec::Vec;
use embedded_hal::blocking::delay::DelayMs;
use libasync::{delay, task}; use libasync::{delay, task};
use libboard_artiq::{drtioaux::Error, drtioaux_async, drtioaux_async::Packet}; use libboard_artiq::{drtioaux::Error, drtioaux_async, drtioaux_async::Packet, drtioaux_proto::DMA_TRACE_MAX_SIZE};
use libboard_artiq::drtioaux_proto::DMA_TRACE_MAX_SIZE;
use libboard_zynq::time::Milliseconds; use libboard_zynq::time::Milliseconds;
use log::{error, info, warn}; use log::{error, info, warn};
use super::*; use super::*;
use crate::{ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, SEEN_ASYNC_ERRORS}; use crate::{rtio_dma::remote_dma, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR,
use crate::rtio_dma::remote_dma; SEEN_ASYNC_ERRORS};
pub fn startup( pub fn startup(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
@ -69,11 +69,17 @@ pub mod drtio {
loop { loop {
let reply = recv_aux_timeout(linkno, 200, timer).await; let reply = recv_aux_timeout(linkno, 200, timer).await;
match reply { match reply {
Ok(Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp }) => { Ok(Packet::DmaPlaybackStatus {
id,
destination,
error,
channel,
timestamp,
}) => {
remote_dma::playback_done(id, destination, error, channel, timestamp).await; remote_dma::playback_done(id, destination, error, channel, timestamp).await;
}, }
Ok(packet) => return Ok(packet), Ok(packet) => return Ok(packet),
Err(e) => return Err(e) Err(e) => return Err(e),
} }
} }
} }
@ -184,8 +190,13 @@ pub mod drtio {
async fn process_unsolicited_aux(aux_mutex: &Rc<Mutex<bool>>, linkno: u8) { async fn process_unsolicited_aux(aux_mutex: &Rc<Mutex<bool>>, linkno: u8) {
let _lock = aux_mutex.async_lock().await; let _lock = aux_mutex.async_lock().await;
match drtioaux_async::recv(linkno).await { match drtioaux_async::recv(linkno).await {
Ok(Some(Packet::DmaPlaybackStatus { id, destination, error, channel, timestamp }) Ok(Some(Packet::DmaPlaybackStatus {
) => remote_dma::playback_done(id, destination, error, channel, timestamp).await, id,
destination,
error,
channel,
timestamp,
})) => remote_dma::playback_done(id, destination, error, channel, timestamp).await,
Ok(Some(packet)) => warn!("[LINK#{}] unsolicited aux packet: {:?}", linkno, packet), Ok(Some(packet)) => warn!("[LINK#{}] unsolicited aux packet: {:?}", linkno, packet),
Ok(None) => (), Ok(None) => (),
Err(_) => warn!("[LINK#{}] aux packet error", linkno), Err(_) => warn!("[LINK#{}] aux packet error", linkno),
@ -267,7 +278,8 @@ pub mod drtio {
match reply { match reply {
Ok(Packet::DestinationDownReply) => { Ok(Packet::DestinationDownReply) => {
destination_set_up(routing_table, up_destinations, destination, false).await; destination_set_up(routing_table, up_destinations, destination, false).await;
remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, false).await; remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, false)
.await;
} }
Ok(Packet::DestinationOkReply) => (), Ok(Packet::DestinationOkReply) => (),
Ok(Packet::DestinationSequenceErrorReply { channel }) => { Ok(Packet::DestinationSequenceErrorReply { channel }) => {
@ -320,7 +332,8 @@ pub mod drtio {
Ok(Packet::DestinationOkReply) => { Ok(Packet::DestinationOkReply) => {
destination_set_up(routing_table, up_destinations, destination, true).await; destination_set_up(routing_table, up_destinations, destination, true).await;
init_buffer_space(destination as u8, linkno).await; init_buffer_space(destination as u8, linkno).await;
remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, true).await; remote_dma::destination_changed(aux_mutex, routing_table, timer, destination, true)
.await;
} }
Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet), Ok(packet) => error!("[DEST#{}] received unexpected aux packet: {:?}", destination, packet),
Err(e) => error!("[DEST#{}] communication failed ({})", destination, e), Err(e) => error!("[DEST#{}] communication failed ({})", destination, e),
@ -413,48 +426,72 @@ pub mod drtio {
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
trace: &Vec<u8> trace: &Vec<u8>,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let mut i = 0; let mut i = 0;
while i < trace.len() { while i < trace.len() {
let mut trace_slice: [u8; DMA_TRACE_MAX_SIZE] = [0; DMA_TRACE_MAX_SIZE]; let mut trace_slice: [u8; DMA_TRACE_MAX_SIZE] = [0; DMA_TRACE_MAX_SIZE];
let len: usize = if i + DMA_TRACE_MAX_SIZE < trace.len() { DMA_TRACE_MAX_SIZE } else { trace.len() - i } as usize; let len: usize = if i + DMA_TRACE_MAX_SIZE < trace.len() {
DMA_TRACE_MAX_SIZE
} else {
trace.len() - i
} as usize;
let last = i + len == trace.len(); let last = i + len == trace.len();
trace_slice[..len].clone_from_slice(&trace[i..i+len]); trace_slice[..len].clone_from_slice(&trace[i..i + len]);
i += len; i += len;
let reply = aux_transact(aux_mutex, linkno, let reply = aux_transact(
aux_mutex,
linkno,
&Packet::DmaAddTraceRequest { &Packet::DmaAddTraceRequest {
id: id, destination: destination, last: last, length: len as u16, trace: trace_slice}, id: id,
timer).await; destination: destination,
last: last,
length: len as u16,
trace: trace_slice,
},
timer,
)
.await;
match reply { match reply {
Ok(Packet::DmaAddTraceReply { succeeded: true }) => (), Ok(Packet::DmaAddTraceReply { succeeded: true }) => (),
Ok(Packet::DmaAddTraceReply { succeeded: false }) => { Ok(Packet::DmaAddTraceReply { succeeded: false }) => {
return Err("error adding trace on satellite"); }, return Err("error adding trace on satellite");
Ok(_) => { return Err("adding DMA trace failed, unexpected aux packet"); }, }
Err(_) => { return Err("adding DMA trace failed, aux error"); } Ok(_) => {
return Err("adding DMA trace failed, unexpected aux packet");
}
Err(_) => {
return Err("adding DMA trace failed, aux error");
}
} }
} }
Ok(()) Ok(())
} }
pub async fn ddma_send_erase( pub async fn ddma_send_erase(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8 destination: u8,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(aux_mutex, linkno, let reply = aux_transact(
&Packet::DmaRemoveTraceRequest { id: id, destination: destination }, aux_mutex,
timer).await; linkno,
&Packet::DmaRemoveTraceRequest {
id: id,
destination: destination,
},
timer,
)
.await;
match reply { match reply {
Ok(Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()), Ok(Packet::DmaRemoveTraceReply { succeeded: true }) => Ok(()),
Ok(Packet::DmaRemoveTraceReply { succeeded: false }) => Err("satellite DMA erase error"), Ok(Packet::DmaRemoveTraceReply { succeeded: false }) => Err("satellite DMA erase error"),
Ok(_) => Err("adding trace failed, unexpected aux packet"), Ok(_) => Err("adding trace failed, unexpected aux packet"),
Err(_) => Err("erasing trace failed, aux error") Err(_) => Err("erasing trace failed, aux error"),
} }
} }
@ -464,19 +501,27 @@ pub mod drtio {
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
timestamp: u64 timestamp: u64,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact(aux_mutex, linkno, &Packet::DmaPlaybackRequest{ let reply = aux_transact(
id: id, destination: destination, timestamp: timestamp }, timer).await; aux_mutex,
linkno,
&Packet::DmaPlaybackRequest {
id: id,
destination: destination,
timestamp: timestamp,
},
timer,
)
.await;
match reply { match reply {
Ok(Packet::DmaPlaybackReply { succeeded: true }) => Ok(()), Ok(Packet::DmaPlaybackReply { succeeded: true }) => Ok(()),
Ok(Packet::DmaPlaybackReply { succeeded: false }) => Err("error on DMA playback request"), Ok(Packet::DmaPlaybackReply { succeeded: false }) => Err("error on DMA playback request"),
Ok(_) => Err("received unexpected aux packet during DMA playback"), Ok(_) => Err("received unexpected aux packet during DMA playback"),
Err(_) => Err("aux error on DMA playback") Err(_) => Err("aux error on DMA playback"),
} }
} }
} }
fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> { fn read_device_map(cfg: &Config) -> BTreeMap<u32, String> {

View File

@ -1,49 +1,48 @@
use libcortex_a9::cache::dcci_slice; use alloc::{collections::btree_map::BTreeMap, vec::Vec};
use libboard_artiq::pl::csr; use libboard_artiq::pl::csr;
use alloc::{vec::Vec, collections::btree_map::BTreeMap}; use libcortex_a9::cache::dcci_slice;
const ALIGNMENT: usize = 64; const ALIGNMENT: usize = 64;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum ManagerState { enum ManagerState {
Idle, Idle,
Playback Playback,
} }
pub struct RtioStatus { pub struct RtioStatus {
pub id: u32, pub id: u32,
pub error: u8, pub error: u8,
pub channel: u32, pub channel: u32,
pub timestamp: u64 pub timestamp: u64,
} }
pub enum Error { pub enum Error {
IdNotFound, IdNotFound,
PlaybackInProgress, PlaybackInProgress,
EntryNotComplete EntryNotComplete,
} }
#[derive(Debug)] #[derive(Debug)]
struct Entry { struct Entry {
trace: Vec<u8>, trace: Vec<u8>,
padding_len: usize, padding_len: usize,
complete: bool complete: bool,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Manager { pub struct Manager {
entries: BTreeMap<u32, Entry>, entries: BTreeMap<u32, Entry>,
state: ManagerState, state: ManagerState,
currentid: u32 currentid: u32,
} }
impl Manager { impl Manager {
pub fn new() -> Manager { pub fn new() -> Manager {
// in case Manager is created during a DMA in progress // in case Manager is created during a DMA in progress
// wait for it to end // wait for it to end
unsafe { unsafe { while csr::rtio_dma::enable_read() != 0 {} }
while csr::rtio_dma::enable_read() != 0 {}
}
Manager { Manager {
entries: BTreeMap::new(), entries: BTreeMap::new(),
currentid: 0, currentid: 0,
@ -57,22 +56,30 @@ impl Manager {
if entry.complete { if entry.complete {
// replace entry // replace entry
self.entries.remove(&id); self.entries.remove(&id);
self.entries.insert(id, Entry { self.entries.insert(
id,
Entry {
trace: Vec::new(), trace: Vec::new(),
padding_len: 0, padding_len: 0,
complete: false }); complete: false,
},
);
self.entries.get_mut(&id).unwrap() self.entries.get_mut(&id).unwrap()
} else { } else {
entry entry
} }
}, }
None => { None => {
self.entries.insert(id, Entry { self.entries.insert(
id,
Entry {
trace: Vec::new(), trace: Vec::new(),
padding_len: 0, padding_len: 0,
complete: false }); complete: false,
self.entries.get_mut(&id).unwrap()
}, },
);
self.entries.get_mut(&id).unwrap()
}
}; };
entry.trace.extend(&trace[0..trace_len]); entry.trace.extend(&trace[0..trace_len]);
@ -101,7 +108,7 @@ impl Manager {
pub fn erase(&mut self, id: u32) -> Result<(), Error> { pub fn erase(&mut self, id: u32) -> Result<(), Error> {
match self.entries.remove(&id) { match self.entries.remove(&id) {
Some(_) => Ok(()), Some(_) => Ok(()),
None => Err(Error::IdNotFound) None => Err(Error::IdNotFound),
} }
} }
@ -110,9 +117,11 @@ impl Manager {
return Err(Error::PlaybackInProgress); return Err(Error::PlaybackInProgress);
} }
let entry = match self.entries.get(&id){ let entry = match self.entries.get(&id) {
Some(entry) => entry, Some(entry) => entry,
None => { return Err(Error::IdNotFound); } None => {
return Err(Error::IdNotFound);
}
}; };
if !entry.complete { if !entry.complete {
return Err(Error::EntryNotComplete); return Err(Error::EntryNotComplete);
@ -156,9 +165,9 @@ impl Manager {
id: self.currentid, id: self.currentid,
error: error, error: error,
channel: channel, channel: channel,
timestamp: timestamp }); timestamp: timestamp,
});
} }
} }
} }
} }

View File

@ -20,6 +20,7 @@ extern crate alloc;
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use dma::Manager as DmaManager;
use embedded_hal::blocking::delay::DelayUs; use embedded_hal::blocking::delay::DelayUs;
#[cfg(feature = "target_kasli_soc")] #[cfg(feature = "target_kasli_soc")]
use libboard_artiq::io_expander; use libboard_artiq::io_expander;
@ -36,10 +37,9 @@ use libcortex_a9::{asm, interrupt_handler,
spin_lock_yield}; spin_lock_yield};
use libregister::{RegisterR, RegisterW}; use libregister::{RegisterR, RegisterW};
use libsupport_zynq::ram; use libsupport_zynq::ram;
use dma::Manager as DmaManager;
mod repeater;
mod dma; mod dma;
mod repeater;
fn drtiosat_reset(reset: bool) { fn drtiosat_reset(reset: bool) {
unsafe { unsafe {
@ -94,7 +94,7 @@ fn process_aux_packet(
packet: drtioaux::Packet, packet: drtioaux::Packet,
timer: &mut GlobalTimer, timer: &mut GlobalTimer,
i2c: &mut I2c, i2c: &mut I2c,
dma_manager: &mut DmaManager dma_manager: &mut DmaManager,
) -> Result<(), drtioaux::Error> { ) -> Result<(), drtioaux::Error> {
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels, // In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
// and u16 otherwise; hence the `as _` conversion. // and u16 otherwise; hence the `as _` conversion.
@ -417,31 +417,28 @@ fn process_aux_packet(
id, id,
last, last,
length, length,
trace trace,
} => { } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer); forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
let succeeded = dma_manager.add(id, last, &trace, length as usize).is_ok(); let succeeded = dma_manager.add(id, last, &trace, length as usize).is_ok();
drtioaux::send(0, drtioaux::send(0, &drtioaux::Packet::DmaAddTraceReply { succeeded: succeeded })
&drtioaux::Packet::DmaAddTraceReply { succeeded: succeeded })
} }
drtioaux::Packet::DmaRemoveTraceRequest { drtioaux::Packet::DmaRemoveTraceRequest {
destination: _destination, destination: _destination,
id id,
} => { } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer); forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
let succeeded = dma_manager.erase(id).is_ok(); let succeeded = dma_manager.erase(id).is_ok();
drtioaux::send(0, drtioaux::send(0, &drtioaux::Packet::DmaRemoveTraceReply { succeeded: succeeded })
&drtioaux::Packet::DmaRemoveTraceReply { succeeded: succeeded })
} }
drtioaux::Packet::DmaPlaybackRequest { drtioaux::Packet::DmaPlaybackRequest {
destination: _destination, destination: _destination,
id, id,
timestamp timestamp,
} => { } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer); forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
let succeeded = dma_manager.playback(id, timestamp).is_ok(); let succeeded = dma_manager.playback(id, timestamp).is_ok();
drtioaux::send(0, drtioaux::send(0, &drtioaux::Packet::DmaPlaybackReply { succeeded: succeeded })
&drtioaux::Packet::DmaPlaybackReply { succeeded: succeeded })
} }
_ => { _ => {
@ -457,7 +454,7 @@ fn process_aux_packets(
rank: &mut u8, rank: &mut u8,
timer: &mut GlobalTimer, timer: &mut GlobalTimer,
i2c: &mut I2c, i2c: &mut I2c,
dma_manager: &mut DmaManager dma_manager: &mut DmaManager,
) { ) {
let result = drtioaux::recv(0).and_then(|packet| { let result = drtioaux::recv(0).and_then(|packet| {
if let Some(packet) = packet { if let Some(packet) = packet {
@ -645,7 +642,14 @@ pub extern "C" fn main_core0() -> i32 {
while drtiosat_link_rx_up() { while drtiosat_link_rx_up() {
drtiosat_process_errors(); drtiosat_process_errors();
process_aux_packets(&mut repeaters, &mut routing_table, &mut rank, &mut timer, &mut i2c, &mut dma_manager); process_aux_packets(
&mut repeaters,
&mut routing_table,
&mut rank,
&mut timer,
&mut i2c,
&mut dma_manager,
);
#[allow(unused_mut)] #[allow(unused_mut)]
for mut rep in repeaters.iter_mut() { for mut rep in repeaters.iter_mut() {
rep.service(&routing_table, rank, &mut timer); rep.service(&routing_table, rank, &mut timer);
@ -663,14 +667,20 @@ pub extern "C" fn main_core0() -> i32 {
} }
} }
if let Some(status) = dma_manager.check_state() { if let Some(status) = dma_manager.check_state() {
info!("playback done, error: {}, channel: {}, timestamp: {}", status.error, status.channel, status.timestamp); info!(
if let Err(e) = drtioaux::send(0, &drtioaux::Packet::DmaPlaybackStatus { "playback done, error: {}, channel: {}, timestamp: {}",
status.error, status.channel, status.timestamp
);
if let Err(e) = drtioaux::send(
0,
&drtioaux::Packet::DmaPlaybackStatus {
destination: rank, destination: rank,
id: status.id, id: status.id,
error: status.error, error: status.error,
channel: status.channel, channel: status.channel,
timestamp: status.timestamp timestamp: status.timestamp,
}) { },
) {
error!("error sending DMA playback status: {:?}", e); error!("error sending DMA playback status: {:?}", e);
} }
} }