2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-25 03:08:27 +08:00

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 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();

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::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);

View File

@ -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;
}