diff --git a/artiq/firmware/libdrtioaux/lib.rs b/artiq/firmware/libdrtioaux/lib.rs index 7074d3a09..927825630 100644 --- a/artiq/firmware/libdrtioaux/lib.rs +++ b/artiq/firmware/libdrtioaux/lib.rs @@ -17,6 +17,8 @@ use proto::*; pub enum Packet { EchoRequest, EchoReply, + ResetRequest { phy: bool }, + ResetAck, RtioErrorRequest, RtioNoErrorReply, @@ -52,6 +54,10 @@ impl Packet { Ok(match read_u8(reader)? { 0x00 => Packet::EchoRequest, 0x01 => Packet::EchoReply, + 0x02 => Packet::ResetRequest { + phy: read_bool(reader)? + }, + 0x03 => Packet::ResetAck, 0x20 => Packet::RtioErrorRequest, 0x21 => Packet::RtioNoErrorReply, @@ -149,6 +155,11 @@ impl Packet { match *self { Packet::EchoRequest => write_u8(writer, 0x00)?, Packet::EchoReply => write_u8(writer, 0x01)?, + Packet::ResetRequest { phy } => { + write_u8(writer, 0x02)?; + write_bool(writer, phy)?; + }, + Packet::ResetAck => write_u8(writer, 0x03)?, Packet::RtioErrorRequest => write_u8(writer, 0x20)?, Packet::RtioNoErrorReply => write_u8(writer, 0x21)?, diff --git a/artiq/firmware/runtime/rtio_mgt.rs b/artiq/firmware/runtime/rtio_mgt.rs index bc03eac5d..f05c99d09 100644 --- a/artiq/firmware/runtime/rtio_mgt.rs +++ b/artiq/firmware/runtime/rtio_mgt.rs @@ -131,21 +131,34 @@ pub mod drtio { Err(e) => error!("[LINK#{}] aux packet error ({})", linkno, e) } } + + // FIXME: use csr::DRTIO.len(), maybe get rid of static mut as well. + static mut LINK_UP: [bool; 16] = [false; 16]; + + fn link_up(linkno: u8) -> bool { + unsafe { + LINK_UP[linkno as usize] + } + } + + fn set_link_up(linkno: u8, up: bool) { + unsafe { + LINK_UP[linkno as usize] = up + } + } pub fn link_thread(io: Io) { - let mut link_up = vec![false; csr::DRTIO.len()]; - loop { for linkno in 0..csr::DRTIO.len() { let linkno = linkno as u8; - if link_up[linkno as usize] { + if link_up(linkno) { /* link was previously up */ if link_rx_up(linkno) { process_local_errors(linkno); process_aux_errors(linkno); } else { info!("[LINK#{}] link is down", linkno); - link_up[linkno as usize] = false; + set_link_up(linkno, false); } } else { /* link was previously down */ @@ -158,7 +171,7 @@ pub mod drtio { init_buffer_space(linkno); sync_tsc(linkno); info!("[LINK#{}] link initialization completed", linkno); - link_up[linkno as usize] = true; + set_link_up(linkno, true); } else { info!("[LINK#{}] ping failed", linkno); } @@ -170,7 +183,18 @@ pub mod drtio { } pub fn init() { - // TODO: send reset commands (over aux) to every link that is up + for linkno in 0..csr::DRTIO.len() { + let linkno = linkno as u8; + if link_up(linkno) { + drtioaux::hw::send_link(linkno, + &drtioaux::Packet::ResetRequest { phy: false }).unwrap(); + match drtioaux::hw::recv_timeout_link(linkno, None) { + Ok(drtioaux::Packet::ResetAck) => (), + Ok(_) => error!("[LINK#{}] reset failed, received unexpected aux packet", linkno), + Err(e) => error!("[LINK#{}] reset failed, aux packet error ({})", linkno, e) + } + } + } } } diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 77c63f0ef..2e11ad869 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -18,11 +18,33 @@ use board_artiq::serwb; #[cfg(has_hmc830_7043)] use board_artiq::hmc830_7043; + +fn drtio_reset(reset: bool) { + unsafe { + (csr::DRTIO[0].reset_write)(if reset { 1 } else { 0 }); + } +} + +fn drtio_reset_phy(reset: bool) { + unsafe { + (csr::DRTIO[0].reset_phy_write)(if reset { 1 } else { 0 }); + } +} + fn process_aux_packet(p: &drtioaux::Packet) { // In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels, // and u16 otherwise; hence the `as _` conversion. match *p { drtioaux::Packet::EchoRequest => drtioaux::hw::send_link(0, &drtioaux::Packet::EchoReply).unwrap(), + drtioaux::Packet::ResetRequest { phy } => { + if phy { + drtio_reset_phy(true); + drtio_reset_phy(false); + } else { + drtio_reset(true); + drtio_reset(false); + } + }, drtioaux::Packet::RtioErrorRequest => { let errors; @@ -193,14 +215,6 @@ fn drtio_link_is_up() -> bool { } } -fn drtio_reset(reset: bool) { - let reset = if reset { 1 } else { 0 }; - unsafe { - (csr::DRTIO[0].reset_write)(reset); - (csr::DRTIO[0].reset_phy_write)(reset); - } -} - fn startup() { board::clock::init(); info!("ARTIQ satellite manager starting..."); @@ -225,10 +239,12 @@ fn startup() { info!("link is up, switching to recovered clock"); si5324::select_ext_input(true).expect("failed to switch clocks"); drtio_reset(false); + drtio_reset_phy(false); while drtio_link_is_up() { process_errors(); process_aux_packets(); } + drtio_reset_phy(true); drtio_reset(true); info!("link is down, switching to local crystal clock"); si5324::select_ext_input(false).expect("failed to switch clocks");