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 {
|
pub enum Packet {
|
||||||
EchoRequest,
|
EchoRequest,
|
||||||
EchoReply,
|
EchoReply,
|
||||||
|
ResetRequest { phy: bool },
|
||||||
|
ResetAck,
|
||||||
|
|
||||||
RtioErrorRequest,
|
RtioErrorRequest,
|
||||||
RtioNoErrorReply,
|
RtioNoErrorReply,
|
||||||
|
@ -52,6 +54,10 @@ impl Packet {
|
||||||
Ok(match read_u8(reader)? {
|
Ok(match read_u8(reader)? {
|
||||||
0x00 => Packet::EchoRequest,
|
0x00 => Packet::EchoRequest,
|
||||||
0x01 => Packet::EchoReply,
|
0x01 => Packet::EchoReply,
|
||||||
|
0x02 => Packet::ResetRequest {
|
||||||
|
phy: read_bool(reader)?
|
||||||
|
},
|
||||||
|
0x03 => Packet::ResetAck,
|
||||||
|
|
||||||
0x20 => Packet::RtioErrorRequest,
|
0x20 => Packet::RtioErrorRequest,
|
||||||
0x21 => Packet::RtioNoErrorReply,
|
0x21 => Packet::RtioNoErrorReply,
|
||||||
|
@ -149,6 +155,11 @@ impl Packet {
|
||||||
match *self {
|
match *self {
|
||||||
Packet::EchoRequest => write_u8(writer, 0x00)?,
|
Packet::EchoRequest => write_u8(writer, 0x00)?,
|
||||||
Packet::EchoReply => write_u8(writer, 0x01)?,
|
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::RtioErrorRequest => write_u8(writer, 0x20)?,
|
||||||
Packet::RtioNoErrorReply => write_u8(writer, 0x21)?,
|
Packet::RtioNoErrorReply => write_u8(writer, 0x21)?,
|
||||||
|
|
|
@ -132,20 +132,33 @@ pub mod drtio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_thread(io: Io) {
|
// FIXME: use csr::DRTIO.len(), maybe get rid of static mut as well.
|
||||||
let mut link_up = vec![false; csr::DRTIO.len()];
|
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 {
|
loop {
|
||||||
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 link_up[linkno as usize] {
|
if link_up(linkno) {
|
||||||
/* link was previously up */
|
/* link was previously up */
|
||||||
if link_rx_up(linkno) {
|
if link_rx_up(linkno) {
|
||||||
process_local_errors(linkno);
|
process_local_errors(linkno);
|
||||||
process_aux_errors(linkno);
|
process_aux_errors(linkno);
|
||||||
} else {
|
} else {
|
||||||
info!("[LINK#{}] link is down", linkno);
|
info!("[LINK#{}] link is down", linkno);
|
||||||
link_up[linkno as usize] = false;
|
set_link_up(linkno, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* link was previously down */
|
/* link was previously down */
|
||||||
|
@ -158,7 +171,7 @@ pub mod drtio {
|
||||||
init_buffer_space(linkno);
|
init_buffer_space(linkno);
|
||||||
sync_tsc(linkno);
|
sync_tsc(linkno);
|
||||||
info!("[LINK#{}] link initialization completed", linkno);
|
info!("[LINK#{}] link initialization completed", linkno);
|
||||||
link_up[linkno as usize] = true;
|
set_link_up(linkno, true);
|
||||||
} else {
|
} else {
|
||||||
info!("[LINK#{}] ping failed", linkno);
|
info!("[LINK#{}] ping failed", linkno);
|
||||||
}
|
}
|
||||||
|
@ -170,7 +183,18 @@ pub mod drtio {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init() {
|
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)]
|
#[cfg(has_hmc830_7043)]
|
||||||
use board_artiq::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) {
|
fn process_aux_packet(p: &drtioaux::Packet) {
|
||||||
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
|
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
|
||||||
// and u16 otherwise; hence the `as _` conversion.
|
// and u16 otherwise; hence the `as _` conversion.
|
||||||
match *p {
|
match *p {
|
||||||
drtioaux::Packet::EchoRequest => drtioaux::hw::send_link(0, &drtioaux::Packet::EchoReply).unwrap(),
|
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 => {
|
drtioaux::Packet::RtioErrorRequest => {
|
||||||
let errors;
|
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() {
|
fn startup() {
|
||||||
board::clock::init();
|
board::clock::init();
|
||||||
info!("ARTIQ satellite manager starting...");
|
info!("ARTIQ satellite manager starting...");
|
||||||
|
@ -225,10 +239,12 @@ fn startup() {
|
||||||
info!("link is up, switching to recovered clock");
|
info!("link is up, switching to recovered clock");
|
||||||
si5324::select_ext_input(true).expect("failed to switch clocks");
|
si5324::select_ext_input(true).expect("failed to switch clocks");
|
||||||
drtio_reset(false);
|
drtio_reset(false);
|
||||||
|
drtio_reset_phy(false);
|
||||||
while drtio_link_is_up() {
|
while drtio_link_is_up() {
|
||||||
process_errors();
|
process_errors();
|
||||||
process_aux_packets();
|
process_aux_packets();
|
||||||
}
|
}
|
||||||
|
drtio_reset_phy(true);
|
||||||
drtio_reset(true);
|
drtio_reset(true);
|
||||||
info!("link is down, switching to local crystal clock");
|
info!("link is down, switching to local crystal clock");
|
||||||
si5324::select_ext_input(false).expect("failed to switch clocks");
|
si5324::select_ext_input(false).expect("failed to switch clocks");
|
||||||
|
|
Loading…
Reference in New Issue