runtime: handle drtio-eem satellite disconnection #338

Merged
sb10q merged 1 commits from occheung/artiq-zynq:efc-disconnect into master 2024-11-18 14:01:21 +08:00
2 changed files with 66 additions and 12 deletions

View File

@ -185,6 +185,24 @@ unsafe fn align_comma(timer: &mut GlobalTimer) {
} }
} }
pub unsafe fn align_wordslip(timer: &mut GlobalTimer, trx_no: u8) -> bool {
pl::csr::eem_transceiver::transceiver_sel_write(trx_no);
for slip in 0..=1 {
pl::csr::eem_transceiver::wordslip_write(slip as u8);
timer.delay_us(1);
pl::csr::eem_transceiver::comma_align_reset_write(1);
timer.delay_us(100);
if pl::csr::eem_transceiver::comma_read() == 1 {
debug!("comma alignment completed with {} wordslip", slip);
return true;
}
}
false
}
pub fn init(timer: &mut GlobalTimer, cfg: &Config) { pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
for trx_no in 0..pl::csr::CONFIG_EEM_DRTIO_COUNT { for trx_no in 0..pl::csr::CONFIG_EEM_DRTIO_COUNT {
unsafe { unsafe {
@ -222,7 +240,6 @@ pub fn init(timer: &mut GlobalTimer, cfg: &Config) {
unsafe { unsafe {
align_comma(timer); align_comma(timer);
pl::csr::eem_transceiver::rx_ready_write(1);
} }
} }
} }

View File

@ -13,9 +13,13 @@ pub mod drtio {
use core::fmt; use core::fmt;
use embedded_hal::blocking::delay::DelayMs; use embedded_hal::blocking::delay::DelayMs;
#[cfg(has_drtio_eem)]
use embedded_hal::blocking::delay::DelayUs;
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};
#[cfg(has_drtio_eem)]
use libboard_artiq::drtio_eem;
use libboard_artiq::{drtioaux::Error as DrtioError, use libboard_artiq::{drtioaux::Error as DrtioError,
drtioaux_async, drtioaux_async,
drtioaux_async::Packet, drtioaux_async::Packet,
@ -26,6 +30,10 @@ 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};
#[cfg(has_drtio_eem)]
const DRTIO_EEM_LINKNOS: core::ops::Range<usize> =
(csr::DRTIO.len() - csr::CONFIG_EEM_DRTIO_COUNT as usize)..csr::DRTIO.len();
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Error { pub enum Error {
Timeout, Timeout,
@ -76,8 +84,18 @@ pub mod drtio {
}); });
} }
async fn link_rx_up(linkno: u8) -> bool { async fn link_rx_up(linkno: u8, _timer: &mut GlobalTimer) -> bool {
let linkno = linkno as usize; let linkno = linkno as usize;
#[cfg(has_drtio_eem)]
if DRTIO_EEM_LINKNOS.contains(&linkno) {
let eem_trx_no = linkno - DRTIO_EEM_LINKNOS.start;
unsafe {
csr::eem_transceiver::transceiver_sel_write(eem_trx_no as u8);
csr::eem_transceiver::comma_align_reset_write(1);
}
_timer.delay_us(100);
return unsafe { csr::eem_transceiver::comma_read() == 1 };
}
unsafe { (csr::DRTIO[linkno].rx_up_read)() == 1 } unsafe { (csr::DRTIO[linkno].rx_up_read)() == 1 }
} }
@ -152,8 +170,8 @@ pub mod drtio {
} }
} }
async fn recv_aux_timeout(linkno: u8, timeout: u64, timer: GlobalTimer) -> Result<Packet, Error> { async fn recv_aux_timeout(linkno: u8, timeout: u64, mut timer: GlobalTimer) -> Result<Packet, Error> {
if !link_rx_up(linkno).await { if !link_rx_up(linkno, &mut timer).await {
return Err(Error::LinkDown); return Err(Error::LinkDown);
} }
match drtioaux_async::recv_timeout(linkno, Some(timeout), timer).await { match drtioaux_async::recv_timeout(linkno, Some(timeout), timer).await {
@ -168,9 +186,9 @@ pub mod drtio {
linkno: u8, linkno: u8,
routing_table: &RoutingTable, routing_table: &RoutingTable,
request: &Packet, request: &Packet,
timer: GlobalTimer, mut timer: GlobalTimer,
) -> Result<Packet, Error> { ) -> Result<Packet, Error> {
if !link_rx_up(linkno).await { if !link_rx_up(linkno, &mut timer).await {
return Err(Error::LinkDown); return Err(Error::LinkDown);
} }
let _lock = aux_mutex.async_lock().await; let _lock = aux_mutex.async_lock().await;
@ -194,11 +212,11 @@ pub mod drtio {
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
linkno: u8, linkno: u8,
routing_table: &RoutingTable, routing_table: &RoutingTable,
timer: GlobalTimer, mut timer: GlobalTimer,
) -> u32 { ) -> u32 {
let mut count = 0; let mut count = 0;
loop { loop {
if !link_rx_up(linkno).await { if !link_rx_up(linkno, &mut timer).await {
return 0; return 0;
} }
count += 1; count += 1;
@ -462,7 +480,7 @@ pub mod drtio {
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &RoutingTable,
up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>, up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
timer: GlobalTimer, mut timer: GlobalTimer,
) { ) {
let mut up_links = [false; csr::DRTIO.len()]; let mut up_links = [false; csr::DRTIO.len()];
loop { loop {
@ -470,16 +488,35 @@ pub mod drtio {
let linkno = linkno as u8; let linkno = linkno as u8;
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, &mut timer).await {
process_unsolicited_aux(aux_mutex, linkno, routing_table).await; process_unsolicited_aux(aux_mutex, linkno, routing_table).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);
up_links[linkno as usize] = false; up_links[linkno as usize] = false;
#[cfg(has_drtio_eem)]
if DRTIO_EEM_LINKNOS.contains(&(linkno as usize)) {
unsafe {
csr::eem_transceiver::rx_ready_write(0);
}
while !matches!(drtioaux_async::recv(linkno).await, Ok(None)) {}
}
} }
} else { } else {
/* link was previously down */ /* link was previously down */
if link_rx_up(linkno).await { #[cfg(has_drtio_eem)]
if DRTIO_EEM_LINKNOS.contains(&(linkno as usize)) {
let eem_trx_no = linkno - DRTIO_EEM_LINKNOS.start as u8;
if !unsafe { drtio_eem::align_wordslip(&mut timer, eem_trx_no) } {
continue;
}
unsafe {
csr::eem_transceiver::rx_ready_write(1);
}
}
if link_rx_up(linkno, &mut timer).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, routing_table, timer).await; let ping_count = ping_remote(aux_mutex, linkno, routing_table, timer).await;
if ping_count > 0 { if ping_count > 0 {
@ -523,7 +560,7 @@ 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, &mut timer)) {
let reply = task::block_on(aux_transact( let reply = task::block_on(aux_transact(
&aux_mutex, &aux_mutex,
linkno, linkno,