2018-09-10 20:17:02 +08:00
|
|
|
#![feature(never_type, panic_implementation, panic_info_message, const_slice_len)]
|
2017-01-19 06:50:32 +08:00
|
|
|
#![no_std]
|
|
|
|
|
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
2017-03-15 17:26:09 +08:00
|
|
|
#[macro_use]
|
2018-05-15 01:54:29 +08:00
|
|
|
extern crate board_misoc;
|
2017-12-28 15:10:34 +08:00
|
|
|
extern crate board_artiq;
|
2017-02-22 15:26:32 +08:00
|
|
|
|
2018-05-15 01:54:29 +08:00
|
|
|
use board_misoc::{csr, ident, clock, uart_logger};
|
2018-05-15 01:26:36 +08:00
|
|
|
use board_artiq::{i2c, spi, si5324, drtioaux};
|
2017-12-28 15:10:34 +08:00
|
|
|
#[cfg(has_serwb_phy_amc)]
|
|
|
|
use board_artiq::serwb;
|
|
|
|
#[cfg(has_hmc830_7043)]
|
|
|
|
use board_artiq::hmc830_7043;
|
|
|
|
|
2018-09-10 20:17:02 +08:00
|
|
|
mod repeater;
|
|
|
|
|
|
|
|
fn drtiosat_reset(reset: bool) {
|
2018-02-20 18:48:54 +08:00
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
csr::drtiosat::reset_write(if reset { 1 } else { 0 });
|
2018-02-20 18:48:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:17:02 +08:00
|
|
|
fn drtiosat_reset_phy(reset: bool) {
|
2018-02-20 18:48:54 +08:00
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
csr::drtiosat::reset_phy_write(if reset { 1 } else { 0 });
|
2018-02-20 18:48:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:17:02 +08:00
|
|
|
fn drtiosat_link_rx_up() -> bool {
|
|
|
|
unsafe {
|
|
|
|
csr::drtiosat::rx_up_read() == 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn drtiosat_tsc_loaded() -> bool {
|
2018-06-21 17:00:32 +08:00
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
let tsc_loaded = csr::drtiosat::tsc_loaded_read() == 1;
|
2018-06-21 17:00:32 +08:00
|
|
|
if tsc_loaded {
|
2018-09-05 17:56:56 +08:00
|
|
|
csr::drtiosat::tsc_loaded_write(1);
|
2018-06-21 17:00:32 +08:00
|
|
|
}
|
|
|
|
tsc_loaded
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-16 00:35:05 +08:00
|
|
|
fn process_aux_packet(packet: drtioaux::Packet) -> Result<(), drtioaux::Error<!>> {
|
2017-02-23 16:59:27 +08:00
|
|
|
// In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
|
|
|
|
// and u16 otherwise; hence the `as _` conversion.
|
2018-05-14 19:18:09 +08:00
|
|
|
match packet {
|
|
|
|
drtioaux::Packet::EchoRequest =>
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &drtioaux::Packet::EchoReply),
|
2018-02-20 18:48:54 +08:00
|
|
|
drtioaux::Packet::ResetRequest { phy } => {
|
|
|
|
if phy {
|
2018-09-10 20:17:02 +08:00
|
|
|
drtiosat_reset_phy(true);
|
|
|
|
drtiosat_reset_phy(false);
|
2018-02-20 18:48:54 +08:00
|
|
|
} else {
|
2018-09-10 20:17:02 +08:00
|
|
|
drtiosat_reset(true);
|
|
|
|
drtiosat_reset(false);
|
2018-02-22 15:27:54 +08:00
|
|
|
}
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &drtioaux::Packet::ResetAck)
|
2018-02-20 18:48:54 +08:00
|
|
|
},
|
2017-04-02 23:45:55 +08:00
|
|
|
|
|
|
|
drtioaux::Packet::RtioErrorRequest => {
|
|
|
|
let errors;
|
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
errors = csr::drtiosat::rtio_error_read();
|
2017-04-02 23:45:55 +08:00
|
|
|
}
|
|
|
|
if errors & 1 != 0 {
|
2017-09-29 16:32:57 +08:00
|
|
|
let channel;
|
2017-04-02 23:45:55 +08:00
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
channel = csr::drtiosat::sequence_error_channel_read();
|
|
|
|
csr::drtiosat::rtio_error_write(1);
|
2017-04-02 23:45:55 +08:00
|
|
|
}
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::RtioErrorSequenceErrorReply { channel })
|
2017-04-02 23:45:55 +08:00
|
|
|
} else if errors & 2 != 0 {
|
2017-09-29 16:32:57 +08:00
|
|
|
let channel;
|
2017-04-02 23:45:55 +08:00
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
channel = csr::drtiosat::collision_channel_read();
|
|
|
|
csr::drtiosat::rtio_error_write(2);
|
2017-04-02 23:45:55 +08:00
|
|
|
}
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::RtioErrorCollisionReply { channel })
|
2017-09-24 12:23:47 +08:00
|
|
|
} else if errors & 4 != 0 {
|
2017-09-29 16:32:57 +08:00
|
|
|
let channel;
|
2017-09-24 12:23:47 +08:00
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
channel = csr::drtiosat::busy_channel_read();
|
|
|
|
csr::drtiosat::rtio_error_write(4);
|
2017-09-24 12:23:47 +08:00
|
|
|
}
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::RtioErrorBusyReply { channel })
|
2017-09-24 12:23:47 +08:00
|
|
|
}
|
|
|
|
else {
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &drtioaux::Packet::RtioNoErrorReply)
|
2017-04-02 23:45:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-23 16:24:05 +08:00
|
|
|
drtioaux::Packet::MonitorRequest { channel, probe } => {
|
|
|
|
let value;
|
|
|
|
#[cfg(has_rtio_moninj)]
|
|
|
|
unsafe {
|
2017-12-28 15:10:34 +08:00
|
|
|
csr::rtio_moninj::mon_chan_sel_write(channel as _);
|
|
|
|
csr::rtio_moninj::mon_probe_sel_write(probe);
|
|
|
|
csr::rtio_moninj::mon_value_update_write(1);
|
|
|
|
value = csr::rtio_moninj::mon_value_read();
|
2017-02-23 16:24:05 +08:00
|
|
|
}
|
|
|
|
#[cfg(not(has_rtio_moninj))]
|
|
|
|
{
|
|
|
|
value = 0;
|
|
|
|
}
|
|
|
|
let reply = drtioaux::Packet::MonitorReply { value: value as u32 };
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &reply)
|
2017-02-23 16:24:05 +08:00
|
|
|
},
|
|
|
|
drtioaux::Packet::InjectionRequest { channel, overrd, value } => {
|
|
|
|
#[cfg(has_rtio_moninj)]
|
|
|
|
unsafe {
|
2017-12-28 15:10:34 +08:00
|
|
|
csr::rtio_moninj::inj_chan_sel_write(channel as _);
|
|
|
|
csr::rtio_moninj::inj_override_sel_write(overrd);
|
|
|
|
csr::rtio_moninj::inj_value_write(value);
|
2017-02-23 16:24:05 +08:00
|
|
|
}
|
2018-05-14 19:18:09 +08:00
|
|
|
Ok(())
|
2017-02-23 16:24:05 +08:00
|
|
|
},
|
|
|
|
drtioaux::Packet::InjectionStatusRequest { channel, overrd } => {
|
|
|
|
let value;
|
|
|
|
#[cfg(has_rtio_moninj)]
|
|
|
|
unsafe {
|
2017-12-28 15:10:34 +08:00
|
|
|
csr::rtio_moninj::inj_chan_sel_write(channel as _);
|
|
|
|
csr::rtio_moninj::inj_override_sel_write(overrd);
|
|
|
|
value = csr::rtio_moninj::inj_value_read();
|
2017-02-23 16:24:05 +08:00
|
|
|
}
|
|
|
|
#[cfg(not(has_rtio_moninj))]
|
|
|
|
{
|
|
|
|
value = 0;
|
|
|
|
}
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &drtioaux::Packet::InjectionStatusReply { value: value })
|
2017-02-23 16:24:05 +08:00
|
|
|
},
|
2017-06-21 16:50:51 +08:00
|
|
|
|
|
|
|
drtioaux::Packet::I2cStartRequest { busno } => {
|
2017-12-28 15:10:34 +08:00
|
|
|
let succeeded = i2c::start(busno).is_ok();
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded })
|
2017-06-21 16:50:51 +08:00
|
|
|
}
|
|
|
|
drtioaux::Packet::I2cRestartRequest { busno } => {
|
2017-12-28 15:10:34 +08:00
|
|
|
let succeeded = i2c::restart(busno).is_ok();
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded })
|
2017-06-21 16:50:51 +08:00
|
|
|
}
|
|
|
|
drtioaux::Packet::I2cStopRequest { busno } => {
|
2017-12-28 15:10:34 +08:00
|
|
|
let succeeded = i2c::stop(busno).is_ok();
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded })
|
2017-06-21 16:50:51 +08:00
|
|
|
}
|
|
|
|
drtioaux::Packet::I2cWriteRequest { busno, data } => {
|
2017-12-28 15:10:34 +08:00
|
|
|
match i2c::write(busno, data) {
|
2018-05-15 01:26:36 +08:00
|
|
|
Ok(ack) => drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::I2cWriteReply { succeeded: true, ack: ack }),
|
2018-05-15 01:26:36 +08:00
|
|
|
Err(_) => drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::I2cWriteReply { succeeded: false, ack: false })
|
|
|
|
}
|
2017-06-21 16:50:51 +08:00
|
|
|
}
|
|
|
|
drtioaux::Packet::I2cReadRequest { busno, ack } => {
|
2017-12-28 15:10:34 +08:00
|
|
|
match i2c::read(busno, ack) {
|
2018-05-15 01:26:36 +08:00
|
|
|
Ok(data) => drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::I2cReadReply { succeeded: true, data: data }),
|
2018-05-15 01:26:36 +08:00
|
|
|
Err(_) => drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::I2cReadReply { succeeded: false, data: 0xff })
|
|
|
|
}
|
2017-06-21 16:50:51 +08:00
|
|
|
}
|
|
|
|
|
2018-02-23 17:50:49 +08:00
|
|
|
drtioaux::Packet::SpiSetConfigRequest { busno, flags, length, div, cs } => {
|
|
|
|
let succeeded = spi::set_config(busno, flags, length, div, cs).is_ok();
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::SpiBasicReply { succeeded: succeeded })
|
2017-06-21 16:50:51 +08:00
|
|
|
},
|
|
|
|
drtioaux::Packet::SpiWriteRequest { busno, data } => {
|
2017-12-28 15:10:34 +08:00
|
|
|
let succeeded = spi::write(busno, data).is_ok();
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::SpiBasicReply { succeeded: succeeded })
|
2017-06-21 16:50:51 +08:00
|
|
|
}
|
|
|
|
drtioaux::Packet::SpiReadRequest { busno } => {
|
2017-12-28 15:10:34 +08:00
|
|
|
match spi::read(busno) {
|
2018-05-15 01:26:36 +08:00
|
|
|
Ok(data) => drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::SpiReadReply { succeeded: true, data: data }),
|
2018-05-15 01:26:36 +08:00
|
|
|
Err(_) => drtioaux::send_link(0,
|
2018-05-14 19:18:09 +08:00
|
|
|
&drtioaux::Packet::SpiReadReply { succeeded: false, data: 0 })
|
|
|
|
}
|
2017-06-21 16:50:51 +08:00
|
|
|
}
|
|
|
|
|
2018-05-14 19:18:09 +08:00
|
|
|
_ => {
|
|
|
|
warn!("received unexpected aux packet");
|
|
|
|
Ok(())
|
|
|
|
}
|
2017-02-22 15:26:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn process_aux_packets() {
|
2018-05-14 19:18:09 +08:00
|
|
|
let result =
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::recv_link(0).and_then(|packet| {
|
2018-05-14 19:18:09 +08:00
|
|
|
if let Some(packet) = packet {
|
|
|
|
process_aux_packet(packet)
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
});
|
|
|
|
match result {
|
|
|
|
Ok(()) => (),
|
2017-02-22 15:26:32 +08:00
|
|
|
Err(e) => warn!("aux packet error ({})", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-10 20:17:02 +08:00
|
|
|
fn drtiosat_process_errors() {
|
2017-04-01 12:18:00 +08:00
|
|
|
let errors;
|
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
errors = csr::drtiosat::protocol_error_read();
|
2017-04-01 12:18:00 +08:00
|
|
|
}
|
|
|
|
if errors & 1 != 0 {
|
|
|
|
error!("received packet of an unknown type");
|
|
|
|
}
|
|
|
|
if errors & 2 != 0 {
|
|
|
|
error!("received truncated packet");
|
|
|
|
}
|
|
|
|
if errors & 4 != 0 {
|
2018-09-05 14:00:09 +08:00
|
|
|
error!("timeout attempting to get buffer space from CRI")
|
|
|
|
}
|
|
|
|
if errors & 8 != 0 {
|
2018-03-12 23:41:19 +08:00
|
|
|
let channel;
|
|
|
|
let timestamp_event;
|
|
|
|
let timestamp_counter;
|
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
channel = csr::drtiosat::underflow_channel_read();
|
|
|
|
timestamp_event = csr::drtiosat::underflow_timestamp_event_read() as i64;
|
|
|
|
timestamp_counter = csr::drtiosat::underflow_timestamp_counter_read() as i64;
|
2018-03-12 23:41:19 +08:00
|
|
|
}
|
|
|
|
error!("write underflow, channel={}, timestamp={}, counter={}, slack={}",
|
|
|
|
channel, timestamp_event, timestamp_counter, timestamp_event-timestamp_counter);
|
2017-04-01 12:18:00 +08:00
|
|
|
}
|
2018-09-05 14:00:09 +08:00
|
|
|
if errors & 16 != 0 {
|
2017-04-01 12:18:00 +08:00
|
|
|
error!("write overflow");
|
|
|
|
}
|
2018-03-12 23:41:19 +08:00
|
|
|
unsafe {
|
2018-09-05 17:56:56 +08:00
|
|
|
csr::drtiosat::protocol_error_write(errors);
|
2018-03-12 23:41:19 +08:00
|
|
|
}
|
2017-04-01 12:18:00 +08:00
|
|
|
}
|
|
|
|
|
2017-02-02 18:11:24 +08:00
|
|
|
#[cfg(rtio_frequency = "150.0")]
|
2017-12-28 15:10:34 +08:00
|
|
|
const SI5324_SETTINGS: si5324::FrequencySettings
|
2018-03-07 00:06:39 +08:00
|
|
|
= si5324::FrequencySettings {
|
|
|
|
n1_hs : 6,
|
|
|
|
nc1_ls : 6,
|
2017-02-02 18:11:24 +08:00
|
|
|
n2_hs : 10,
|
2018-03-07 00:06:39 +08:00
|
|
|
n2_ls : 270,
|
|
|
|
n31 : 75,
|
|
|
|
n32 : 75,
|
|
|
|
bwsel : 4,
|
2018-02-17 13:52:01 +08:00
|
|
|
crystal_ref: true
|
2017-02-02 18:11:24 +08:00
|
|
|
};
|
|
|
|
|
2018-06-21 17:00:32 +08:00
|
|
|
const SIPHASER_PHASE: u16 = 32;
|
|
|
|
|
2018-05-14 18:45:11 +08:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern fn main() -> i32 {
|
2018-05-15 01:54:29 +08:00
|
|
|
clock::init();
|
|
|
|
uart_logger::ConsoleLogger::register();
|
2018-05-14 18:45:11 +08:00
|
|
|
|
2017-01-25 05:55:51 +08:00
|
|
|
info!("ARTIQ satellite manager starting...");
|
2018-07-15 17:40:17 +08:00
|
|
|
info!("software ident {}", csr::CONFIG_IDENTIFIER_STR);
|
|
|
|
info!("gateware ident {}", ident::read(&mut [0; 64]));
|
2017-01-19 06:50:32 +08:00
|
|
|
|
2018-06-19 14:33:48 +08:00
|
|
|
#[cfg(has_slave_fpga_cfg)]
|
|
|
|
board_artiq::slave_fpga::load().expect("cannot load RTM FPGA gateware");
|
2017-11-19 01:09:35 +08:00
|
|
|
#[cfg(has_serwb_phy_amc)]
|
2017-12-28 15:10:34 +08:00
|
|
|
serwb::wait_init();
|
2017-09-06 11:07:07 +08:00
|
|
|
|
2017-12-28 15:10:34 +08:00
|
|
|
i2c::init();
|
2018-03-07 00:06:39 +08:00
|
|
|
si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324");
|
2018-06-28 11:23:40 +08:00
|
|
|
#[cfg(has_hmc830_7043)]
|
|
|
|
/* must be the first SPI init because of HMC830 SPI mode selection */
|
|
|
|
hmc830_7043::init().expect("cannot initialize HMC830/7043");
|
2018-02-18 22:29:30 +08:00
|
|
|
unsafe {
|
|
|
|
csr::drtio_transceiver::stable_clkin_write(1);
|
|
|
|
}
|
2017-01-30 11:06:45 +08:00
|
|
|
|
2018-06-19 18:09:05 +08:00
|
|
|
#[cfg(has_allaki_atts)]
|
|
|
|
board_artiq::hmc542::program_all(8/*=4dB*/);
|
2018-06-19 14:33:48 +08:00
|
|
|
|
2018-09-10 20:17:02 +08:00
|
|
|
#[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);
|
|
|
|
}
|
|
|
|
|
2017-02-18 13:32:40 +08:00
|
|
|
loop {
|
2018-09-10 20:17:02 +08:00
|
|
|
while !drtiosat_link_rx_up() {
|
|
|
|
drtiosat_process_errors();
|
|
|
|
for mut rep in repeaters.iter_mut() {
|
|
|
|
rep.service();
|
|
|
|
}
|
2017-04-01 12:18:00 +08:00
|
|
|
}
|
2018-08-17 22:57:54 +08:00
|
|
|
|
2017-02-18 13:32:40 +08:00
|
|
|
info!("link is up, switching to recovered clock");
|
2018-03-07 11:15:44 +08:00
|
|
|
si5324::siphaser::select_recovered_clock(true).expect("failed to switch clocks");
|
2018-06-21 17:00:32 +08:00
|
|
|
si5324::siphaser::calibrate_skew(SIPHASER_PHASE).expect("failed to calibrate skew");
|
2018-08-17 22:57:54 +08:00
|
|
|
|
|
|
|
#[cfg(has_ad9154)]
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* One side of the JESD204 elastic buffer is clocked by the Si5324, the other
|
|
|
|
* by the RTM.
|
|
|
|
* The elastic buffer can operate only when those two clocks are derived from
|
|
|
|
* the same oscillator.
|
|
|
|
* This is the case when either of those conditions is true:
|
|
|
|
* (1) The DRTIO master and the RTM are clocked directly from a common external
|
|
|
|
* source, *and* the Si5324 has locked to the recovered clock.
|
|
|
|
* This clocking scheme provides less noise and phase drift at the DACs.
|
|
|
|
* (2) The RTM clock is connected to the Si5324 output.
|
|
|
|
* To handle those cases, we simply keep the JESD204 core in reset unless the
|
|
|
|
* Si5324 is locked to the recovered clock.
|
|
|
|
*/
|
|
|
|
board_artiq::ad9154::jesd_reset(false);
|
|
|
|
board_artiq::ad9154::init();
|
|
|
|
}
|
|
|
|
|
2018-05-15 01:26:36 +08:00
|
|
|
drtioaux::reset(0);
|
2018-09-10 20:17:02 +08:00
|
|
|
drtiosat_reset(false);
|
|
|
|
drtiosat_reset_phy(false);
|
2018-08-17 22:57:54 +08:00
|
|
|
|
2018-09-10 20:17:02 +08:00
|
|
|
while drtiosat_link_rx_up() {
|
|
|
|
drtiosat_process_errors();
|
2017-02-22 15:26:32 +08:00
|
|
|
process_aux_packets();
|
2018-09-10 20:17:02 +08:00
|
|
|
for mut rep in repeaters.iter_mut() {
|
|
|
|
rep.service();
|
|
|
|
}
|
|
|
|
if drtiosat_tsc_loaded() {
|
2018-09-10 20:33:44 +08:00
|
|
|
info!("TSC loaded");
|
2018-07-26 20:28:17 +08:00
|
|
|
#[cfg(has_ad9154)]
|
|
|
|
{
|
2018-07-26 19:37:59 +08:00
|
|
|
if let Err(e) = board_artiq::jesd204sync::sysref_auto_rtio_align() {
|
2018-07-26 16:26:57 +08:00
|
|
|
error!("failed to align SYSREF at FPGA: {}", e);
|
|
|
|
}
|
2018-07-26 19:37:59 +08:00
|
|
|
if let Err(e) = board_artiq::jesd204sync::sysref_auto_dac_align() {
|
|
|
|
error!("failed to align SYSREF at DAC: {}", e);
|
|
|
|
}
|
2018-06-21 17:00:32 +08:00
|
|
|
}
|
2018-09-10 20:33:44 +08:00
|
|
|
for rep in repeaters.iter() {
|
|
|
|
rep.sync_tsc();
|
|
|
|
}
|
2018-07-26 20:28:17 +08:00
|
|
|
if let Err(e) = drtioaux::send_link(0, &drtioaux::Packet::TSCAck) {
|
|
|
|
error!("aux packet error: {}", e);
|
|
|
|
}
|
2018-06-21 17:00:32 +08:00
|
|
|
}
|
2017-02-22 15:26:32 +08:00
|
|
|
}
|
2018-08-17 22:57:54 +08:00
|
|
|
|
|
|
|
#[cfg(has_ad9154)]
|
|
|
|
board_artiq::ad9154::jesd_reset(true);
|
|
|
|
|
2018-09-10 20:17:02 +08:00
|
|
|
drtiosat_reset_phy(true);
|
|
|
|
drtiosat_reset(true);
|
|
|
|
drtiosat_tsc_loaded();
|
2017-02-18 13:32:40 +08:00
|
|
|
info!("link is down, switching to local crystal clock");
|
2018-03-07 11:15:44 +08:00
|
|
|
si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks");
|
2017-02-18 13:32:40 +08:00
|
|
|
}
|
2017-01-19 06:50:32 +08:00
|
|
|
}
|
|
|
|
|
2017-01-25 05:55:51 +08:00
|
|
|
#[no_mangle]
|
2017-12-28 15:10:34 +08:00
|
|
|
pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) {
|
2017-02-03 20:12:41 +08:00
|
|
|
panic!("exception {:?} at PC 0x{:x}, EA 0x{:x}", vect, pc, ea)
|
2017-01-19 06:50:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-02-03 20:12:41 +08:00
|
|
|
pub extern fn abort() {
|
2017-12-28 15:10:34 +08:00
|
|
|
println!("aborted");
|
|
|
|
loop {}
|
2017-01-19 06:50:32 +08:00
|
|
|
}
|
|
|
|
|
2018-08-13 07:12:21 +08:00
|
|
|
#[no_mangle] // https://github.com/rust-lang/rust/issues/{38281,51647}
|
|
|
|
#[panic_implementation]
|
|
|
|
pub fn panic_fmt(info: &core::panic::PanicInfo) -> ! {
|
|
|
|
if let Some(location) = info.location() {
|
|
|
|
print!("panic at {}:{}:{}", location.file(), location.line(), location.column());
|
|
|
|
} else {
|
|
|
|
print!("panic at unknown location");
|
|
|
|
}
|
|
|
|
if let Some(message) = info.message() {
|
|
|
|
println!(": {}", message);
|
|
|
|
} else {
|
|
|
|
println!("");
|
|
|
|
}
|
2017-03-15 17:26:09 +08:00
|
|
|
loop {}
|
|
|
|
}
|