drtio: support remote RTIO resets

This commit is contained in:
Sebastien Bourdeauducq 2018-02-20 18:48:54 +08:00
parent f15b4bdde7
commit 738654c783
3 changed files with 65 additions and 14 deletions

View File

@ -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)?,

View File

@ -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)
}
}
}
}
}

View File

@ -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");