firmware: split out libboard_artiq from libboard.

This commit is contained in:
whitequark 2017-12-28 07:06:45 +00:00
parent 6801921fc0
commit ca419aa3c2
37 changed files with 352 additions and 247 deletions

View File

@ -26,11 +26,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "board"
version = "0.0.0"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"build_artiq 0.0.0",
"build_misoc 0.0.0",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "board_artiq"
version = "0.0.0"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"board 0.0.0",
"build_artiq 0.0.0",
]
[[package]]
@ -40,6 +47,10 @@ dependencies = [
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "build_misoc"
version = "0.0.0"
[[package]]
name = "byteorder"
version = "1.2.1"
@ -169,6 +180,7 @@ dependencies = [
"amp 0.0.0",
"backtrace_artiq 0.0.0",
"board 0.0.0",
"board_artiq 0.0.0",
"build_artiq 0.0.0",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.0 (git+https://github.com/m-labs/compiler-builtins?rev=97916b1)",

View File

@ -10,12 +10,10 @@ path = "lib.rs"
[build-dependencies]
cc = "1.0"
build_artiq = { path = "../libbuild_artiq" }
build_misoc = { path = "../libbuild_misoc" }
[dependencies]
bitflags = "1.0"
byteorder = { version = "1.0", default-features = false }
log = { version = "0.3", default-features = false }
[features]
uart_console = []

View File

@ -1,38 +1,18 @@
extern crate build_artiq;
extern crate build_misoc;
extern crate cc;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
fn build_vectors() {
println!("cargo:rerun-if-changed=vectors.S");
cc::Build::new()
.file("vectors.S")
.compile("vectors");
}
fn gen_hmc7043_writes() {
println!("cargo:rerun-if-changed=hmc7043_gen_writes.py");
println!("cargo:rerun-if-changed=hmc7043_guiexport_6gbps.py");
let hmc7043_writes =
Command::new("python3")
.arg("hmc7043_gen_writes.py")
.arg("hmc7043_guiexport_6gbps.py")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap();
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let mut f = File::create(out_dir.join("hmc7043_writes.rs")).unwrap();
write!(f, "{}", hmc7043_writes).unwrap();
}
use std::path::Path;
fn main() {
build_artiq::misoc_cfg();
build_vectors();
gen_hmc7043_writes();
build_misoc::cfg();
let triple = env::var("TARGET").unwrap();
let arch = triple.split("-").next().unwrap();
let vectors_path = Path::new(arch).join("vectors.S");
println!("cargo:rerun-if-changed={}", vectors_path.to_str().unwrap());
cc::Build::new()
.file(vectors_path)
.compile("vectors");
}

View File

@ -1,6 +1,7 @@
use core::i64;
use csr;
const INIT: u64 = ::core::i64::MAX as u64;
const INIT: u64 = i64::MAX as u64;
const FREQ: u64 = csr::CONFIG_CLOCK_FREQUENCY as u64;
pub fn init() {
@ -35,49 +36,3 @@ pub fn spin_us(interval: u64) {
}
}
}
#[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)
}
}
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

@ -1,9 +1,41 @@
use core::{str, fmt};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
AlreadyLocked,
SpaceExhausted,
Truncated { offset: usize },
InvalidSize { offset: usize, size: usize },
MissingSeparator { offset: usize },
Utf8Error(str::Utf8Error)
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Error::AlreadyLocked =>
write!(f, "attempt at reentrant access"),
&Error::SpaceExhausted =>
write!(f, "space exhausted"),
&Error::Truncated { offset }=>
write!(f, "truncated record at offset {}", offset),
&Error::InvalidSize { offset, size } =>
write!(f, "invalid record size {} at offset {}", size, offset),
&Error::MissingSeparator { offset } =>
write!(f, "missing separator at offset {}", offset),
&Error::Utf8Error(err) =>
write!(f, "{}", err)
}
}
}
#[cfg(has_spiflash)]
mod imp {
use core::str;
use byteorder::{ByteOrder, BigEndian};
use cache;
use spiflash;
use super::Error;
// One flash sector immediately after the bootloader.
const ADDR: usize = ::mem::FLASH_BOOT_ADDRESS - spiflash::PAGE_SIZE;
@ -12,17 +44,18 @@ mod imp {
mod lock {
use core::slice;
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use super::Error;
static LOCKED: AtomicUsize = ATOMIC_USIZE_INIT;
pub struct Lock;
impl Lock {
pub fn take() -> Result<Lock, ()> {
pub fn take() -> Result<Lock, Error> {
if LOCKED.swap(1, Ordering::SeqCst) != 0 {
Err(()) // already locked
Err(Error::AlreadyLocked)
} else {
Ok(Lock) // locked now
Ok(Lock)
}
}
@ -53,29 +86,27 @@ mod imp {
}
impl<'a> Iterator for Iter<'a> {
type Item = Result<(&'a [u8], &'a [u8]), ()>;
type Item = Result<(&'a [u8], &'a [u8]), Error>;
fn next(&mut self) -> Option<Self::Item> {
let data = &self.data[self.offset..];
if data.len() < 4 {
error!("offset {}: truncated record", self.offset);
return Some(Err(()))
// error!("offset {}: truncated record", self.offset);
return Some(Err(Error::Truncated { offset: self.offset }))
}
let record_size = BigEndian::read_u32(data) as usize;
if record_size == !0 /* all ones; erased flash */ {
return None
} else if record_size < 4 || record_size > data.len() {
error!("offset {}: invalid record size {}", self.offset, record_size);
return Some(Err(()))
return Some(Err(Error::InvalidSize { offset: self.offset, size: record_size }))
}
let record_body = &data[4..record_size];
match record_body.iter().position(|&x| x == 0) {
None => {
error!("offset {}: missing separator", self.offset);
Some(Err(()))
return Some(Err(Error::MissingSeparator { offset: self.offset }))
}
Some(pos) => {
self.offset += record_size;
@ -87,7 +118,7 @@ mod imp {
}
}
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(key: &str, f: F) -> R {
pub fn read<F: FnOnce(Result<&[u8], Error>) -> R, R>(key: &str, f: F) -> R {
f(Lock::take().and_then(|lock| {
let mut iter = Iter::new(lock.data());
let mut value = &[][..];
@ -102,52 +133,53 @@ mod imp {
}))
}
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(key: &str, f: F) -> R {
pub fn read_str<F: FnOnce(Result<&str, Error>) -> R, R>(key: &str, f: F) -> R {
read(key, |result| {
f(result.and_then(|value| str::from_utf8(value).map_err(|_| ())))
f(result.and_then(|value| str::from_utf8(value).map_err(Error::Utf8Error)))
})
}
unsafe fn append_at<'a>(mut data: &'a [u8], key: &[u8], value: &[u8]) -> Result<&'a [u8], ()> {
unsafe fn append_at(data: &[u8], mut offset: usize,
key: &[u8], value: &[u8]) -> Result<usize, Error> {
let record_size = 4 + key.len() + 1 + value.len();
if data.len() < record_size {
return Err(())
if offset + record_size > data.len() {
return Err(Error::SpaceExhausted)
}
let mut record_size_bytes = [0u8; 4];
BigEndian::write_u32(&mut record_size_bytes[..], record_size as u32);
spiflash::write(data.as_ptr() as usize, &record_size_bytes[..]);
data = &data[record_size_bytes.len()..];
{
let mut write = |payload| {
spiflash::write(data.as_ptr().offset(offset as isize) as usize, payload);
offset += payload.len();
};
spiflash::write(data.as_ptr() as usize, key);
data = &data[key.len()..];
write(&record_size_bytes[..]);
write(key);
write(&[0]);
write(value);
cache::flush_l2_cache();
}
spiflash::write(data.as_ptr() as usize, &[0]);
data = &data[1..];
spiflash::write(data.as_ptr() as usize, value);
data = &data[value.len()..];
cache::flush_l2_cache();
Ok(data)
Ok(offset)
}
fn compact() -> Result<(), ()> {
fn compact() -> Result<(), Error> {
let lock = Lock::take()?;
let data = lock.data();
static mut OLD_DATA: [u8; SIZE] = [0; SIZE];
let old_data = unsafe {
OLD_DATA.copy_from_slice(lock.data());
OLD_DATA.copy_from_slice(data);
&OLD_DATA[..]
};
let mut data = lock.data();
unsafe { spiflash::erase_sector(data.as_ptr() as usize) };
// This is worst-case quadratic, but we're limited by a small SPI flash sector size,
// so it does not really matter.
let mut offset = 0;
let mut iter = Iter::new(old_data);
while let Some(result) = iter.next() {
let (key, mut value) = result?;
@ -159,47 +191,48 @@ mod imp {
value = next_value
}
}
data = unsafe { append_at(data, key, value)? };
offset = unsafe { append_at(data, offset, key, value)? };
}
Ok(())
}
fn append(key: &str, value: &[u8]) -> Result<(), ()> {
fn append(key: &str, value: &[u8]) -> Result<(), Error> {
let lock = Lock::take()?;
let data = lock.data();
let free = {
let mut iter = Iter::new(lock.data());
let free_offset = {
let mut iter = Iter::new(data);
while let Some(result) = iter.next() {
let _ = result?;
}
&iter.data[iter.offset..]
iter.offset
};
unsafe { append_at(free, key.as_bytes(), value)? };
unsafe { append_at(data, free_offset, key.as_bytes(), value)? };
Ok(())
}
pub fn write(key: &str, value: &[u8]) -> Result<(), ()> {
pub fn write(key: &str, value: &[u8]) -> Result<(), Error> {
match append(key, value) {
Ok(()) => (),
Err(()) => {
Err(Error::SpaceExhausted) => {
compact()?;
append(key, value)?;
append(key, value)
}
res => res
}
Ok(())
}
pub fn remove(key: &str) -> Result<(), ()> {
pub fn remove(key: &str) -> Result<(), Error> {
write(key, &[])
}
pub fn erase() -> Result<(), ()> {
pub fn erase() -> Result<(), Error> {
let lock = Lock::take()?;
let data = lock.data();
unsafe { spiflash::erase_sector(lock.data().as_ptr() as usize) };
unsafe { spiflash::erase_sector(data.as_ptr() as usize) };
cache::flush_l2_cache();
Ok(())
@ -208,23 +241,23 @@ mod imp {
#[cfg(not(has_spiflash))]
mod imp {
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(_key: &str, f: F) -> R {
pub fn read<F: FnOnce(Result<&[u8], Error>) -> R, R>(_key: &str, f: F) -> R {
f(Err(()))
}
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(_key: &str, f: F) -> R {
pub fn read_str<F: FnOnce(Result<&str, Error>) -> R, R>(_key: &str, f: F) -> R {
f(Err(()))
}
pub fn write(_key: &str, _value: &[u8]) -> Result<(), ()> {
pub fn write(_key: &str, _value: &[u8]) -> Result<(), Error> {
Err(())
}
pub fn remove(_key: &str) -> Result<(), ()> {
pub fn remove(_key: &str) -> Result<(), Error> {
Err(())
}
pub fn erase() -> Result<(), ()> {
pub fn erase() -> Result<(), Error> {
Err(())
}
}

View File

@ -0,0 +1,13 @@
use core::{ptr, cmp, str};
use csr;
pub fn read(buf: &mut [u8]) -> &str {
unsafe {
let len = ptr::read_volatile(csr::IDENTIFIER_MEM_BASE);
let len = cmp::min(len as usize, buf.len());
for i in 0..len {
buf[i] = ptr::read_volatile(csr::IDENTIFIER_MEM_BASE.offset(1 + i as isize)) as u8
}
str::from_utf8_unchecked(&buf[..len])
}
}

View File

@ -1,58 +1,22 @@
#![feature(asm, lang_items)]
#![no_std]
#![feature(asm)]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
#[macro_use]
extern crate log;
use core::{cmp, ptr, str};
#[cfg(target_arch = "or1k")]
#[path = "or1k/mod.rs"]
mod arch;
pub use arch::*;
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/mem.rs"));
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/csr.rs"));
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/sdram_phy.rs"));
pub mod spr;
pub mod irq;
pub mod cache;
pub mod pcr;
pub mod ident;
pub mod clock;
pub mod uart;
#[cfg(feature = "uart_console")]
pub mod uart_console;
#[cfg(has_spiflash)]
pub mod spiflash;
pub mod config;
pub mod i2c;
pub mod spi;
#[cfg(has_si5324)]
pub mod si5324;
#[cfg(has_serwb_phy_amc)]
pub mod serwb;
#[cfg(has_hmc830_7043)]
pub mod hmc830_7043;
#[cfg(has_ad9154)]
#[allow(dead_code)]
mod ad9154_reg;
#[cfg(has_ad9154)]
pub mod ad9154;
pub mod boot;
#[cfg(feature = "uart_console")]
pub use uart_console::Console;
pub fn ident(buf: &mut [u8]) -> &str {
unsafe {
let len = ptr::read_volatile(csr::IDENTIFIER_MEM_BASE);
let len = cmp::min(len as usize, buf.len());
for i in 0..len {
buf[i] = ptr::read_volatile(csr::IDENTIFIER_MEM_BASE.offset(1 + i as isize)) as u8
}
str::from_utf8_unchecked(&buf[..len])
}
}
pub mod uart_console;

View File

@ -1,19 +1,19 @@
use core::ptr;
use spr::{self, mfspr, mtspr};
use super::spr::*;
use csr;
use mem;
pub fn flush_cpu_icache() {
unsafe {
let iccfgr = mfspr(spr::SPR_ICCFGR);
let ways = 1 << (iccfgr & spr::SPR_ICCFGR_NCW);
let set_size = 1 << ((iccfgr & spr::SPR_ICCFGR_NCS) >> 3);
let block_size = if iccfgr & spr::SPR_ICCFGR_CBS != 0 { 32 } else { 16 };
let iccfgr = mfspr(SPR_ICCFGR);
let ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
let set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
let block_size = if iccfgr & SPR_ICCFGR_CBS != 0 { 32 } else { 16 };
let size = set_size * ways * block_size;
let mut i = 0;
while i < size {
mtspr(spr::SPR_ICBIR, i);
mtspr(SPR_ICBIR, i);
i += block_size;
}
}
@ -21,15 +21,15 @@ pub fn flush_cpu_icache() {
pub fn flush_cpu_dcache() {
unsafe {
let dccfgr = mfspr(spr::SPR_DCCFGR);
let ways = 1 << (dccfgr & spr::SPR_ICCFGR_NCW);
let set_size = 1 << ((dccfgr & spr::SPR_DCCFGR_NCS) >> 3);
let block_size = if dccfgr & spr::SPR_DCCFGR_CBS != 0 { 32 } else { 16 };
let dccfgr = mfspr(SPR_DCCFGR);
let ways = 1 << (dccfgr & SPR_ICCFGR_NCW);
let set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
let block_size = if dccfgr & SPR_DCCFGR_CBS != 0 { 32 } else { 16 };
let size = set_size * ways * block_size;
let mut i = 0;
while i < size {
mtspr(spr::SPR_DCBIR, i);
mtspr(SPR_DCBIR, i);
i += block_size;
}
}

View File

@ -0,0 +1,3 @@
pub mod spr;
pub mod irq;
pub mod cache;

View File

@ -1,5 +1,3 @@
#![allow(dead_code)]
use core::cmp;
use csr;
@ -8,7 +6,7 @@ pub const PAGE_SIZE: usize = csr::CONFIG_SPIFLASH_PAGE_SIZE as usize;
const PAGE_MASK: usize = PAGE_SIZE - 1;
const CMD_PP: u8 = 0x02;
const CMD_WRDI: u8 = 0x04;
// const CMD_WRDI: u8 = 0x04;
const CMD_RDSR: u8 = 0x05;
const CMD_WREN: u8 = 0x06;
const CMD_SE: u8 = 0xd8;

View File

@ -0,0 +1,19 @@
[package]
authors = ["M-Labs"]
name = "board_artiq"
version = "0.0.0"
build = "build.rs"
[lib]
name = "board_artiq"
path = "lib.rs"
[build-dependencies]
build_artiq = { path = "../libbuild_artiq" }
[dependencies]
bitflags = "1.0"
board = { path = "../libboard" }
[features]
uart_console = []

View File

@ -1,3 +1,5 @@
#![allow(dead_code)]
pub const SPI_INTFCONFA : u16 = 0x000;
pub const SOFTRESET : u8 = 1 << 0;
pub const LSBFIRST : u8 = 1 << 1;

View File

@ -1,4 +1,4 @@
use irq;
use board::irq;
pub unsafe fn reboot() -> ! {
irq::set_ie(false);

View File

@ -0,0 +1,28 @@
extern crate build_artiq;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
fn gen_hmc7043_writes() {
println!("cargo:rerun-if-changed=hmc7043_gen_writes.py");
println!("cargo:rerun-if-changed=hmc7043_guiexport_6gbps.py");
let hmc7043_writes =
Command::new("python3")
.arg("hmc7043_gen_writes.py")
.arg("hmc7043_guiexport_6gbps.py")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap();
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let mut f = File::create(out_dir.join("hmc7043_writes.rs")).unwrap();
write!(f, "{}", hmc7043_writes).unwrap();
}
fn main() {
gen_hmc7043_writes();
}

View File

@ -0,0 +1,25 @@
#![feature(asm, lang_items)]
#![no_std]
#[macro_use]
extern crate bitflags;
extern crate board;
pub mod pcr;
pub mod i2c;
pub mod spi;
#[cfg(has_si5324)]
pub mod si5324;
#[cfg(has_serwb_phy_amc)]
pub mod serwb;
#[cfg(has_hmc830_7043)]
pub mod hmc830_7043;
#[cfg(has_ad9154)]
mod ad9154_reg;
#[cfg(has_ad9154)]
pub mod ad9154;
pub mod boot;

View File

@ -1,4 +1,4 @@
use spr::*;
use board::spr::*;
bitflags! {
pub struct Counters: u32 {

View File

@ -21,7 +21,7 @@ pub fn wait_init() {
error!("incorrect RTM identifier: 0x{:08x}", rtm_identifier);
// proceed anyway
}
unsafe {
debug!("AMC serwb settings:");
debug!(" delay_min_found: {}", csr::serwb_phy_amc::control_delay_min_found_read());

View File

@ -0,0 +1,8 @@
[package]
authors = ["M-Labs"]
name = "build_misoc"
version = "0.0.0"
[lib]
name = "build_misoc"
path = "lib.rs"

View File

@ -0,0 +1,15 @@
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
pub fn cfg() {
let out_dir = env::var("BUILDINC_DIRECTORY").unwrap();
let cfg_path = Path::new(&out_dir).join("generated").join("rust-cfg");
println!("cargo:rerun-if-changed={}", cfg_path.to_str().unwrap());
let f = BufReader::new(File::open(&cfg_path).unwrap());
for line in f.lines() {
println!("cargo:rustc-cfg={}", line.unwrap());
}
}

View File

@ -2,13 +2,14 @@
extern crate log;
extern crate log_buffer;
#[macro_use]
extern crate board;
use core::cell::{Cell, RefCell};
use core::fmt::Write;
use log::{Log, LogMetadata, LogRecord, LogLevelFilter, MaxLogLevelFilter};
use log_buffer::LogBuffer;
use board::{Console, clock};
use board::clock;
pub struct BufferLogger {
buffer: RefCell<LogBuffer<&'static mut [u8]>>,
@ -110,9 +111,8 @@ impl Log for BufferLogger {
record.level(), record.target(), record.args()).unwrap();
if record.level() <= self.uart_filter.get() {
writeln!(Console,
"[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
record.level(), record.target(), record.args()).unwrap();
println!("[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
record.level(), record.target(), record.args());
}
}
}

View File

@ -16,11 +16,12 @@ build_artiq = { path = "../libbuild_artiq" }
byteorder = { version = "1.0", default-features = false }
cslice = { version = "0.3" }
log = { version = "0.3", default-features = false }
board = { path = "../libboard", features = ["uart_console"] }
alloc_list = { path = "../liballoc_list" }
std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] }
logger_artiq = { path = "../liblogger_artiq" }
backtrace_artiq = { path = "../libbacktrace_artiq" }
board = { path = "../libboard", features = ["uart_console"] }
board_artiq = { path = "../libboard_artiq" }
proto = { path = "../libproto", features = ["log"] }
amp = { path = "../libamp" }
drtioaux = { path = "../libdrtioaux" }

View File

@ -120,14 +120,14 @@ mod drtio_i2c {
}
mod i2c {
use board;
use board_artiq::i2c as local_i2c;
use super::drtio_i2c;
pub fn start(busno: u32) -> Result<(), ()> {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::i2c::start(node_busno)
local_i2c::start(node_busno)
} else {
drtio_i2c::start(nodeno, node_busno)
}
@ -137,7 +137,7 @@ mod i2c {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::i2c::restart(node_busno)
local_i2c::restart(node_busno)
} else {
drtio_i2c::restart(nodeno, node_busno)
}
@ -147,7 +147,7 @@ mod i2c {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::i2c::stop(node_busno)
local_i2c::stop(node_busno)
} else {
drtio_i2c::stop(nodeno, node_busno)
}
@ -157,7 +157,7 @@ mod i2c {
let nodeno = (busno >> 16 )as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::i2c::write(node_busno, data)
local_i2c::write(node_busno, data)
} else {
drtio_i2c::write(nodeno, node_busno, data)
}
@ -167,7 +167,7 @@ mod i2c {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::i2c::read(node_busno, ack)
local_i2c::read(node_busno, ack)
} else {
drtio_i2c::read(nodeno, node_busno, ack)
}
@ -254,11 +254,13 @@ mod drtio_spi {
#[cfg(not(has_drtio))]
mod drtio_spi {
pub fn set_config(_nodeno: u8, _busno: u8, _flags: u8, _write_div: u8, _read_div: u8) -> Result<(), ()> {
pub fn set_config(_nodeno: u8, _busno: u8, _flags: u8,
_write_div: u8, _read_div: u8) -> Result<(), ()> {
Err(())
}
pub fn set_xfer(_nodeno: u8, _busno: u8, _chip_select: u16, _write_length: u8, _read_length: u8) -> Result<(), ()> {
pub fn set_xfer(_nodeno: u8, _busno: u8, _chip_select: u16,
_write_length: u8, _read_length: u8) -> Result<(), ()> {
Err(())
}
@ -272,14 +274,14 @@ mod drtio_spi {
}
mod spi {
use board;
use board_artiq::spi as local_spi;
use super::drtio_spi;
pub fn set_config(busno: u32, flags: u8, write_div: u8, read_div: u8) -> Result<(), ()> {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::spi::set_config(node_busno, flags, write_div, read_div)
local_spi::set_config(node_busno, flags, write_div, read_div)
} else {
drtio_spi::set_config(nodeno, node_busno, flags, write_div, read_div)
}
@ -289,7 +291,7 @@ mod spi {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::spi::set_xfer(node_busno, chip_select, write_length, read_length)
local_spi::set_xfer(node_busno, chip_select, write_length, read_length)
} else {
drtio_spi::set_xfer(nodeno, node_busno, chip_select, write_length, read_length)
}
@ -299,7 +301,7 @@ mod spi {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::spi::write(node_busno, data)
local_spi::write(node_busno, data)
} else {
drtio_spi::write(nodeno, node_busno, data)
}
@ -309,7 +311,7 @@ mod spi {
let nodeno = (busno >> 16) as u8;
let node_busno = busno as u8;
if nodeno == 0 {
board::spi::read(node_busno)
local_spi::read(node_busno)
} else {
drtio_spi::read(nodeno, node_busno)
}

View File

@ -17,6 +17,7 @@ extern crate logger_artiq;
extern crate backtrace_artiq;
#[macro_use]
extern crate board;
extern crate board_artiq;
extern crate proto;
extern crate amp;
#[cfg(has_drtio)]
@ -41,6 +42,7 @@ mod rtio_dma;
mod mgmt;
mod kernel;
mod kern_hwreq;
mod watchdog;
mod session;
#[cfg(any(has_rtio_moninj, has_drtio))]
mod moninj;
@ -51,7 +53,7 @@ fn startup() {
board::clock::init();
info!("ARTIQ runtime starting...");
info!("software version {}", include_str!(concat!(env!("OUT_DIR"), "/git-describe")));
info!("gateware version {}", board::ident(&mut [0; 64]));
info!("gateware version {}", board::ident::read(&mut [0; 64]));
#[cfg(has_serwb_phy_amc)]
board::serwb::wait_init();
@ -69,7 +71,7 @@ fn startup() {
info!("continuing boot");
#[cfg(has_i2c)]
board::i2c::init();
board_artiq::i2c::init();
#[cfg(si5324_free_running)]
setup_si5324_free_running();
#[cfg(has_hmc830_7043)]
@ -106,27 +108,27 @@ fn setup_si5324_free_running()
#[cfg(has_ethmac)]
fn startup_ethernet() {
let hardware_addr;
match config::read_str("mac", |r| r?.parse()) {
Err(()) => {
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
Ok(addr) => {
match config::read_str("mac", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => {
hardware_addr = addr;
info!("using MAC address {}", hardware_addr);
}
_ => {
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
warn!("using default MAC address {}; consider changing it", hardware_addr);
}
}
let protocol_addr;
match config::read_str("ip", |r| r?.parse()) {
Err(()) => {
protocol_addr = IpAddress::v4(192, 168, 1, 50);
info!("using default IP address {}", protocol_addr);
}
Ok(addr) => {
match config::read_str("ip", |r| r.map(|s| s.parse())) {
Ok(Ok(addr)) => {
protocol_addr = addr;
info!("using IP address {}", protocol_addr);
}
_ => {
protocol_addr = IpAddress::v4(192, 168, 1, 50);
info!("using default IP address {}", protocol_addr);
}
}
// fn _net_trace_writer<U>(timestamp: u64, printer: smoltcp::wire::PrettyPrinter<U>)
@ -159,26 +161,24 @@ fn startup_ethernet() {
#[cfg(has_rtio_analyzer)]
io.spawn(4096, analyzer::thread);
match config::read_str("log_level", |r| r?.parse()) {
Err(()) => (),
Ok(log_level_filter) => {
match config::read_str("log_level", |r| r.map(|s| s.parse())) {
Ok(Ok(log_level_filter)) => {
info!("log level set to {} by `log_level` config key",
log_level_filter);
logger_artiq::BufferLogger::with(|logger|
logger.set_max_log_level(log_level_filter));
}
_ => info!("log level set to INFO by default")
}
match config::read_str("uart_log_level", |r| r?.parse()) {
Err(()) => {
info!("UART log level set to INFO by default");
},
Ok(uart_log_level_filter) => {
match config::read_str("uart_log_level", |r| r.map(|s| s.parse())) {
Ok(Ok(uart_log_level_filter)) => {
info!("UART log level set to {} by `uart_log_level` config key",
uart_log_level_filter);
logger_artiq::BufferLogger::with(|logger|
logger.set_uart_log_level(uart_log_level_filter));
}
_ => info!("UART log level set to INFO by default")
}
let mut net_stats = ethmac::EthernetStatistics::new();
@ -247,7 +247,7 @@ pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u3
if config::read_str("panic_reboot", |r| r == Ok("1")) {
println!("rebooting...");
unsafe { board::boot::reboot() }
unsafe { board_artiq::boot::reboot() }
} else {
println!("halting.");
println!("use `artiq_coreconfig write -s panic_reboot 1` to reboot instead");

View File

@ -1,9 +1,9 @@
use board_artiq::boot;
use std::io::{self, Read, Write};
use log::LogLevelFilter;
use logger_artiq::BufferLogger;
use sched::Io;
use sched::{TcpListener, TcpStream};
use board;
use proto::WriteExt;
use mgmt_proto::*;
@ -86,14 +86,14 @@ fn worker(io: &Io, stream: &mut TcpStream) -> io::Result<()> {
Reply::RebootImminent.write_to(stream)?;
stream.close()?;
stream.flush()?;
unsafe { board::boot::hotswap(&firmware) }
unsafe { boot::hotswap(&firmware) }
},
Request::Reboot => {
Reply::RebootImminent.write_to(stream)?;
stream.close()?;
warn!("rebooting");
unsafe { board::boot::reboot() }
unsafe { boot::reboot() }
}
};
}

View File

@ -226,12 +226,13 @@ pub fn startup(io: &Io) {
info!("using external startup RTIO clock");
RtioClock::External
},
Err(()) => {
Err(_) => {
info!("using internal startup RTIO clock (by default)");
RtioClock::Internal
},
Ok(_) => {
error!("unrecognized startup_clock configuration entry, using internal RTIO clock");
error!("unrecognized startup_clock configuration entry, \
using internal RTIO clock");
RtioClock::Internal
}
}

View File

@ -15,6 +15,7 @@ use rtio_mgt;
use rtio_dma::Manager as DmaManager;
use cache::Cache;
use kern_hwreq;
use watchdog::WatchdogSet;
use rpc_proto as rpc;
use session_proto as host;
@ -66,7 +67,7 @@ enum KernelState {
struct Session<'a> {
congress: &'a mut Congress,
kernel_state: KernelState,
watchdog_set: board::clock::WatchdogSet,
watchdog_set: WatchdogSet,
log_buffer: String
}
@ -75,7 +76,7 @@ impl<'a> Session<'a> {
Session {
congress: congress,
kernel_state: KernelState::Absent,
watchdog_set: board::clock::WatchdogSet::new(),
watchdog_set: WatchdogSet::new(),
log_buffer: String::new()
}
}
@ -226,7 +227,7 @@ fn process_host_message(io: &Io,
match host_read(stream)? {
host::Request::SystemInfo => {
host_write(stream, host::Reply::SystemInfo {
ident: board::ident(&mut [0; 64]),
ident: board::ident::read(&mut [0; 64]),
finished_cleanly: session.congress.finished_cleanly.get()
})?;
session.congress.finished_cleanly.set(true);
@ -238,7 +239,7 @@ fn process_host_message(io: &Io,
config::read(key, |result| {
match result {
Ok(value) => host_write(stream, host::Reply::FlashRead(&value)),
Err(()) => host_write(stream, host::Reply::FlashError)
Err(_) => host_write(stream, host::Reply::FlashError)
}
})
}

View File

@ -0,0 +1,47 @@
use board::clock;
#[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 = clock::get_ms() + interval;
return Ok(index)
}
}
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| clock::get_ms() > wd.threshold)
}
}