From 09fb4869f3408e7b2a296e7a064774153e3c668b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 9 Dec 2016 19:24:00 +0800 Subject: [PATCH] runtime: centralize (D)RTIO management --- artiq/runtime.rs/src/drtio.rs | 70 -------------- artiq/runtime.rs/src/lib.rs | 11 +-- artiq/runtime.rs/src/rtio_crg.rs | 65 ------------- artiq/runtime.rs/src/rtio_mgt.rs | 161 +++++++++++++++++++++++++++++++ artiq/runtime.rs/src/session.rs | 13 +-- 5 files changed, 168 insertions(+), 152 deletions(-) delete mode 100644 artiq/runtime.rs/src/drtio.rs delete mode 100644 artiq/runtime.rs/src/rtio_crg.rs create mode 100644 artiq/runtime.rs/src/rtio_mgt.rs diff --git a/artiq/runtime.rs/src/drtio.rs b/artiq/runtime.rs/src/drtio.rs deleted file mode 100644 index 1f05803f3..000000000 --- a/artiq/runtime.rs/src/drtio.rs +++ /dev/null @@ -1,70 +0,0 @@ -use board::csr; -use sched::{Waiter, Spawner}; - -fn drtio_link_is_up() -> bool { - unsafe { - csr::drtio::link_status_read() == 1 - } -} - -fn drtio_sync_tsc() { - unsafe { - csr::drtio::set_time_write(1); - while csr::drtio::set_time_read() == 1 {} - } -} - -fn drtio_init_channel(channel: u16) { - unsafe { - csr::drtio::chan_sel_override_write(channel); - csr::drtio::chan_sel_override_en_write(1); - - csr::drtio::o_reset_channel_status_write(1); - csr::drtio::o_get_fifo_space_write(1); - while csr::drtio::o_wait_read() == 1 {} - info!("FIFO space on channel {} is {}", channel, csr::drtio::o_dbg_fifo_space_read()); - - csr::drtio::chan_sel_override_en_write(0); - } -} - -pub fn link_thread(waiter: Waiter, _spawner: Spawner) { - loop { - waiter.until(drtio_link_is_up).unwrap(); - info!("link RX is up"); - - waiter.sleep(600).unwrap(); - info!("wait for remote side done"); - - drtio_sync_tsc(); - info!("TSC synced"); - for channel in 0..16 { - drtio_init_channel(channel); - } - info!("link initialization completed"); - - waiter.until(|| !drtio_link_is_up()).unwrap(); - info!("link is down"); - } -} - -fn drtio_packet_error_present() -> bool { - unsafe { - csr::drtio::packet_err_present_read() != 0 - } -} - -fn drtio_get_packet_error() -> u8 { - unsafe { - let err = csr::drtio::packet_err_code_read(); - csr::drtio::packet_err_present_write(1); - err - } -} - -pub fn error_thread(waiter: Waiter, _spawner: Spawner) { - loop { - waiter.until(drtio_packet_error_present).unwrap(); - error!("DRTIO packet error {}", drtio_get_packet_error()); - } -} diff --git a/artiq/runtime.rs/src/lib.rs b/artiq/runtime.rs/src/lib.rs index c8aa52950..cfc623de8 100644 --- a/artiq/runtime.rs/src/lib.rs +++ b/artiq/runtime.rs/src/lib.rs @@ -58,7 +58,7 @@ extern fn panic_fmt(args: self::core::fmt::Arguments, file: &'static str, line: mod board; mod config; mod clock; -mod rtio_crg; +mod rtio_mgt; mod mailbox; mod rpc_queue; @@ -80,8 +80,6 @@ mod session; mod moninj; #[cfg(has_rtio_analyzer)] mod analyzer; -#[cfg(has_drtio)] -mod drtio; extern { fn network_init(); @@ -120,20 +118,15 @@ pub unsafe extern fn rust_main() { } info!("continuing boot"); - rtio_crg::init(); network_init(); let mut scheduler = sched::Scheduler::new(); + rtio_mgt::startup(&scheduler); scheduler.spawner().spawn(16384, session::thread); #[cfg(has_rtio_moninj)] scheduler.spawner().spawn(4096, moninj::thread); #[cfg(has_rtio_analyzer)] scheduler.spawner().spawn(4096, analyzer::thread); - #[cfg(has_drtio)] - { - scheduler.spawner().spawn(4096, drtio::link_thread); - scheduler.spawner().spawn(4096, drtio::error_thread); - } loop { scheduler.run(); diff --git a/artiq/runtime.rs/src/rtio_crg.rs b/artiq/runtime.rs/src/rtio_crg.rs deleted file mode 100644 index 416bab03f..000000000 --- a/artiq/runtime.rs/src/rtio_crg.rs +++ /dev/null @@ -1,65 +0,0 @@ -use config; - -#[cfg(has_rtio_crg)] -mod imp { - use board::csr; - use clock; - - pub fn init() { - unsafe { csr::rtio_crg::pll_reset_write(0) } - } - - pub fn check() -> bool { - unsafe { csr::rtio_crg::pll_locked_read() != 0 } - } - - pub fn switch_clock(clk: u8) -> bool { - unsafe { - let cur_clk = csr::rtio_crg::clock_sel_read(); - if clk != cur_clk { - csr::rtio_crg::pll_reset_write(1); - csr::rtio_crg::clock_sel_write(clk); - csr::rtio_crg::pll_reset_write(0); - } - } - - clock::spin_us(150); - return check() - } -} - -#[cfg(not(has_rtio_crg))] -mod imp { - pub fn init() {} - pub fn check() -> bool { true } - pub fn switch_clock(clk: u8) -> bool { true } -} - -pub fn init() { - imp::init(); - - let mut opt = [b'i']; - let clk; - match config::read("startup_clock", &mut opt) { - Ok(0) | Ok(1) if &opt == b"i" => { - info!("startup RTIO clock: internal"); - clk = 0 - } - Ok(1) if &opt == b"e" => { - info!("startup RTIO clock: external"); - clk = 1 - } - _ => { - error!("unrecognized startup_clock configuration entry"); - clk = 0 - } - }; - - if !switch_clock(clk) { - error!("startup RTIO clock failed"); - warn!("this may cause the system initialization to fail"); - warn!("fix clocking and reset the device"); - } -} - -pub use self::imp::{check, switch_clock}; diff --git a/artiq/runtime.rs/src/rtio_mgt.rs b/artiq/runtime.rs/src/rtio_mgt.rs new file mode 100644 index 000000000..4c39755d2 --- /dev/null +++ b/artiq/runtime.rs/src/rtio_mgt.rs @@ -0,0 +1,161 @@ +use config; +use board::csr; +use sched::Scheduler; + +#[cfg(has_rtio_crg)] +pub mod crg { + use clock; + use board::csr; + + pub fn init() { + unsafe { csr::rtio_crg::pll_reset_write(0) } + } + + pub fn check() -> bool { + unsafe { csr::rtio_crg::pll_locked_read() != 0 } + } + + pub fn switch_clock(clk: u8) -> bool { + unsafe { + let cur_clk = csr::rtio_crg::clock_sel_read(); + if clk != cur_clk { + csr::rtio_crg::pll_reset_write(1); + csr::rtio_crg::clock_sel_write(clk); + csr::rtio_crg::pll_reset_write(0); + } + } + + clock::spin_us(150); + return check() + } +} + +#[cfg(not(has_rtio_crg))] +pub mod crg { + pub fn init() {} + pub fn check() -> bool { true } + pub fn switch_clock(_clk: u8) -> bool { true } +} + +#[cfg(has_drtio)] +mod drtio { + use board::csr; + use sched::{Scheduler, Waiter, Spawner}; + + pub fn init(scheduler: &Scheduler) { + scheduler.spawner().spawn(4096, link_thread); + scheduler.spawner().spawn(4096, error_thread); + } + + fn link_is_up() -> bool { + unsafe { + csr::drtio::link_status_read() == 1 + } + } + + fn sync_tsc() { + unsafe { + csr::drtio::set_time_write(1); + while csr::drtio::set_time_read() == 1 {} + } + } + + fn init_channel(channel: u16) { + unsafe { + csr::drtio::chan_sel_override_write(channel); + csr::drtio::chan_sel_override_en_write(1); + + csr::drtio::o_reset_channel_status_write(1); + csr::drtio::o_get_fifo_space_write(1); + while csr::drtio::o_wait_read() == 1 {} + info!("FIFO space on channel {} is {}", channel, csr::drtio::o_dbg_fifo_space_read()); + + csr::drtio::chan_sel_override_en_write(0); + } + } + + pub fn link_thread(waiter: Waiter, _spawner: Spawner) { + loop { + waiter.until(link_is_up).unwrap(); + info!("link RX is up"); + + waiter.sleep(600).unwrap(); + info!("wait for remote side done"); + + sync_tsc(); + info!("TSC synced"); + for channel in 0..16 { + init_channel(channel); + } + info!("link initialization completed"); + + waiter.until(|| !link_is_up()).unwrap(); + info!("link is down"); + } + } + + fn packet_error_present() -> bool { + unsafe { + csr::drtio::packet_err_present_read() != 0 + } + } + + fn get_packet_error() -> u8 { + unsafe { + let err = csr::drtio::packet_err_code_read(); + csr::drtio::packet_err_present_write(1); + err + } + } + + pub fn error_thread(waiter: Waiter, _spawner: Spawner) { + loop { + waiter.until(packet_error_present).unwrap(); + error!("DRTIO packet error {}", get_packet_error()); + } + } + +} + +#[cfg(not(has_drtio))] +mod drtio { + use sched::Scheduler; + + pub fn init(_scheduler: &Scheduler) {} +} + +pub fn startup(scheduler: &Scheduler) { + crg::init(); + + let mut opt = [b'i']; + let clk; + match config::read("startup_clock", &mut opt) { + Ok(0) | Ok(1) if &opt == b"i" => { + info!("startup RTIO clock: internal"); + clk = 0 + } + Ok(1) if &opt == b"e" => { + info!("startup RTIO clock: external"); + clk = 1 + } + _ => { + error!("unrecognized startup_clock configuration entry"); + clk = 0 + } + }; + + if !crg::switch_clock(clk) { + error!("startup RTIO clock failed"); + warn!("this may cause the system initialization to fail"); + warn!("fix clocking and reset the device"); + } + + drtio::init(scheduler); + init_core() +} + +pub fn init_core() { + unsafe { + csr::rtio_core::reset_write(1); + } +} diff --git a/artiq/runtime.rs/src/session.rs b/artiq/runtime.rs/src/session.rs index c40e8dd53..cf28202d1 100644 --- a/artiq/runtime.rs/src/session.rs +++ b/artiq/runtime.rs/src/session.rs @@ -3,8 +3,7 @@ use std::{mem, str}; use std::cell::RefCell; use std::io::{self, Read, Write, BufWriter}; use std::btree_set::BTreeSet; -use {config, rtio_crg, clock, mailbox, rpc_queue, kernel}; -use board::csr; // TODO: centralize (D)RTIO management +use {config, rtio_mgt, clock, mailbox, rpc_queue, kernel}; use logger::BufferLogger; use cache::Cache; use urc::Urc; @@ -249,7 +248,7 @@ fn process_host_message(waiter: Waiter, unexpected!("attempted to switch RTIO clock while a kernel was running") } - if rtio_crg::switch_clock(clk) { + if rtio_mgt::crg::switch_clock(clk) { host_write(stream, host::Reply::ClockSwitchCompleted) } else { host_write(stream, host::Reply::ClockSwitchFailed) @@ -380,9 +379,7 @@ fn process_kern_message(waiter: Waiter, &kern::RTIOInitRequest => { info!("resetting RTIO"); - unsafe { - csr::rtio_core::reset_write(1); - } + rtio_mgt::init_core(); kern_acknowledge() } @@ -514,7 +511,7 @@ fn host_kernel_worker(waiter: Waiter, return Err(io_error("watchdog expired")) } - if !rtio_crg::check() { + if !rtio_mgt::crg::check() { try!(host_write(stream, host::Reply::ClockFailure)); return Err(io_error("RTIO clock failure")) } @@ -552,7 +549,7 @@ fn flash_kernel_worker(waiter: Waiter, return Err(io_error("watchdog expired")) } - if !rtio_crg::check() { + if !rtio_mgt::crg::check() { return Err(io_error("RTIO clock failure")) }