forked from M-Labs/artiq
Rust: port clock, rtio_crg routines.
This commit is contained in:
parent
83940ae4a6
commit
9c18f1b555
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ use buffer_logger::BufferLogger;
|
|||
pub mod board;
|
||||
pub mod io;
|
||||
pub mod config;
|
||||
pub mod clock;
|
||||
pub mod rtio_crg;
|
||||
pub mod buffer_logger;
|
||||
pub mod session;
|
||||
|
||||
|
@ -28,7 +30,8 @@ pub unsafe extern fn rust_main() {
|
|||
static mut log_buffer: [u8; 4096] = [0; 4096];
|
||||
BufferLogger::new(&mut log_buffer[..])
|
||||
.register(move |logger| {
|
||||
info!("Accepting network sessions in Rust.");
|
||||
clock::init();
|
||||
rtio_crg::init();
|
||||
network_init();
|
||||
|
||||
let mut scheduler = io::Scheduler::new();
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use std::prelude::v1::*;
|
||||
use std::str;
|
||||
use std::io::{self, Read, ErrorKind};
|
||||
use config;
|
||||
use {config, rtio_crg};
|
||||
use self::protocol::*;
|
||||
|
||||
mod protocol;
|
||||
|
@ -26,14 +26,23 @@ extern {
|
|||
}
|
||||
|
||||
impl Session {
|
||||
pub fn start() -> Session {
|
||||
pub fn new() -> Session {
|
||||
unsafe { kloader_stop(); }
|
||||
Session {
|
||||
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 {
|
||||
kloader_stop();
|
||||
watchdog_init();
|
||||
|
@ -55,10 +64,14 @@ fn check_magic(stream: &mut ::io::TcpStream) -> io::Result<()> {
|
|||
}
|
||||
|
||||
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> {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -71,6 +84,7 @@ fn handle_request(stream: &mut ::io::TcpStream,
|
|||
Request::Ident =>
|
||||
write_reply(stream, Reply::Ident(::board::ident(&mut [0; 64]))),
|
||||
|
||||
// artiq_corelog
|
||||
Request::Log => {
|
||||
// Logging the packet with the log is inadvisable
|
||||
trace!("comm->host Log(...)");
|
||||
|
@ -84,6 +98,7 @@ fn handle_request(stream: &mut ::io::TcpStream,
|
|||
write_reply(stream, Reply::Log(""))
|
||||
}
|
||||
|
||||
// artiq_coreconfig
|
||||
Request::FlashRead { ref key } => {
|
||||
let value = config::read_to_end(key);
|
||||
write_reply(stream, Reply::FlashRead(&value))
|
||||
|
@ -106,6 +121,20 @@ fn handle_request(stream: &mut ::io::TcpStream,
|
|||
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!()
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +142,10 @@ fn handle_request(stream: &mut ::io::TcpStream,
|
|||
fn handle_requests(stream: &mut ::io::TcpStream,
|
||||
logger: &::buffer_logger::BufferLogger) -> io::Result<()> {
|
||||
try!(check_magic(stream));
|
||||
|
||||
let mut session = Session::new();
|
||||
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) {
|
||||
let addr = ::io::SocketAddr::new(::io::IP_ANY, 1381);
|
||||
let listener = ::io::TcpListener::bind(waiter, addr).unwrap();
|
||||
info!("accepting network sessions in Rust");
|
||||
|
||||
loop {
|
||||
let (mut stream, addr) = listener.accept().unwrap();
|
||||
info!("new connection from {:?}", addr);
|
||||
|
|
|
@ -206,6 +206,8 @@ static struct net_server_instance analyzer_inst = {
|
|||
|
||||
static void regular_main(void)
|
||||
{
|
||||
clock_init();
|
||||
rtiocrg_init();
|
||||
session_startup_kernel();
|
||||
|
||||
puts("Accepting network sessions.");
|
||||
|
@ -242,11 +244,9 @@ int main(void)
|
|||
puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");
|
||||
|
||||
alloc_give(&_fheap, &_eheap - &_fheap);
|
||||
clock_init();
|
||||
rtiocrg_init();
|
||||
|
||||
rust_main();
|
||||
// regular_main();
|
||||
// rust_main();
|
||||
regular_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue