forked from M-Labs/artiq
parent
31bef9918e
commit
bc1d3fda6a
|
@ -1,4 +1,4 @@
|
||||||
#![feature(never_type, panic_implementation, panic_info_message)]
|
#![feature(never_type, panic_implementation, panic_info_message, const_slice_len)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -14,19 +14,27 @@ 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) {
|
mod repeater;
|
||||||
|
|
||||||
|
fn drtiosat_reset(reset: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::drtiosat::reset_write(if reset { 1 } else { 0 });
|
csr::drtiosat::reset_write(if reset { 1 } else { 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drtio_reset_phy(reset: bool) {
|
fn drtiosat_reset_phy(reset: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::drtiosat::reset_phy_write(if reset { 1 } else { 0 });
|
csr::drtiosat::reset_phy_write(if reset { 1 } else { 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drtio_tsc_loaded() -> bool {
|
fn drtiosat_link_rx_up() -> bool {
|
||||||
|
unsafe {
|
||||||
|
csr::drtiosat::rx_up_read() == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drtiosat_tsc_loaded() -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let tsc_loaded = csr::drtiosat::tsc_loaded_read() == 1;
|
let tsc_loaded = csr::drtiosat::tsc_loaded_read() == 1;
|
||||||
if tsc_loaded {
|
if tsc_loaded {
|
||||||
|
@ -44,11 +52,11 @@ fn process_aux_packet(packet: drtioaux::Packet) -> Result<(), drtioaux::Error<!>
|
||||||
drtioaux::send_link(0, &drtioaux::Packet::EchoReply),
|
drtioaux::send_link(0, &drtioaux::Packet::EchoReply),
|
||||||
drtioaux::Packet::ResetRequest { phy } => {
|
drtioaux::Packet::ResetRequest { phy } => {
|
||||||
if phy {
|
if phy {
|
||||||
drtio_reset_phy(true);
|
drtiosat_reset_phy(true);
|
||||||
drtio_reset_phy(false);
|
drtiosat_reset_phy(false);
|
||||||
} else {
|
} else {
|
||||||
drtio_reset(true);
|
drtiosat_reset(true);
|
||||||
drtio_reset(false);
|
drtiosat_reset(false);
|
||||||
}
|
}
|
||||||
drtioaux::send_link(0, &drtioaux::Packet::ResetAck)
|
drtioaux::send_link(0, &drtioaux::Packet::ResetAck)
|
||||||
},
|
},
|
||||||
|
@ -198,7 +206,7 @@ fn process_aux_packets() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_errors() {
|
fn drtiosat_process_errors() {
|
||||||
let errors;
|
let errors;
|
||||||
unsafe {
|
unsafe {
|
||||||
errors = csr::drtiosat::protocol_error_read();
|
errors = csr::drtiosat::protocol_error_read();
|
||||||
|
@ -245,12 +253,6 @@ const SI5324_SETTINGS: si5324::FrequencySettings
|
||||||
crystal_ref: true
|
crystal_ref: true
|
||||||
};
|
};
|
||||||
|
|
||||||
fn drtio_link_rx_up() -> bool {
|
|
||||||
unsafe {
|
|
||||||
csr::drtiosat::rx_up_read() == 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SIPHASER_PHASE: u16 = 32;
|
const SIPHASER_PHASE: u16 = 32;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -279,9 +281,21 @@ pub extern fn main() -> i32 {
|
||||||
#[cfg(has_allaki_atts)]
|
#[cfg(has_allaki_atts)]
|
||||||
board_artiq::hmc542::program_all(8/*=4dB*/);
|
board_artiq::hmc542::program_all(8/*=4dB*/);
|
||||||
|
|
||||||
|
#[cfg(has_drtio_routing)]
|
||||||
|
let mut repeaters = [repeater::Repeater::default(); csr::DRTIOREP.len()];
|
||||||
|
#[cfg(not(has_drtio_routing))]
|
||||||
|
let mut repeaters = [repeater::Repeater::default(); 0];
|
||||||
|
|
||||||
|
for i in 0..repeaters.len() {
|
||||||
|
repeaters[i] = repeater::Repeater::new(i as u8);
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
while !drtio_link_rx_up() {
|
while !drtiosat_link_rx_up() {
|
||||||
process_errors();
|
drtiosat_process_errors();
|
||||||
|
for mut rep in repeaters.iter_mut() {
|
||||||
|
rep.service();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("link is up, switching to recovered clock");
|
info!("link is up, switching to recovered clock");
|
||||||
|
@ -308,13 +322,16 @@ pub extern fn main() -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
drtioaux::reset(0);
|
drtioaux::reset(0);
|
||||||
drtio_reset(false);
|
drtiosat_reset(false);
|
||||||
drtio_reset_phy(false);
|
drtiosat_reset_phy(false);
|
||||||
|
|
||||||
while drtio_link_rx_up() {
|
while drtiosat_link_rx_up() {
|
||||||
process_errors();
|
drtiosat_process_errors();
|
||||||
process_aux_packets();
|
process_aux_packets();
|
||||||
if drtio_tsc_loaded() {
|
for mut rep in repeaters.iter_mut() {
|
||||||
|
rep.service();
|
||||||
|
}
|
||||||
|
if drtiosat_tsc_loaded() {
|
||||||
#[cfg(has_ad9154)]
|
#[cfg(has_ad9154)]
|
||||||
{
|
{
|
||||||
if let Err(e) = board_artiq::jesd204sync::sysref_auto_rtio_align() {
|
if let Err(e) = board_artiq::jesd204sync::sysref_auto_rtio_align() {
|
||||||
|
@ -333,9 +350,9 @@ pub extern fn main() -> i32 {
|
||||||
#[cfg(has_ad9154)]
|
#[cfg(has_ad9154)]
|
||||||
board_artiq::ad9154::jesd_reset(true);
|
board_artiq::ad9154::jesd_reset(true);
|
||||||
|
|
||||||
drtio_reset_phy(true);
|
drtiosat_reset_phy(true);
|
||||||
drtio_reset(true);
|
drtiosat_reset(true);
|
||||||
drtio_tsc_loaded();
|
drtiosat_tsc_loaded();
|
||||||
info!("link is down, switching to local crystal clock");
|
info!("link is down, switching to local crystal clock");
|
||||||
si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks");
|
si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
use board_misoc::{csr, clock};
|
||||||
|
use board_artiq::drtioaux;
|
||||||
|
|
||||||
|
#[cfg(has_drtio_routing)]
|
||||||
|
fn rep_link_rx_up(linkno: u8) -> bool {
|
||||||
|
let linkno = linkno as usize;
|
||||||
|
unsafe {
|
||||||
|
(csr::DRTIOREP[linkno].rx_up_read)() == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum RepeaterState {
|
||||||
|
Down,
|
||||||
|
SendPing { ping_count: u16 },
|
||||||
|
WaitPingReply { ping_count: u16, timeout: u64 },
|
||||||
|
Up,
|
||||||
|
Failed
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RepeaterState {
|
||||||
|
fn default() -> RepeaterState { RepeaterState::Down }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
pub struct Repeater {
|
||||||
|
repno: u8,
|
||||||
|
auxno: u8,
|
||||||
|
state: RepeaterState
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_drtio_routing)]
|
||||||
|
impl Repeater {
|
||||||
|
pub fn new(repno: u8) -> Repeater {
|
||||||
|
Repeater {
|
||||||
|
repno: repno,
|
||||||
|
auxno: repno + 1,
|
||||||
|
state: RepeaterState::Down
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn service(&mut self) {
|
||||||
|
match self.state {
|
||||||
|
RepeaterState::Down => {
|
||||||
|
if rep_link_rx_up(self.repno) {
|
||||||
|
info!("[REP#{}] link RX became up, pinging", self.repno);
|
||||||
|
self.state = RepeaterState::SendPing { ping_count: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RepeaterState::SendPing { ping_count } => {
|
||||||
|
if rep_link_rx_up(self.repno) {
|
||||||
|
drtioaux::send_link(self.auxno, &drtioaux::Packet::EchoRequest).unwrap();
|
||||||
|
self.state = RepeaterState::WaitPingReply {
|
||||||
|
ping_count: ping_count + 1,
|
||||||
|
timeout: clock::get_ms() + 100
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info!("[REP#{}] link RX went down during ping", self.repno);
|
||||||
|
self.state = RepeaterState::Down;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RepeaterState::WaitPingReply { ping_count, timeout } => {
|
||||||
|
if rep_link_rx_up(self.repno) {
|
||||||
|
if let Ok(Some(drtioaux::Packet::EchoReply)) = drtioaux::recv_link(self.auxno) {
|
||||||
|
info!("[REP#{}] remote replied after {} packets", self.repno, ping_count);
|
||||||
|
// TODO: send TSC, routing table, and rank
|
||||||
|
self.state = RepeaterState::Up;
|
||||||
|
} else {
|
||||||
|
if clock::get_ms() > timeout {
|
||||||
|
if ping_count > 200 {
|
||||||
|
info!("[REP#{}] ping failed", self.repno);
|
||||||
|
self.state = RepeaterState::Failed;
|
||||||
|
} else {
|
||||||
|
self.state = RepeaterState::SendPing { ping_count: ping_count };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info!("[REP#{}] link RX went down during ping", self.repno);
|
||||||
|
self.state = RepeaterState::Down;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RepeaterState::Up => {
|
||||||
|
if !rep_link_rx_up(self.repno) {
|
||||||
|
info!("[REP#{}] link is down", self.repno);
|
||||||
|
self.state = RepeaterState::Down;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RepeaterState::Failed => {
|
||||||
|
if !rep_link_rx_up(self.repno) {
|
||||||
|
info!("[REP#{}] link is down", self.repno);
|
||||||
|
self.state = RepeaterState::Down;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(has_drtio_routing))]
|
||||||
|
impl Repeater {
|
||||||
|
pub fn new(_repno: u8) -> Repeater { Repeater::default() }
|
||||||
|
|
||||||
|
pub fn service(&self) { }
|
||||||
|
}
|
Loading…
Reference in New Issue