Rust: port clock, rtio_crg routines.

This commit is contained in:
whitequark 2016-09-29 20:36:04 +00:00
parent 83940ae4a6
commit 9c18f1b555
5 changed files with 171 additions and 11 deletions

View File

@ -0,0 +1,77 @@
use board::csr::timer0;
const INIT: u64 = ::core::i64::MAX as u64;
const FREQ: u64 = ::board::csr::CONFIG_CLOCK_FREQUENCY as u64;
pub fn init() {
unsafe {
timer0::en_write(0);
timer0::load_write(INIT);
timer0::reload_write(INIT);
timer0::en_write(1);
}
}
pub fn get_ms() -> u64 {
unsafe {
timer0::update_value_write(1);
(INIT - timer0::value_read()) / (FREQ / 1_000)
}
}
pub fn spin_us(interval: u64) {
unsafe {
timer0::update_value_write(1);
let threshold = timer0::value_read() - interval * (FREQ / 1_000_000);
while timer0::value_read() > threshold {
timer0::update_value_write(1)
}
}
}
#[derive(Debug, Clone, Copy)]
struct Watchdog {
active: bool,
threshold: u64
}
pub const MAX_WATCHDOGS: usize = 16;
#[derive(Debug)]
pub struct WatchdogSet {
watchdogs: [Watchdog; MAX_WATCHDOGS]
}
impl WatchdogSet {
pub fn new() -> WatchdogSet {
WatchdogSet {
watchdogs: [Watchdog { active: false, threshold: 0 }; MAX_WATCHDOGS]
}
}
pub fn set_ms(&mut self, interval: u64) -> Result<usize, ()> {
for (index, watchdog) in self.watchdogs.iter_mut().enumerate() {
if !watchdog.active {
watchdog.active = true;
watchdog.threshold = get_ms() + interval;
return Ok(index)
}
}
warn!("cannot add watchdog; all {} watchdogs used", MAX_WATCHDOGS);
Err(())
}
pub fn clear(&mut self, index: usize) {
if index < MAX_WATCHDOGS {
self.watchdogs[index].active = false
}
}
pub fn expired(&self) -> bool {
self.watchdogs.iter()
.filter(|wd| wd.active)
.min_by_key(|wd| wd.threshold)
.map_or(false, |wd| get_ms() > wd.threshold)
}
}

View File

@ -15,6 +15,8 @@ use buffer_logger::BufferLogger;
pub mod board; pub mod board;
pub mod io; pub mod io;
pub mod config; pub mod config;
pub mod clock;
pub mod rtio_crg;
pub mod buffer_logger; pub mod buffer_logger;
pub mod session; pub mod session;
@ -28,7 +30,8 @@ pub unsafe extern fn rust_main() {
static mut log_buffer: [u8; 4096] = [0; 4096]; static mut log_buffer: [u8; 4096] = [0; 4096];
BufferLogger::new(&mut log_buffer[..]) BufferLogger::new(&mut log_buffer[..])
.register(move |logger| { .register(move |logger| {
info!("Accepting network sessions in Rust."); clock::init();
rtio_crg::init();
network_init(); network_init();
let mut scheduler = io::Scheduler::new(); let mut scheduler = io::Scheduler::new();

View File

@ -0,0 +1,47 @@
use board::csr;
use {clock, config};
pub fn init() {
unsafe { csr::rtio_crg::pll_reset_write(0) }
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 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()
}

View File

@ -1,7 +1,7 @@
use std::prelude::v1::*; use std::prelude::v1::*;
use std::str; use std::str;
use std::io::{self, Read, ErrorKind}; use std::io::{self, Read, ErrorKind};
use config; use {config, rtio_crg};
use self::protocol::*; use self::protocol::*;
mod protocol; mod protocol;
@ -26,14 +26,23 @@ extern {
} }
impl Session { impl Session {
pub fn start() -> Session { pub fn new() -> Session {
unsafe { kloader_stop(); } unsafe { kloader_stop(); }
Session { Session {
kernel_state: KernelState::Absent kernel_state: KernelState::Absent
} }
} }
pub fn end(self) { pub fn running(&self) -> bool {
match self.kernel_state {
KernelState::Absent | KernelState::Loaded => false,
KernelState::Running | KernelState::RpcWait => true
}
}
}
impl Drop for Session {
fn drop(&mut self) {
unsafe { unsafe {
kloader_stop(); kloader_stop();
watchdog_init(); watchdog_init();
@ -55,10 +64,14 @@ fn check_magic(stream: &mut ::io::TcpStream) -> io::Result<()> {
} }
fn handle_request(stream: &mut ::io::TcpStream, fn handle_request(stream: &mut ::io::TcpStream,
logger: &::buffer_logger::BufferLogger) -> io::Result<()> { logger: &::buffer_logger::BufferLogger,
session: &mut Session) -> io::Result<()> {
fn read_request(stream: &mut ::io::TcpStream) -> io::Result<Request> { fn read_request(stream: &mut ::io::TcpStream) -> io::Result<Request> {
let request = try!(Request::read_from(stream)); let request = try!(Request::read_from(stream));
trace!("comm<-host {:?}", request); match &request {
&Request::LoadLibrary(_) => trace!("comm<-host LoadLibrary(...)"),
_ => trace!("comm<-host {:?}", request)
}
Ok(request) Ok(request)
} }
@ -71,6 +84,7 @@ fn handle_request(stream: &mut ::io::TcpStream,
Request::Ident => Request::Ident =>
write_reply(stream, Reply::Ident(::board::ident(&mut [0; 64]))), write_reply(stream, Reply::Ident(::board::ident(&mut [0; 64]))),
// artiq_corelog
Request::Log => { Request::Log => {
// Logging the packet with the log is inadvisable // Logging the packet with the log is inadvisable
trace!("comm->host Log(...)"); trace!("comm->host Log(...)");
@ -84,6 +98,7 @@ fn handle_request(stream: &mut ::io::TcpStream,
write_reply(stream, Reply::Log("")) write_reply(stream, Reply::Log(""))
} }
// artiq_coreconfig
Request::FlashRead { ref key } => { Request::FlashRead { ref key } => {
let value = config::read_to_end(key); let value = config::read_to_end(key);
write_reply(stream, Reply::FlashRead(&value)) write_reply(stream, Reply::FlashRead(&value))
@ -106,6 +121,20 @@ fn handle_request(stream: &mut ::io::TcpStream,
write_reply(stream, Reply::FlashOk) write_reply(stream, Reply::FlashOk)
} }
// artiq_run/artiq_master
Request::SwitchClock(clk) => {
if session.running() {
error!("attempted to switch RTIO clock while kernel was running");
write_reply(stream, Reply::ClockSwitchFailed)
} else {
if rtio_crg::switch_clock(clk) {
write_reply(stream, Reply::ClockSwitchCompleted)
} else {
write_reply(stream, Reply::ClockSwitchFailed)
}
}
}
_ => unreachable!() _ => unreachable!()
} }
} }
@ -113,8 +142,10 @@ fn handle_request(stream: &mut ::io::TcpStream,
fn handle_requests(stream: &mut ::io::TcpStream, fn handle_requests(stream: &mut ::io::TcpStream,
logger: &::buffer_logger::BufferLogger) -> io::Result<()> { logger: &::buffer_logger::BufferLogger) -> io::Result<()> {
try!(check_magic(stream)); try!(check_magic(stream));
let mut session = Session::new();
loop { loop {
try!(handle_request(stream, logger)) try!(handle_request(stream, logger, &mut session))
} }
} }
@ -122,6 +153,8 @@ pub fn handler(waiter: ::io::Waiter,
logger: &::buffer_logger::BufferLogger) { logger: &::buffer_logger::BufferLogger) {
let addr = ::io::SocketAddr::new(::io::IP_ANY, 1381); let addr = ::io::SocketAddr::new(::io::IP_ANY, 1381);
let listener = ::io::TcpListener::bind(waiter, addr).unwrap(); let listener = ::io::TcpListener::bind(waiter, addr).unwrap();
info!("accepting network sessions in Rust");
loop { loop {
let (mut stream, addr) = listener.accept().unwrap(); let (mut stream, addr) = listener.accept().unwrap();
info!("new connection from {:?}", addr); info!("new connection from {:?}", addr);

View File

@ -206,6 +206,8 @@ static struct net_server_instance analyzer_inst = {
static void regular_main(void) static void regular_main(void)
{ {
clock_init();
rtiocrg_init();
session_startup_kernel(); session_startup_kernel();
puts("Accepting network sessions."); puts("Accepting network sessions.");
@ -242,11 +244,9 @@ int main(void)
puts("ARTIQ runtime built "__DATE__" "__TIME__"\n"); puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");
alloc_give(&_fheap, &_eheap - &_fheap); alloc_give(&_fheap, &_eheap - &_fheap);
clock_init();
rtiocrg_init();
rust_main(); // rust_main();
// regular_main(); regular_main();
return 0; return 0;
} }