runtime: drtio aux refactoring, revert async flag

drtioaux_small_overhaul
mwojcik 2024-04-24 17:13:21 +08:00
parent 2d10503c20
commit a30c7d1f3a
6 changed files with 250 additions and 204 deletions

View File

@ -74,8 +74,8 @@ where F: FnOnce(&[u8]) -> Result<T, Error> {
let linkidx = linkno as usize; let linkidx = linkno as usize;
unsafe { unsafe {
if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 { if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 {
let cpu_ptr = (DRTIOAUX[linkidx].aux_read_pointer_read)() as usize; let read_ptr = (DRTIOAUX[linkidx].aux_read_pointer_read)() as usize;
let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2 + cpu_ptr * 0x400) as *mut u32; let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2 + read_ptr * 0x400) as *mut u32;
// work buffer to accomodate axi burst reads // work buffer to accomodate axi burst reads
// buffer at maximum proto packet size, not maximum gateware supported size // buffer at maximum proto packet size, not maximum gateware supported size
// to minimize copying time // to minimize copying time
@ -133,10 +133,9 @@ where F: FnOnce(&mut [u8]) -> Result<usize, Error> {
unsafe { unsafe {
while (DRTIOAUX[linkno].aux_tx_read)() != 0 {} while (DRTIOAUX[linkno].aux_tx_read)() != 0 {}
let ptr = DRTIOAUX_MEM[linkno].base as *mut u32; let ptr = DRTIOAUX_MEM[linkno].base as *mut u32;
let len = DRTIOAUX_MEM[linkno].size / 2;
// work buffer, works with unaligned mem access // work buffer, works with unaligned mem access
let mut buf: [u8; 1024] = [0; 1024]; let mut buf: [u8; 1024] = [0; 1024];
let len = f(&mut buf[0..len])?; let len = f(&mut buf)?;
copy_work_buffer(buf.as_mut_ptr() as *mut u32, ptr, len as isize); copy_work_buffer(buf.as_mut_ptr() as *mut u32, ptr, len as isize);
(DRTIOAUX[linkno].aux_tx_length_write)(len as u16); (DRTIOAUX[linkno].aux_tx_length_write)(len as u16);
(DRTIOAUX[linkno].aux_tx_write)(1); (DRTIOAUX[linkno].aux_tx_write)(1);

View File

@ -38,8 +38,8 @@ where F: FnOnce(&[u8]) -> Result<T, Error> {
let linkidx = linkno as usize; let linkidx = linkno as usize;
unsafe { unsafe {
if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 { if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 {
let cpu_ptr = (DRTIOAUX[linkidx].aux_read_pointer_read)() as usize; let read_ptr = (DRTIOAUX[linkidx].aux_read_pointer_read)() as usize;
let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2 + cpu_ptr * 0x400) as *mut u32; let ptr = (DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2 + read_ptr * 0x400) as *mut u32;
// work buffer to accomodate axi burst reads // work buffer to accomodate axi burst reads
// buffer at maximum proto packet size, not maximum gateware supported size // buffer at maximum proto packet size, not maximum gateware supported size
// to minimize required copying time // to minimize required copying time
@ -106,10 +106,9 @@ where F: FnOnce(&mut [u8]) -> Result<usize, Error> {
unsafe { unsafe {
let _ = block_async!(tx_ready(linkno)).await; let _ = block_async!(tx_ready(linkno)).await;
let ptr = DRTIOAUX_MEM[linkno].base as *mut u32; let ptr = DRTIOAUX_MEM[linkno].base as *mut u32;
let len = DRTIOAUX_MEM[linkno].size / 2;
// work buffer, works with unaligned mem access // work buffer, works with unaligned mem access
let mut buf: [u8; 1024] = [0; 1024]; let mut buf: [u8; 1024] = [0; 1024];
let len = f(&mut buf[0..len])?; let len = f(&mut buf)?;
copy_work_buffer(buf.as_mut_ptr() as *mut u32, ptr, len as isize); copy_work_buffer(buf.as_mut_ptr() as *mut u32, ptr, len as isize);
(DRTIOAUX[linkno].aux_tx_length_write)(len as u16); (DRTIOAUX[linkno].aux_tx_length_write)(len as u16);
(DRTIOAUX[linkno].aux_tx_write)(1); (DRTIOAUX[linkno].aux_tx_write)(1);

View File

@ -60,7 +60,7 @@ pub mod remote_analyzer {
routing_table: &drtio_routing::RoutingTable, routing_table: &drtio_routing::RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer, timer: GlobalTimer,
) -> Result<RemoteBuffer, &'static str> { ) -> Result<RemoteBuffer, drtio::Error> {
// gets data from satellites and returns consolidated data // gets data from satellites and returns consolidated data
let mut remote_data: Vec<u8> = Vec::new(); let mut remote_data: Vec<u8> = Vec::new();
let mut remote_error = false; let mut remote_error = false;

View File

@ -58,10 +58,11 @@ mod remote_moninj {
use log::error; use log::error;
use super::*; use super::*;
use crate::rtio_mgt::drtio; use crate::rtio_mgt::{drtio, drtio::Error as DrtioError};
pub async fn read_probe( pub async fn read_probe(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -71,6 +72,7 @@ mod remote_moninj {
let reply = drtio::aux_transact( let reply = drtio::aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&drtioaux_async::Packet::MonitorRequest { &drtioaux_async::Packet::MonitorRequest {
destination: destination, destination: destination,
channel: channel as _, channel: channel as _,
@ -82,8 +84,8 @@ mod remote_moninj {
match reply { match reply {
Ok(drtioaux_async::Packet::MonitorReply { value }) => return value as i64, Ok(drtioaux_async::Packet::MonitorReply { value }) => return value as i64,
Ok(packet) => error!("received unexpected aux packet: {:?}", packet), Ok(packet) => error!("received unexpected aux packet: {:?}", packet),
Err("link went down") => { Err(DrtioError::LinkDown) => {
debug!("link is down"); warn!("link is down");
} }
Err(e) => error!("aux packet error ({})", e), Err(e) => error!("aux packet error ({})", e),
} }
@ -92,6 +94,7 @@ mod remote_moninj {
pub async fn inject( pub async fn inject(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
_routing_table: &drtio_routing::RoutingTable,
_timer: GlobalTimer, _timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -115,6 +118,7 @@ mod remote_moninj {
pub async fn read_injection_status( pub async fn read_injection_status(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -124,6 +128,7 @@ mod remote_moninj {
let reply = drtio::aux_transact( let reply = drtio::aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&drtioaux_async::Packet::InjectionStatusRequest { &drtioaux_async::Packet::InjectionStatusRequest {
destination: destination, destination: destination,
channel: channel as _, channel: channel as _,
@ -135,8 +140,8 @@ mod remote_moninj {
match reply { match reply {
Ok(drtioaux_async::Packet::InjectionStatusReply { value }) => return value as i8, Ok(drtioaux_async::Packet::InjectionStatusReply { value }) => return value as i8,
Ok(packet) => error!("received unexpected aux packet: {:?}", packet), Ok(packet) => error!("received unexpected aux packet: {:?}", packet),
Err("link went down") => { Err(DrtioError::LinkDown) => {
debug!("link is down"); warn!("link is down");
} }
Err(e) => error!("aux packet error ({})", e), Err(e) => error!("aux packet error ({})", e),
} }
@ -183,7 +188,7 @@ macro_rules! dispatch {
local_moninj::$func(channel.into(), $($param, )*) local_moninj::$func(channel.into(), $($param, )*)
} else { } else {
let linkno = hop - 1 as u8; let linkno = hop - 1 as u8;
remote_moninj::$func($aux_mutex, $timer, linkno, destination, channel, $($param, )*).await remote_moninj::$func($aux_mutex, $routing_table, $timer, linkno, destination, channel, $($param, )*).await
} }
}} }}
} }

View File

@ -1,19 +1,20 @@
use alloc::rc::Rc; use alloc::rc::Rc;
use core::cell::RefCell; use core::cell::RefCell;
use libboard_artiq::{drtio_routing, pl::csr}; use libboard_artiq::{drtio_routing, drtio_routing::RoutingTable, pl::csr};
use libboard_zynq::timer::GlobalTimer; use libboard_zynq::timer::GlobalTimer;
use libcortex_a9::mutex::Mutex; use libcortex_a9::mutex::Mutex;
#[cfg(has_drtio)] #[cfg(has_drtio)]
pub mod drtio { pub mod drtio {
use alloc::vec::Vec; use alloc::vec::Vec;
use core::fmt;
use embedded_hal::blocking::delay::DelayMs; use embedded_hal::blocking::delay::DelayMs;
use ksupport::{resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR, use ksupport::{resolve_channel_name, ASYNC_ERROR_BUSY, ASYNC_ERROR_COLLISION, ASYNC_ERROR_SEQUENCE_ERROR,
SEEN_ASYNC_ERRORS}; SEEN_ASYNC_ERRORS};
use libasync::{delay, task}; use libasync::{delay, task};
use libboard_artiq::{drtioaux::Error, use libboard_artiq::{drtioaux::Error as DrtioError,
drtioaux_async, drtioaux_async,
drtioaux_async::Packet, drtioaux_async::Packet,
drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE}}; drtioaux_proto::{PayloadStatus, MASTER_PAYLOAD_MAX_SIZE}};
@ -23,9 +24,44 @@ pub mod drtio {
use super::*; use super::*;
use crate::{analyzer::remote_analyzer::RemoteBuffer, rtio_dma::remote_dma, subkernel}; use crate::{analyzer::remote_analyzer::RemoteBuffer, rtio_dma::remote_dma, subkernel};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Error {
Timeout,
AuxError,
LinkDown,
UnexpectedReply,
DmaAddTraceFail(u8),
DmaEraseFail(u8),
DmaPlaybackFail(u8),
SubkernelAddFail(u8),
SubkernelRunFail(u8),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Timeout => write!(f, "timed out"),
Error::AuxError => write!(f, "aux packet error"),
Error::LinkDown => write!(f, "link down"),
Error::UnexpectedReply => write!(f, "unexpected reply"),
Error::DmaAddTraceFail(dest) => write!(f, "error adding DMA trace on satellite #{}", dest),
Error::DmaEraseFail(dest) => write!(f, "error erasing DMA trace on satellite #{}", dest),
Error::DmaPlaybackFail(dest) => write!(f, "error playing back DMA trace on satellite #{}", dest),
Error::SubkernelAddFail(dest) => write!(f, "error adding subkernel on satellite #{}", dest),
Error::SubkernelRunFail(dest) => write!(f, "error on subkernel run request on satellite #{}", dest),
}
}
}
impl From<DrtioError> for Error {
fn from(_error: DrtioError) -> Self {
Error::AuxError
}
}
pub fn startup( pub fn startup(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>, routing_table: &Rc<RefCell<RoutingTable>>,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer, timer: GlobalTimer,
) { ) {
@ -43,128 +79,104 @@ pub mod drtio {
unsafe { (csr::DRTIO[linkno].rx_up_read)() == 1 } unsafe { (csr::DRTIO[linkno].rx_up_read)() == 1 }
} }
async fn link_has_async_ready(linkno: u8) -> bool { async fn process_async_packets(linkno: u8, routing_table: &RoutingTable, packet: Packet) -> Option<Packet> {
let linkno = linkno as usize; match packet {
let async_ready; Packet::DmaPlaybackStatus {
unsafe { id,
async_ready = (csr::DRTIO[linkno].async_messages_ready_read)() == 1; source,
(csr::DRTIO[linkno].async_messages_ready_write)(1); destination: 0,
} error,
async_ready channel,
} timestamp,
} => {
async fn process_async_packets( remote_dma::playback_done(id, source, error, channel, timestamp).await;
aux_mutex: &Mutex<bool>, None
linkno: u8, }
routing_table: &drtio_routing::RoutingTable, Packet::SubkernelFinished {
timer: GlobalTimer, id,
) { destination: 0,
if link_has_async_ready(linkno).await { with_exception,
loop { exception_src,
let reply = aux_transact(aux_mutex, linkno, &Packet::RoutingRetrievePackets, timer).await; } => {
if let Ok(packet) = reply { subkernel::subkernel_finished(id, with_exception, exception_src).await;
match packet { None
Packet::DmaPlaybackStatus { }
id, Packet::SubkernelMessage {
source, id,
destination: 0, source,
error, destination: 0,
channel, status,
timestamp, length,
} => { data,
remote_dma::playback_done(id, source, error, channel, timestamp).await; } => {
} subkernel::message_handle_incoming(id, status, length as usize, &data).await;
Packet::SubkernelFinished { // acknowledge receiving part of the message
id, drtioaux_async::send(linkno, &Packet::SubkernelMessageAck { destination: source })
destination: 0, .await
with_exception, .unwrap();
exception_src, None
} => { }
subkernel::subkernel_finished(id, with_exception, exception_src).await; // routable packets
} Packet::DmaAddTraceRequest { destination, .. }
Packet::SubkernelMessage { | Packet::DmaAddTraceReply { destination, .. }
id, | Packet::DmaRemoveTraceRequest { destination, .. }
source, | Packet::DmaRemoveTraceReply { destination, .. }
destination: 0, | Packet::DmaPlaybackRequest { destination, .. }
status, | Packet::DmaPlaybackReply { destination, .. }
length, | Packet::SubkernelLoadRunRequest { destination, .. }
data, | Packet::SubkernelLoadRunReply { destination, .. }
} => { | Packet::SubkernelMessage { destination, .. }
subkernel::message_handle_incoming(id, status, length as usize, &data).await; | Packet::SubkernelMessageAck { destination, .. }
// acknowledge receiving part of the message | Packet::DmaPlaybackStatus { destination, .. }
let _lock = aux_mutex.async_lock().await; | Packet::SubkernelFinished { destination, .. } => {
drtioaux_async::send(linkno, &Packet::SubkernelMessageAck { destination: source }) if destination == 0 {
.await Some(packet)
.unwrap();
let mut countdown = timer.countdown();
// give the satellites some time to process
delay(&mut countdown, Milliseconds(10)).await;
}
// routable packets
Packet::DmaAddTraceRequest { destination, .. }
| Packet::DmaAddTraceReply { destination, .. }
| Packet::DmaRemoveTraceRequest { destination, .. }
| Packet::DmaRemoveTraceReply { destination, .. }
| Packet::DmaPlaybackRequest { destination, .. }
| Packet::DmaPlaybackReply { destination, .. }
| Packet::SubkernelLoadRunRequest { destination, .. }
| Packet::SubkernelLoadRunReply { destination, .. }
| Packet::SubkernelMessage { destination, .. }
| Packet::SubkernelMessageAck { destination, .. }
| Packet::DmaPlaybackStatus { destination, .. }
| Packet::SubkernelFinished { destination, .. } => {
let dest_link = routing_table.0[destination as usize][0] - 1;
if dest_link == linkno {
warn!(
"[LINK#{}] Re-routed packet would return to the same link, dropping: {:?}",
linkno, packet
);
} else if destination == 0 {
warn!("[LINK#{}] Received invalid routable packet: {:?}", linkno, packet)
} else {
drtioaux_async::send(dest_link, &packet).await.unwrap();
}
}
Packet::RoutingNoPackets => break,
other => warn!("[LINK#{}] Received an unroutable packet: {:?}", linkno, other),
}
} else { } else {
warn!( let dest_link = routing_table.0[destination as usize][0] - 1;
"[LINK#{}] Error handling async packets ({})", if dest_link == linkno {
linkno, warn!(
reply.unwrap_err() "[LINK#{}] Re-routed packet would return to the same link, dropping: {:?}",
); linkno, packet
return; );
} else {
drtioaux_async::send(dest_link, &packet).await.unwrap();
}
None
} }
} }
other => Some(other),
} }
} }
async fn recv_aux_timeout(linkno: u8, timeout: u64, timer: GlobalTimer) -> Result<Packet, &'static str> { async fn recv_aux_timeout(linkno: u8, timeout: u64, timer: GlobalTimer) -> Result<Packet, Error> {
if !link_rx_up(linkno).await { if !link_rx_up(linkno).await {
return Err("link went down"); return Err(Error::LinkDown);
} }
match drtioaux_async::recv_timeout(linkno, Some(timeout), timer).await { match drtioaux_async::recv_timeout(linkno, Some(timeout), timer).await {
Ok(packet) => return Ok(packet), Ok(packet) => return Ok(packet),
Err(Error::TimedOut) => return Err("timed out"), Err(DrtioError::TimedOut) => return Err(Error::Timeout),
Err(_) => return Err("aux packet error"), Err(_) => return Err(Error::AuxError),
} }
} }
pub async fn aux_transact( pub async fn aux_transact(
aux_mutex: &Mutex<bool>, aux_mutex: &Mutex<bool>,
linkno: u8, linkno: u8,
routing_table: &RoutingTable,
request: &Packet, request: &Packet,
timer: GlobalTimer, timer: GlobalTimer,
) -> Result<Packet, &'static str> { ) -> Result<Packet, Error> {
if !link_rx_up(linkno).await { if !link_rx_up(linkno).await {
return Err("link went down"); return Err(Error::LinkDown);
} }
let _lock = aux_mutex.async_lock().await; let _lock = aux_mutex.async_lock().await;
drtioaux_async::send(linkno, request).await.unwrap(); drtioaux_async::send(linkno, request).await.unwrap();
Ok(recv_aux_timeout(linkno, 200, timer).await?) loop {
let packet = recv_aux_timeout(linkno, 200, timer).await?;
if let Some(packet) = process_async_packets(linkno, routing_table, packet).await {
return Ok(packet);
}
}
} }
async fn drain_buffer(linkno: u8, draining_time: Milliseconds, timer: GlobalTimer) { async fn drain_buffer(linkno: u8, draining_time: Milliseconds, timer: GlobalTimer) {
@ -172,12 +184,17 @@ pub mod drtio {
loop { loop {
if timer.get_time() > max_time { if timer.get_time() > max_time {
return; return;
} //could this be cut short? }
let _ = drtioaux_async::recv(linkno).await; let _ = drtioaux_async::recv(linkno).await;
} }
} }
async fn ping_remote(aux_mutex: &Rc<Mutex<bool>>, linkno: u8, timer: GlobalTimer) -> u32 { async fn ping_remote(
aux_mutex: &Rc<Mutex<bool>>,
linkno: u8,
routing_table: &RoutingTable,
timer: GlobalTimer,
) -> u32 {
let mut count = 0; let mut count = 0;
loop { loop {
if !link_rx_up(linkno).await { if !link_rx_up(linkno).await {
@ -187,7 +204,7 @@ pub mod drtio {
if count > 100 { if count > 100 {
return 0; return 0;
} }
let reply = aux_transact(aux_mutex, linkno, &Packet::EchoRequest, timer).await; let reply = aux_transact(aux_mutex, linkno, routing_table, &Packet::EchoRequest, timer).await;
match reply { match reply {
Ok(Packet::EchoReply) => { Ok(Packet::EchoReply) => {
// make sure receive buffer is drained // make sure receive buffer is drained
@ -200,7 +217,7 @@ pub mod drtio {
} }
} }
async fn sync_tsc(aux_mutex: &Rc<Mutex<bool>>, linkno: u8, timer: GlobalTimer) -> Result<(), &'static str> { async fn sync_tsc(aux_mutex: &Rc<Mutex<bool>>, linkno: u8, timer: GlobalTimer) -> Result<(), Error> {
let _lock = aux_mutex.async_lock().await; let _lock = aux_mutex.async_lock().await;
unsafe { unsafe {
@ -211,22 +228,23 @@ pub mod drtio {
// by the satellite, in response to a TSC set on the RT link. // by the satellite, in response to a TSC set on the RT link.
let reply = recv_aux_timeout(linkno, 10000, timer).await?; let reply = recv_aux_timeout(linkno, 10000, timer).await?;
if reply == Packet::TSCAck { if reply == Packet::TSCAck {
return Ok(()); Ok(())
} else { } else {
return Err("unexpected reply"); Err(Error::UnexpectedReply)
} }
} }
async fn load_routing_table( async fn load_routing_table(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
linkno: u8, linkno: u8,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
) -> Result<(), &'static str> { ) -> Result<(), Error> {
for i in 0..drtio_routing::DEST_COUNT { for i in 0..drtio_routing::DEST_COUNT {
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::RoutingSetPath { &Packet::RoutingSetPath {
destination: i as u8, destination: i as u8,
hops: routing_table.0[i], hops: routing_table.0[i],
@ -235,7 +253,7 @@ pub mod drtio {
) )
.await?; .await?;
if reply != Packet::RoutingAck { if reply != Packet::RoutingAck {
return Err("unexpected reply"); return Err(Error::UnexpectedReply);
} }
} }
Ok(()) Ok(())
@ -245,13 +263,21 @@ pub mod drtio {
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
linkno: u8, linkno: u8,
rank: u8, rank: u8,
routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
) -> Result<(), &'static str> { ) -> Result<(), Error> {
let reply = aux_transact(aux_mutex, linkno, &Packet::RoutingSetRank { rank: rank }, timer).await?; let reply = aux_transact(
if reply != Packet::RoutingAck { aux_mutex,
return Err("unexpected reply"); linkno,
routing_table,
&Packet::RoutingSetRank { rank: rank },
timer,
)
.await?;
match reply {
Packet::RoutingAck => Ok(()),
_ => Err(Error::UnexpectedReply),
} }
Ok(())
} }
async fn init_buffer_space(destination: u8, linkno: u8) { async fn init_buffer_space(destination: u8, linkno: u8) {
@ -270,10 +296,14 @@ pub mod drtio {
} }
} }
async fn process_unsolicited_aux(aux_mutex: &Rc<Mutex<bool>>, linkno: u8) { async fn process_unsolicited_aux(aux_mutex: &Mutex<bool>, linkno: u8, routing_table: &RoutingTable) {
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)) => warn!("[LINK#{}] unsolicited aux packet: {:?}", linkno, packet), Ok(Some(packet)) => {
if let Some(packet) = process_async_packets(linkno, routing_table, packet).await {
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),
} }
@ -301,7 +331,7 @@ pub mod drtio {
} }
async fn destination_set_up( async fn destination_set_up(
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
destination: u8, destination: u8,
up: bool, up: bool,
@ -324,7 +354,7 @@ pub mod drtio {
async fn destination_survey( async fn destination_survey(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
up_links: &[bool], up_links: &[bool],
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer, timer: GlobalTimer,
@ -345,6 +375,7 @@ pub mod drtio {
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::DestinationStatusRequest { &Packet::DestinationStatusRequest {
destination: destination, destination: destination,
}, },
@ -400,6 +431,7 @@ pub mod drtio {
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::DestinationStatusRequest { &Packet::DestinationStatusRequest {
destination: destination, destination: destination,
}, },
@ -427,7 +459,7 @@ pub mod drtio {
pub async fn link_task( pub async fn link_task(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer, timer: GlobalTimer,
) { ) {
@ -438,8 +470,7 @@ pub mod drtio {
if up_links[linkno as usize] { if up_links[linkno as usize] {
/* link was previously up */ /* link was previously up */
if link_rx_up(linkno).await { if link_rx_up(linkno).await {
process_async_packets(aux_mutex, linkno, routing_table, timer).await; process_unsolicited_aux(aux_mutex, linkno, routing_table).await;
process_unsolicited_aux(aux_mutex, linkno).await;
process_local_errors(linkno).await; process_local_errors(linkno).await;
} else { } else {
info!("[LINK#{}] link is down", linkno); info!("[LINK#{}] link is down", linkno);
@ -449,7 +480,7 @@ pub mod drtio {
/* link was previously down */ /* link was previously down */
if link_rx_up(linkno).await { if link_rx_up(linkno).await {
info!("[LINK#{}] link RX became up, pinging", linkno); info!("[LINK#{}] link RX became up, pinging", linkno);
let ping_count = ping_remote(aux_mutex, linkno, timer).await; let ping_count = ping_remote(aux_mutex, linkno, routing_table, timer).await;
if ping_count > 0 { if ping_count > 0 {
info!("[LINK#{}] remote replied after {} packets", linkno, ping_count); info!("[LINK#{}] remote replied after {} packets", linkno, ping_count);
up_links[linkno as usize] = true; up_links[linkno as usize] = true;
@ -459,7 +490,7 @@ pub mod drtio {
if let Err(e) = load_routing_table(aux_mutex, linkno, routing_table, timer).await { if let Err(e) = load_routing_table(aux_mutex, linkno, routing_table, timer).await {
error!("[LINK#{}] failed to load routing table ({})", linkno, e); error!("[LINK#{}] failed to load routing table ({})", linkno, e);
} }
if let Err(e) = set_rank(aux_mutex, linkno, 1 as u8, timer).await { if let Err(e) = set_rank(aux_mutex, linkno, 1 as u8, routing_table, timer).await {
error!("[LINK#{}] failed to set rank ({})", linkno, e); error!("[LINK#{}] failed to set rank ({})", linkno, e);
} }
info!("[LINK#{}] link initialization completed", linkno); info!("[LINK#{}] link initialization completed", linkno);
@ -476,7 +507,7 @@ pub mod drtio {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn reset(aux_mutex: Rc<Mutex<bool>>, mut timer: GlobalTimer) { pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, mut timer: GlobalTimer) {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
unsafe { unsafe {
(csr::DRTIO[linkno].reset_write)(1); (csr::DRTIO[linkno].reset_write)(1);
@ -492,7 +523,13 @@ pub mod drtio {
for linkno in 0..csr::DRTIO.len() { for linkno in 0..csr::DRTIO.len() {
let linkno = linkno as u8; let linkno = linkno as u8;
if task::block_on(link_rx_up(linkno)) { if task::block_on(link_rx_up(linkno)) {
let reply = task::block_on(aux_transact(&aux_mutex, linkno, &Packet::ResetRequest, timer)); let reply = task::block_on(aux_transact(
&aux_mutex,
linkno,
routing_table,
&Packet::ResetRequest,
timer,
));
match reply { match reply {
Ok(Packet::ResetAck) => (), Ok(Packet::ResetAck) => (),
Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno), Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno),
@ -505,14 +542,15 @@ pub mod drtio {
async fn partition_data<PacketF, HandlerF>( async fn partition_data<PacketF, HandlerF>(
linkno: u8, linkno: u8,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
data: &[u8], data: &[u8],
packet_f: PacketF, packet_f: PacketF,
reply_handler_f: HandlerF, reply_handler_f: HandlerF,
) -> Result<(), &'static str> ) -> Result<(), Error>
where where
PacketF: Fn(&[u8; MASTER_PAYLOAD_MAX_SIZE], PayloadStatus, usize) -> Packet, PacketF: Fn(&[u8; MASTER_PAYLOAD_MAX_SIZE], PayloadStatus, usize) -> Packet,
HandlerF: Fn(&Packet) -> Result<(), &'static str>, HandlerF: Fn(&Packet) -> Result<(), Error>,
{ {
let mut i = 0; let mut i = 0;
while i < data.len() { while i < data.len() {
@ -528,7 +566,7 @@ pub mod drtio {
i += len; i += len;
let status = PayloadStatus::from_status(first, last); let status = PayloadStatus::from_status(first, last);
let packet = packet_f(&slice, status, len); let packet = packet_f(&slice, status, len);
let reply = aux_transact(aux_mutex, linkno, &packet, timer).await?; let reply = aux_transact(aux_mutex, linkno, routing_table, &packet, timer).await?;
reply_handler_f(&reply)?; reply_handler_f(&reply)?;
} }
Ok(()) Ok(())
@ -536,16 +574,17 @@ pub mod drtio {
pub async fn ddma_upload_trace( pub async fn ddma_upload_trace(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
trace: &Vec<u8>, trace: &Vec<u8>,
) -> Result<(), &'static str> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
partition_data( partition_data(
linkno, linkno,
aux_mutex, aux_mutex,
routing_table,
timer, timer,
trace, trace,
|slice, status, len| Packet::DmaAddTraceRequest { |slice, status, len| Packet::DmaAddTraceRequest {
@ -566,8 +605,8 @@ pub mod drtio {
destination: 0, destination: 0,
succeeded: false, succeeded: false,
.. ..
} => Err("error adding trace on satellite"), } => Err(Error::DmaAddTraceFail(destination)),
_ => Err("adding DMA trace failed, unexpected aux packet"), _ => Err(Error::UnexpectedReply),
}, },
) )
.await .await
@ -575,15 +614,16 @@ pub mod drtio {
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: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
) -> Result<(), &'static str> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::DmaRemoveTraceRequest { &Packet::DmaRemoveTraceRequest {
id: id, id: id,
source: 0, source: 0,
@ -591,33 +631,33 @@ pub mod drtio {
}, },
timer, timer,
) )
.await; .await?;
match reply { match reply {
Ok(Packet::DmaRemoveTraceReply { Packet::DmaRemoveTraceReply {
destination: 0, destination: 0,
succeeded: true, succeeded: true,
}) => Ok(()), } => Ok(()),
Ok(Packet::DmaRemoveTraceReply { Packet::DmaRemoveTraceReply {
destination: 0, destination: 0,
succeeded: false, succeeded: false,
}) => Err("satellite DMA erase error"), } => Err(Error::DmaEraseFail(destination)),
Ok(_) => Err("adding trace failed, unexpected aux packet"), _ => Err(Error::UnexpectedReply),
Err(_) => Err("erasing trace failed, aux error"),
} }
} }
pub async fn ddma_send_playback( pub async fn ddma_send_playback(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
timestamp: u64, timestamp: u64,
) -> Result<(), &'static str> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::DmaPlaybackRequest { &Packet::DmaPlaybackRequest {
id: id, id: id,
source: 0, source: 0,
@ -626,45 +666,44 @@ pub mod drtio {
}, },
timer, timer,
) )
.await; .await?;
match reply { match reply {
Ok(Packet::DmaPlaybackReply { Packet::DmaPlaybackReply {
destination: 0, destination: 0,
succeeded: true, succeeded: true,
}) => Ok(()), } => Ok(()),
Ok(Packet::DmaPlaybackReply { Packet::DmaPlaybackReply {
destination: 0, destination: 0,
succeeded: false, succeeded: false,
}) => Err("error on DMA playback request"), } => Err(Error::DmaPlaybackFail(destination)),
Ok(_) => Err("received unexpected aux packet during DMA playback"), _ => Err(Error::UnexpectedReply),
Err(_) => Err("aux error on DMA playback"),
} }
} }
async fn analyzer_get_data( async fn analyzer_get_data(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
destination: u8, destination: u8,
) -> Result<RemoteBuffer, &'static str> { ) -> Result<RemoteBuffer, Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::AnalyzerHeaderRequest { &Packet::AnalyzerHeaderRequest {
destination: destination, destination: destination,
}, },
timer, timer,
) )
.await; .await?;
let (sent, total, overflow) = match reply { let (sent, total, overflow) = match reply {
Ok(Packet::AnalyzerHeader { Packet::AnalyzerHeader {
sent_bytes, sent_bytes,
total_byte_count, total_byte_count,
overflow_occurred, overflow_occurred,
}) => (sent_bytes, total_byte_count, overflow_occurred), } => (sent_bytes, total_byte_count, overflow_occurred),
Ok(_) => return Err("received unexpected aux packet during remote analyzer header request"), _ => return Err(Error::UnexpectedReply),
Err(e) => return Err(e),
}; };
let mut remote_data: Vec<u8> = Vec::new(); let mut remote_data: Vec<u8> = Vec::new();
@ -674,19 +713,19 @@ pub mod drtio {
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::AnalyzerDataRequest { &Packet::AnalyzerDataRequest {
destination: destination, destination: destination,
}, },
timer, timer,
) )
.await; .await?;
match reply { match reply {
Ok(Packet::AnalyzerData { last, length, data }) => { Packet::AnalyzerData { last, length, data } => {
last_packet = last; last_packet = last;
remote_data.extend(&data[0..length as usize]); remote_data.extend(&data[0..length as usize]);
} }
Ok(_) => return Err("received unexpected aux packet during remote analyzer data request"), _ => return Err(Error::UnexpectedReply),
Err(e) => return Err(e),
} }
} }
} }
@ -701,10 +740,10 @@ pub mod drtio {
pub async fn analyzer_query( pub async fn analyzer_query(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer, timer: GlobalTimer,
) -> Result<Vec<RemoteBuffer>, &'static str> { ) -> Result<Vec<RemoteBuffer>, Error> {
let mut remote_buffers: Vec<RemoteBuffer> = Vec::new(); let mut remote_buffers: Vec<RemoteBuffer> = Vec::new();
for i in 1..drtio_routing::DEST_COUNT { for i in 1..drtio_routing::DEST_COUNT {
if destination_up(up_destinations, i as u8).await { if destination_up(up_destinations, i as u8).await {
@ -716,16 +755,17 @@ pub mod drtio {
pub async fn subkernel_upload( pub async fn subkernel_upload(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
data: &Vec<u8>, data: &Vec<u8>,
) -> Result<(), &'static str> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
partition_data( partition_data(
linkno, linkno,
aux_mutex, aux_mutex,
routing_table,
timer, timer,
data, data,
|slice, status, len| Packet::SubkernelAddDataRequest { |slice, status, len| Packet::SubkernelAddDataRequest {
@ -737,8 +777,8 @@ pub mod drtio {
}, },
|reply| match reply { |reply| match reply {
Packet::SubkernelAddDataReply { succeeded: true } => Ok(()), Packet::SubkernelAddDataReply { succeeded: true } => Ok(()),
Packet::SubkernelAddDataReply { succeeded: false } => Err("error adding subkernel on satellite"), Packet::SubkernelAddDataReply { succeeded: false } => Err(Error::SubkernelAddFail(destination)),
_ => Err("adding subkernel failed, unexpected aux packet"), _ => Err(Error::UnexpectedReply),
}, },
) )
.await .await
@ -746,16 +786,17 @@ pub mod drtio {
pub async fn subkernel_load( pub async fn subkernel_load(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
run: bool, run: bool,
) -> Result<(), &'static str> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::SubkernelLoadRunRequest { &Packet::SubkernelLoadRunRequest {
id: id, id: id,
source: 0, source: 0,
@ -773,23 +814,24 @@ pub mod drtio {
Packet::SubkernelLoadRunReply { Packet::SubkernelLoadRunReply {
destination: 0, destination: 0,
succeeded: false, succeeded: false,
} => return Err("error on subkernel run request"), } => return Err(Error::SubkernelRunFail(destination)),
_ => return Err("received unexpected aux packet during subkernel run"), _ => Err(Error::UnexpectedReply),
} }
} }
pub async fn subkernel_retrieve_exception( pub async fn subkernel_retrieve_exception(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
destination: u8, destination: u8,
) -> Result<Vec<u8>, &'static str> { ) -> Result<Vec<u8>, Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
let mut remote_data: Vec<u8> = Vec::new(); let mut remote_data: Vec<u8> = Vec::new();
loop { loop {
let reply = aux_transact( let reply = aux_transact(
aux_mutex, aux_mutex,
linkno, linkno,
routing_table,
&Packet::SubkernelExceptionRequest { &Packet::SubkernelExceptionRequest {
destination: destination, destination: destination,
}, },
@ -803,23 +845,24 @@ pub mod drtio {
return Ok(remote_data); return Ok(remote_data);
} }
} }
_ => return Err("received unexpected aux packet during subkernel exception request"), _ => return Err(Error::UnexpectedReply),
} }
} }
} }
pub async fn subkernel_send_message( pub async fn subkernel_send_message(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
id: u32, id: u32,
destination: u8, destination: u8,
message: &[u8], message: &[u8],
) -> Result<(), &'static str> { ) -> Result<(), Error> {
let linkno = routing_table.0[destination as usize][0] - 1; let linkno = routing_table.0[destination as usize][0] - 1;
partition_data( partition_data(
linkno, linkno,
aux_mutex, aux_mutex,
routing_table,
timer, timer,
message, message,
|slice, status, len| Packet::SubkernelMessage { |slice, status, len| Packet::SubkernelMessage {
@ -832,7 +875,7 @@ pub mod drtio {
}, },
|reply| match reply { |reply| match reply {
Packet::SubkernelMessageAck { .. } => Ok(()), Packet::SubkernelMessageAck { .. } => Ok(()),
_ => Err("sending message to subkernel failed, unexpected aux packet"), _ => Err(Error::UnexpectedReply),
}, },
) )
.await .await
@ -845,19 +888,19 @@ pub mod drtio {
pub fn startup( pub fn startup(
_aux_mutex: &Rc<Mutex<bool>>, _aux_mutex: &Rc<Mutex<bool>>,
_routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>, _routing_table: &Rc<RefCell<RoutingTable>>,
_up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, _up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
_timer: GlobalTimer, _timer: GlobalTimer,
) { ) {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn reset(_aux_mutex: Rc<Mutex<bool>>, mut _timer: GlobalTimer) {} pub fn reset(_aux_mutex: Rc<Mutex<bool>>, _routing_table: &RoutingTable, mut _timer: GlobalTimer) {}
} }
pub fn startup( pub fn startup(
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &Rc<RefCell<drtio_routing::RoutingTable>>, routing_table: &Rc<RefCell<RoutingTable>>,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer, timer: GlobalTimer,
) { ) {
@ -868,9 +911,9 @@ pub fn startup(
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn reset(aux_mutex: Rc<Mutex<bool>>, timer: GlobalTimer) { pub fn reset(aux_mutex: Rc<Mutex<bool>>, routing_table: &RoutingTable, timer: GlobalTimer) {
unsafe { unsafe {
csr::rtio_core::reset_write(1); csr::rtio_core::reset_write(1);
} }
drtio::reset(aux_mutex, timer) drtio::reset(aux_mutex, routing_table, timer)
} }

View File

@ -7,7 +7,7 @@ use libboard_zynq::{time::Milliseconds, timer::GlobalTimer};
use libcortex_a9::mutex::Mutex; use libcortex_a9::mutex::Mutex;
use log::{error, warn}; use log::{error, warn};
use crate::rtio_mgt::drtio; use crate::rtio_mgt::{drtio, drtio::Error as DrtioError};
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
pub enum FinishStatus { pub enum FinishStatus {
@ -31,11 +31,11 @@ pub enum Error {
SubkernelNotFound, SubkernelNotFound,
SubkernelException, SubkernelException,
CommLost, CommLost,
DrtioError(&'static str), DrtioError(DrtioError),
} }
impl From<&'static str> for Error { impl From<DrtioError> for Error {
fn from(value: &'static str) -> Error { fn from(value: DrtioError) -> Error {
Error::DrtioError(value) Error::DrtioError(value)
} }
} }