forked from M-Labs/artiq
drtio: support remote RTIO resets
This commit is contained in:
parent
f15b4bdde7
commit
738654c783
|
@ -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)?,
|
||||
|
|
|
@ -132,20 +132,33 @@ pub mod drtio {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn link_thread(io: Io) {
|
||||
let mut link_up = vec![false; csr::DRTIO.len()];
|
||||
// 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) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue