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 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();
|
||||||
|
|
|
@ -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::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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue