forked from M-Labs/artiq
runtime: centralize (D)RTIO management
This commit is contained in:
parent
0a9f69a3ed
commit
09fb4869f3
@ -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());
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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};
|
161
artiq/runtime.rs/src/rtio_mgt.rs
Normal file
161
artiq/runtime.rs/src/rtio_mgt.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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"))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user