mirror of https://github.com/m-labs/artiq.git
firmware: split out libboard_artiq from libboard.
This commit is contained in:
parent
6801921fc0
commit
ca419aa3c2
|
@ -26,11 +26,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
name = "board"
|
name = "board"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"build_misoc 0.0.0",
|
||||||
"build_artiq 0.0.0",
|
|
||||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
|
@ -40,6 +47,10 @@ dependencies = [
|
||||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "build_misoc"
|
||||||
|
version = "0.0.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -169,6 +180,7 @@ dependencies = [
|
||||||
"amp 0.0.0",
|
"amp 0.0.0",
|
||||||
"backtrace_artiq 0.0.0",
|
"backtrace_artiq 0.0.0",
|
||||||
"board 0.0.0",
|
"board 0.0.0",
|
||||||
|
"board_artiq 0.0.0",
|
||||||
"build_artiq 0.0.0",
|
"build_artiq 0.0.0",
|
||||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"compiler_builtins 0.1.0 (git+https://github.com/m-labs/compiler-builtins?rev=97916b1)",
|
||||||
|
|
|
@ -10,12 +10,10 @@ path = "lib.rs"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "1.0"
|
cc = "1.0"
|
||||||
build_artiq = { path = "../libbuild_artiq" }
|
build_misoc = { path = "../libbuild_misoc" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.0"
|
|
||||||
byteorder = { version = "1.0", default-features = false }
|
byteorder = { version = "1.0", default-features = false }
|
||||||
log = { version = "0.3", default-features = false }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
uart_console = []
|
uart_console = []
|
||||||
|
|
|
@ -1,38 +1,18 @@
|
||||||
extern crate build_artiq;
|
extern crate build_misoc;
|
||||||
extern crate cc;
|
extern crate cc;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::path::Path;
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
build_artiq::misoc_cfg();
|
build_misoc::cfg();
|
||||||
build_vectors();
|
|
||||||
gen_hmc7043_writes();
|
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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
use core::i64;
|
||||||
use csr;
|
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;
|
const FREQ: u64 = csr::CONFIG_CLOCK_FREQUENCY as u64;
|
||||||
|
|
||||||
pub fn init() {
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)]
|
#[cfg(has_spiflash)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use core::str;
|
use core::str;
|
||||||
use byteorder::{ByteOrder, BigEndian};
|
use byteorder::{ByteOrder, BigEndian};
|
||||||
use cache;
|
use cache;
|
||||||
use spiflash;
|
use spiflash;
|
||||||
|
use super::Error;
|
||||||
|
|
||||||
// One flash sector immediately after the bootloader.
|
// One flash sector immediately after the bootloader.
|
||||||
const ADDR: usize = ::mem::FLASH_BOOT_ADDRESS - spiflash::PAGE_SIZE;
|
const ADDR: usize = ::mem::FLASH_BOOT_ADDRESS - spiflash::PAGE_SIZE;
|
||||||
|
@ -12,17 +44,18 @@ mod imp {
|
||||||
mod lock {
|
mod lock {
|
||||||
use core::slice;
|
use core::slice;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
||||||
|
use super::Error;
|
||||||
|
|
||||||
static LOCKED: AtomicUsize = ATOMIC_USIZE_INIT;
|
static LOCKED: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||||
|
|
||||||
pub struct Lock;
|
pub struct Lock;
|
||||||
|
|
||||||
impl Lock {
|
impl Lock {
|
||||||
pub fn take() -> Result<Lock, ()> {
|
pub fn take() -> Result<Lock, Error> {
|
||||||
if LOCKED.swap(1, Ordering::SeqCst) != 0 {
|
if LOCKED.swap(1, Ordering::SeqCst) != 0 {
|
||||||
Err(()) // already locked
|
Err(Error::AlreadyLocked)
|
||||||
} else {
|
} else {
|
||||||
Ok(Lock) // locked now
|
Ok(Lock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,29 +86,27 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Iter<'a> {
|
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> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let data = &self.data[self.offset..];
|
let data = &self.data[self.offset..];
|
||||||
|
|
||||||
if data.len() < 4 {
|
if data.len() < 4 {
|
||||||
error!("offset {}: truncated record", self.offset);
|
// error!("offset {}: truncated record", self.offset);
|
||||||
return Some(Err(()))
|
return Some(Err(Error::Truncated { offset: self.offset }))
|
||||||
}
|
}
|
||||||
|
|
||||||
let record_size = BigEndian::read_u32(data) as usize;
|
let record_size = BigEndian::read_u32(data) as usize;
|
||||||
if record_size == !0 /* all ones; erased flash */ {
|
if record_size == !0 /* all ones; erased flash */ {
|
||||||
return None
|
return None
|
||||||
} else if record_size < 4 || record_size > data.len() {
|
} else if record_size < 4 || record_size > data.len() {
|
||||||
error!("offset {}: invalid record size {}", self.offset, record_size);
|
return Some(Err(Error::InvalidSize { offset: self.offset, size: record_size }))
|
||||||
return Some(Err(()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let record_body = &data[4..record_size];
|
let record_body = &data[4..record_size];
|
||||||
match record_body.iter().position(|&x| x == 0) {
|
match record_body.iter().position(|&x| x == 0) {
|
||||||
None => {
|
None => {
|
||||||
error!("offset {}: missing separator", self.offset);
|
return Some(Err(Error::MissingSeparator { offset: self.offset }))
|
||||||
Some(Err(()))
|
|
||||||
}
|
}
|
||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
self.offset += record_size;
|
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| {
|
f(Lock::take().and_then(|lock| {
|
||||||
let mut iter = Iter::new(lock.data());
|
let mut iter = Iter::new(lock.data());
|
||||||
let mut value = &[][..];
|
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| {
|
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();
|
let record_size = 4 + key.len() + 1 + value.len();
|
||||||
if data.len() < record_size {
|
if offset + record_size > data.len() {
|
||||||
return Err(())
|
return Err(Error::SpaceExhausted)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut record_size_bytes = [0u8; 4];
|
let mut record_size_bytes = [0u8; 4];
|
||||||
BigEndian::write_u32(&mut record_size_bytes[..], record_size as u32);
|
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);
|
||||||
spiflash::write(data.as_ptr() as usize, key);
|
offset += payload.len();
|
||||||
data = &data[key.len()..];
|
};
|
||||||
|
|
||||||
spiflash::write(data.as_ptr() as usize, &[0]);
|
|
||||||
data = &data[1..];
|
|
||||||
|
|
||||||
spiflash::write(data.as_ptr() as usize, value);
|
|
||||||
data = &data[value.len()..];
|
|
||||||
|
|
||||||
|
write(&record_size_bytes[..]);
|
||||||
|
write(key);
|
||||||
|
write(&[0]);
|
||||||
|
write(value);
|
||||||
cache::flush_l2_cache();
|
cache::flush_l2_cache();
|
||||||
|
|
||||||
Ok(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compact() -> Result<(), ()> {
|
Ok(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compact() -> Result<(), Error> {
|
||||||
let lock = Lock::take()?;
|
let lock = Lock::take()?;
|
||||||
|
let data = lock.data();
|
||||||
|
|
||||||
static mut OLD_DATA: [u8; SIZE] = [0; SIZE];
|
static mut OLD_DATA: [u8; SIZE] = [0; SIZE];
|
||||||
let old_data = unsafe {
|
let old_data = unsafe {
|
||||||
OLD_DATA.copy_from_slice(lock.data());
|
OLD_DATA.copy_from_slice(data);
|
||||||
&OLD_DATA[..]
|
&OLD_DATA[..]
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut data = lock.data();
|
|
||||||
unsafe { spiflash::erase_sector(data.as_ptr() as usize) };
|
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,
|
// This is worst-case quadratic, but we're limited by a small SPI flash sector size,
|
||||||
// so it does not really matter.
|
// so it does not really matter.
|
||||||
|
let mut offset = 0;
|
||||||
let mut iter = Iter::new(old_data);
|
let mut iter = Iter::new(old_data);
|
||||||
while let Some(result) = iter.next() {
|
while let Some(result) = iter.next() {
|
||||||
let (key, mut value) = result?;
|
let (key, mut value) = result?;
|
||||||
|
@ -159,47 +191,48 @@ mod imp {
|
||||||
value = next_value
|
value = next_value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = unsafe { append_at(data, key, value)? };
|
offset = unsafe { append_at(data, offset, key, value)? };
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append(key: &str, value: &[u8]) -> Result<(), ()> {
|
fn append(key: &str, value: &[u8]) -> Result<(), Error> {
|
||||||
let lock = Lock::take()?;
|
let lock = Lock::take()?;
|
||||||
|
let data = lock.data();
|
||||||
|
|
||||||
let free = {
|
let free_offset = {
|
||||||
let mut iter = Iter::new(lock.data());
|
let mut iter = Iter::new(data);
|
||||||
while let Some(result) = iter.next() {
|
while let Some(result) = iter.next() {
|
||||||
let _ = result?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(key: &str, value: &[u8]) -> Result<(), ()> {
|
pub fn write(key: &str, value: &[u8]) -> Result<(), Error> {
|
||||||
match append(key, value) {
|
match append(key, value) {
|
||||||
Ok(()) => (),
|
Err(Error::SpaceExhausted) => {
|
||||||
Err(()) => {
|
|
||||||
compact()?;
|
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, &[])
|
write(key, &[])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn erase() -> Result<(), ()> {
|
pub fn erase() -> Result<(), Error> {
|
||||||
let lock = Lock::take()?;
|
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();
|
cache::flush_l2_cache();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -208,23 +241,23 @@ mod imp {
|
||||||
|
|
||||||
#[cfg(not(has_spiflash))]
|
#[cfg(not(has_spiflash))]
|
||||||
mod imp {
|
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(()))
|
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(()))
|
f(Err(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(_key: &str, _value: &[u8]) -> Result<(), ()> {
|
pub fn write(_key: &str, _value: &[u8]) -> Result<(), Error> {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(_key: &str) -> Result<(), ()> {
|
pub fn remove(_key: &str) -> Result<(), Error> {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn erase() -> Result<(), ()> {
|
pub fn erase() -> Result<(), Error> {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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])
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,58 +1,22 @@
|
||||||
#![feature(asm, lang_items)]
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![feature(asm)]
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate bitflags;
|
|
||||||
extern crate byteorder;
|
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/mem.rs"));
|
||||||
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/csr.rs"));
|
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/csr.rs"));
|
||||||
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/sdram_phy.rs"));
|
include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/sdram_phy.rs"));
|
||||||
pub mod spr;
|
pub mod ident;
|
||||||
pub mod irq;
|
|
||||||
pub mod cache;
|
|
||||||
pub mod pcr;
|
|
||||||
pub mod clock;
|
pub mod clock;
|
||||||
pub mod uart;
|
pub mod uart;
|
||||||
#[cfg(feature = "uart_console")]
|
|
||||||
pub mod uart_console;
|
|
||||||
|
|
||||||
#[cfg(has_spiflash)]
|
#[cfg(has_spiflash)]
|
||||||
pub mod spiflash;
|
pub mod spiflash;
|
||||||
pub mod config;
|
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")]
|
#[cfg(feature = "uart_console")]
|
||||||
pub use uart_console::Console;
|
pub mod uart_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])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use spr::{self, mfspr, mtspr};
|
use super::spr::*;
|
||||||
use csr;
|
use csr;
|
||||||
use mem;
|
use mem;
|
||||||
|
|
||||||
pub fn flush_cpu_icache() {
|
pub fn flush_cpu_icache() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let iccfgr = mfspr(spr::SPR_ICCFGR);
|
let iccfgr = mfspr(SPR_ICCFGR);
|
||||||
let ways = 1 << (iccfgr & spr::SPR_ICCFGR_NCW);
|
let ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
|
||||||
let set_size = 1 << ((iccfgr & spr::SPR_ICCFGR_NCS) >> 3);
|
let set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
|
||||||
let block_size = if iccfgr & spr::SPR_ICCFGR_CBS != 0 { 32 } else { 16 };
|
let block_size = if iccfgr & SPR_ICCFGR_CBS != 0 { 32 } else { 16 };
|
||||||
let size = set_size * ways * block_size;
|
let size = set_size * ways * block_size;
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < size {
|
while i < size {
|
||||||
mtspr(spr::SPR_ICBIR, i);
|
mtspr(SPR_ICBIR, i);
|
||||||
i += block_size;
|
i += block_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,15 @@ pub fn flush_cpu_icache() {
|
||||||
|
|
||||||
pub fn flush_cpu_dcache() {
|
pub fn flush_cpu_dcache() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let dccfgr = mfspr(spr::SPR_DCCFGR);
|
let dccfgr = mfspr(SPR_DCCFGR);
|
||||||
let ways = 1 << (dccfgr & spr::SPR_ICCFGR_NCW);
|
let ways = 1 << (dccfgr & SPR_ICCFGR_NCW);
|
||||||
let set_size = 1 << ((dccfgr & spr::SPR_DCCFGR_NCS) >> 3);
|
let set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
|
||||||
let block_size = if dccfgr & spr::SPR_DCCFGR_CBS != 0 { 32 } else { 16 };
|
let block_size = if dccfgr & SPR_DCCFGR_CBS != 0 { 32 } else { 16 };
|
||||||
let size = set_size * ways * block_size;
|
let size = set_size * ways * block_size;
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < size {
|
while i < size {
|
||||||
mtspr(spr::SPR_DCBIR, i);
|
mtspr(SPR_DCBIR, i);
|
||||||
i += block_size;
|
i += block_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod spr;
|
||||||
|
pub mod irq;
|
||||||
|
pub mod cache;
|
|
@ -1,5 +1,3 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
use csr;
|
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 PAGE_MASK: usize = PAGE_SIZE - 1;
|
||||||
|
|
||||||
const CMD_PP: u8 = 0x02;
|
const CMD_PP: u8 = 0x02;
|
||||||
const CMD_WRDI: u8 = 0x04;
|
// const CMD_WRDI: u8 = 0x04;
|
||||||
const CMD_RDSR: u8 = 0x05;
|
const CMD_RDSR: u8 = 0x05;
|
||||||
const CMD_WREN: u8 = 0x06;
|
const CMD_WREN: u8 = 0x06;
|
||||||
const CMD_SE: u8 = 0xd8;
|
const CMD_SE: u8 = 0xd8;
|
||||||
|
|
|
@ -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 = []
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
pub const SPI_INTFCONFA : u16 = 0x000;
|
pub const SPI_INTFCONFA : u16 = 0x000;
|
||||||
pub const SOFTRESET : u8 = 1 << 0;
|
pub const SOFTRESET : u8 = 1 << 0;
|
||||||
pub const LSBFIRST : u8 = 1 << 1;
|
pub const LSBFIRST : u8 = 1 << 1;
|
|
@ -1,4 +1,4 @@
|
||||||
use irq;
|
use board::irq;
|
||||||
|
|
||||||
pub unsafe fn reboot() -> ! {
|
pub unsafe fn reboot() -> ! {
|
||||||
irq::set_ie(false);
|
irq::set_ie(false);
|
|
@ -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();
|
||||||
|
}
|
|
@ -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;
|
|
@ -1,4 +1,4 @@
|
||||||
use spr::*;
|
use board::spr::*;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct Counters: u32 {
|
pub struct Counters: u32 {
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
authors = ["M-Labs"]
|
||||||
|
name = "build_misoc"
|
||||||
|
version = "0.0.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "build_misoc"
|
||||||
|
path = "lib.rs"
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate log_buffer;
|
extern crate log_buffer;
|
||||||
|
#[macro_use]
|
||||||
extern crate board;
|
extern crate board;
|
||||||
|
|
||||||
use core::cell::{Cell, RefCell};
|
use core::cell::{Cell, RefCell};
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use log::{Log, LogMetadata, LogRecord, LogLevelFilter, MaxLogLevelFilter};
|
use log::{Log, LogMetadata, LogRecord, LogLevelFilter, MaxLogLevelFilter};
|
||||||
use log_buffer::LogBuffer;
|
use log_buffer::LogBuffer;
|
||||||
use board::{Console, clock};
|
use board::clock;
|
||||||
|
|
||||||
pub struct BufferLogger {
|
pub struct BufferLogger {
|
||||||
buffer: RefCell<LogBuffer<&'static mut [u8]>>,
|
buffer: RefCell<LogBuffer<&'static mut [u8]>>,
|
||||||
|
@ -110,9 +111,8 @@ impl Log for BufferLogger {
|
||||||
record.level(), record.target(), record.args()).unwrap();
|
record.level(), record.target(), record.args()).unwrap();
|
||||||
|
|
||||||
if record.level() <= self.uart_filter.get() {
|
if record.level() <= self.uart_filter.get() {
|
||||||
writeln!(Console,
|
println!("[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
|
||||||
"[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
|
record.level(), record.target(), record.args());
|
||||||
record.level(), record.target(), record.args()).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,12 @@ build_artiq = { path = "../libbuild_artiq" }
|
||||||
byteorder = { version = "1.0", default-features = false }
|
byteorder = { version = "1.0", default-features = false }
|
||||||
cslice = { version = "0.3" }
|
cslice = { version = "0.3" }
|
||||||
log = { version = "0.3", default-features = false }
|
log = { version = "0.3", default-features = false }
|
||||||
|
board = { path = "../libboard", features = ["uart_console"] }
|
||||||
alloc_list = { path = "../liballoc_list" }
|
alloc_list = { path = "../liballoc_list" }
|
||||||
std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] }
|
std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] }
|
||||||
logger_artiq = { path = "../liblogger_artiq" }
|
logger_artiq = { path = "../liblogger_artiq" }
|
||||||
backtrace_artiq = { path = "../libbacktrace_artiq" }
|
backtrace_artiq = { path = "../libbacktrace_artiq" }
|
||||||
board = { path = "../libboard", features = ["uart_console"] }
|
board_artiq = { path = "../libboard_artiq" }
|
||||||
proto = { path = "../libproto", features = ["log"] }
|
proto = { path = "../libproto", features = ["log"] }
|
||||||
amp = { path = "../libamp" }
|
amp = { path = "../libamp" }
|
||||||
drtioaux = { path = "../libdrtioaux" }
|
drtioaux = { path = "../libdrtioaux" }
|
||||||
|
|
|
@ -120,14 +120,14 @@ mod drtio_i2c {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod i2c {
|
mod i2c {
|
||||||
use board;
|
use board_artiq::i2c as local_i2c;
|
||||||
use super::drtio_i2c;
|
use super::drtio_i2c;
|
||||||
|
|
||||||
pub fn start(busno: u32) -> Result<(), ()> {
|
pub fn start(busno: u32) -> Result<(), ()> {
|
||||||
let nodeno = (busno >> 16) as u8;
|
let nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
if nodeno == 0 {
|
||||||
board::i2c::start(node_busno)
|
local_i2c::start(node_busno)
|
||||||
} else {
|
} else {
|
||||||
drtio_i2c::start(nodeno, node_busno)
|
drtio_i2c::start(nodeno, node_busno)
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ mod i2c {
|
||||||
let nodeno = (busno >> 16) as u8;
|
let nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
if nodeno == 0 {
|
||||||
board::i2c::restart(node_busno)
|
local_i2c::restart(node_busno)
|
||||||
} else {
|
} else {
|
||||||
drtio_i2c::restart(nodeno, node_busno)
|
drtio_i2c::restart(nodeno, node_busno)
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ mod i2c {
|
||||||
let nodeno = (busno >> 16) as u8;
|
let nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
if nodeno == 0 {
|
||||||
board::i2c::stop(node_busno)
|
local_i2c::stop(node_busno)
|
||||||
} else {
|
} else {
|
||||||
drtio_i2c::stop(nodeno, node_busno)
|
drtio_i2c::stop(nodeno, node_busno)
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ mod i2c {
|
||||||
let nodeno = (busno >> 16 )as u8;
|
let nodeno = (busno >> 16 )as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
if nodeno == 0 {
|
||||||
board::i2c::write(node_busno, data)
|
local_i2c::write(node_busno, data)
|
||||||
} else {
|
} else {
|
||||||
drtio_i2c::write(nodeno, node_busno, data)
|
drtio_i2c::write(nodeno, node_busno, data)
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ mod i2c {
|
||||||
let nodeno = (busno >> 16) as u8;
|
let nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
if nodeno == 0 {
|
||||||
board::i2c::read(node_busno, ack)
|
local_i2c::read(node_busno, ack)
|
||||||
} else {
|
} else {
|
||||||
drtio_i2c::read(nodeno, node_busno, ack)
|
drtio_i2c::read(nodeno, node_busno, ack)
|
||||||
}
|
}
|
||||||
|
@ -254,11 +254,13 @@ mod drtio_spi {
|
||||||
|
|
||||||
#[cfg(not(has_drtio))]
|
#[cfg(not(has_drtio))]
|
||||||
mod drtio_spi {
|
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(())
|
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(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,14 +274,14 @@ mod drtio_spi {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod spi {
|
mod spi {
|
||||||
use board;
|
use board_artiq::spi as local_spi;
|
||||||
use super::drtio_spi;
|
use super::drtio_spi;
|
||||||
|
|
||||||
pub fn set_config(busno: u32, flags: u8, write_div: u8, read_div: u8) -> Result<(), ()> {
|
pub fn set_config(busno: u32, flags: u8, write_div: u8, read_div: u8) -> Result<(), ()> {
|
||||||
let nodeno = (busno >> 16) as u8;
|
let nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
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 {
|
} else {
|
||||||
drtio_spi::set_config(nodeno, node_busno, flags, write_div, read_div)
|
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 nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
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 {
|
} else {
|
||||||
drtio_spi::set_xfer(nodeno, node_busno, chip_select, write_length, read_length)
|
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 nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
if nodeno == 0 {
|
||||||
board::spi::write(node_busno, data)
|
local_spi::write(node_busno, data)
|
||||||
} else {
|
} else {
|
||||||
drtio_spi::write(nodeno, node_busno, data)
|
drtio_spi::write(nodeno, node_busno, data)
|
||||||
}
|
}
|
||||||
|
@ -309,7 +311,7 @@ mod spi {
|
||||||
let nodeno = (busno >> 16) as u8;
|
let nodeno = (busno >> 16) as u8;
|
||||||
let node_busno = busno as u8;
|
let node_busno = busno as u8;
|
||||||
if nodeno == 0 {
|
if nodeno == 0 {
|
||||||
board::spi::read(node_busno)
|
local_spi::read(node_busno)
|
||||||
} else {
|
} else {
|
||||||
drtio_spi::read(nodeno, node_busno)
|
drtio_spi::read(nodeno, node_busno)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ extern crate logger_artiq;
|
||||||
extern crate backtrace_artiq;
|
extern crate backtrace_artiq;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate board;
|
extern crate board;
|
||||||
|
extern crate board_artiq;
|
||||||
extern crate proto;
|
extern crate proto;
|
||||||
extern crate amp;
|
extern crate amp;
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
|
@ -41,6 +42,7 @@ mod rtio_dma;
|
||||||
mod mgmt;
|
mod mgmt;
|
||||||
mod kernel;
|
mod kernel;
|
||||||
mod kern_hwreq;
|
mod kern_hwreq;
|
||||||
|
mod watchdog;
|
||||||
mod session;
|
mod session;
|
||||||
#[cfg(any(has_rtio_moninj, has_drtio))]
|
#[cfg(any(has_rtio_moninj, has_drtio))]
|
||||||
mod moninj;
|
mod moninj;
|
||||||
|
@ -51,7 +53,7 @@ fn startup() {
|
||||||
board::clock::init();
|
board::clock::init();
|
||||||
info!("ARTIQ runtime starting...");
|
info!("ARTIQ runtime starting...");
|
||||||
info!("software version {}", include_str!(concat!(env!("OUT_DIR"), "/git-describe")));
|
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)]
|
#[cfg(has_serwb_phy_amc)]
|
||||||
board::serwb::wait_init();
|
board::serwb::wait_init();
|
||||||
|
@ -69,7 +71,7 @@ fn startup() {
|
||||||
info!("continuing boot");
|
info!("continuing boot");
|
||||||
|
|
||||||
#[cfg(has_i2c)]
|
#[cfg(has_i2c)]
|
||||||
board::i2c::init();
|
board_artiq::i2c::init();
|
||||||
#[cfg(si5324_free_running)]
|
#[cfg(si5324_free_running)]
|
||||||
setup_si5324_free_running();
|
setup_si5324_free_running();
|
||||||
#[cfg(has_hmc830_7043)]
|
#[cfg(has_hmc830_7043)]
|
||||||
|
@ -106,27 +108,27 @@ fn setup_si5324_free_running()
|
||||||
#[cfg(has_ethmac)]
|
#[cfg(has_ethmac)]
|
||||||
fn startup_ethernet() {
|
fn startup_ethernet() {
|
||||||
let hardware_addr;
|
let hardware_addr;
|
||||||
match config::read_str("mac", |r| r?.parse()) {
|
match config::read_str("mac", |r| r.map(|s| s.parse())) {
|
||||||
Err(()) => {
|
Ok(Ok(addr)) => {
|
||||||
hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
|
|
||||||
warn!("using default MAC address {}; consider changing it", hardware_addr);
|
|
||||||
}
|
|
||||||
Ok(addr) => {
|
|
||||||
hardware_addr = addr;
|
hardware_addr = addr;
|
||||||
info!("using MAC address {}", hardware_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;
|
let protocol_addr;
|
||||||
match config::read_str("ip", |r| r?.parse()) {
|
match config::read_str("ip", |r| r.map(|s| s.parse())) {
|
||||||
Err(()) => {
|
Ok(Ok(addr)) => {
|
||||||
protocol_addr = IpAddress::v4(192, 168, 1, 50);
|
|
||||||
info!("using default IP address {}", protocol_addr);
|
|
||||||
}
|
|
||||||
Ok(addr) => {
|
|
||||||
protocol_addr = addr;
|
protocol_addr = addr;
|
||||||
info!("using IP address {}", protocol_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>)
|
// fn _net_trace_writer<U>(timestamp: u64, printer: smoltcp::wire::PrettyPrinter<U>)
|
||||||
|
@ -159,26 +161,24 @@ fn startup_ethernet() {
|
||||||
#[cfg(has_rtio_analyzer)]
|
#[cfg(has_rtio_analyzer)]
|
||||||
io.spawn(4096, analyzer::thread);
|
io.spawn(4096, analyzer::thread);
|
||||||
|
|
||||||
match config::read_str("log_level", |r| r?.parse()) {
|
match config::read_str("log_level", |r| r.map(|s| s.parse())) {
|
||||||
Err(()) => (),
|
Ok(Ok(log_level_filter)) => {
|
||||||
Ok(log_level_filter) => {
|
|
||||||
info!("log level set to {} by `log_level` config key",
|
info!("log level set to {} by `log_level` config key",
|
||||||
log_level_filter);
|
log_level_filter);
|
||||||
logger_artiq::BufferLogger::with(|logger|
|
logger_artiq::BufferLogger::with(|logger|
|
||||||
logger.set_max_log_level(log_level_filter));
|
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()) {
|
match config::read_str("uart_log_level", |r| r.map(|s| s.parse())) {
|
||||||
Err(()) => {
|
Ok(Ok(uart_log_level_filter)) => {
|
||||||
info!("UART log level set to INFO by default");
|
|
||||||
},
|
|
||||||
Ok(uart_log_level_filter) => {
|
|
||||||
info!("UART log level set to {} by `uart_log_level` config key",
|
info!("UART log level set to {} by `uart_log_level` config key",
|
||||||
uart_log_level_filter);
|
uart_log_level_filter);
|
||||||
logger_artiq::BufferLogger::with(|logger|
|
logger_artiq::BufferLogger::with(|logger|
|
||||||
logger.set_uart_log_level(uart_log_level_filter));
|
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();
|
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")) {
|
if config::read_str("panic_reboot", |r| r == Ok("1")) {
|
||||||
println!("rebooting...");
|
println!("rebooting...");
|
||||||
unsafe { board::boot::reboot() }
|
unsafe { board_artiq::boot::reboot() }
|
||||||
} else {
|
} else {
|
||||||
println!("halting.");
|
println!("halting.");
|
||||||
println!("use `artiq_coreconfig write -s panic_reboot 1` to reboot instead");
|
println!("use `artiq_coreconfig write -s panic_reboot 1` to reboot instead");
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
use board_artiq::boot;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use log::LogLevelFilter;
|
use log::LogLevelFilter;
|
||||||
use logger_artiq::BufferLogger;
|
use logger_artiq::BufferLogger;
|
||||||
use sched::Io;
|
use sched::Io;
|
||||||
use sched::{TcpListener, TcpStream};
|
use sched::{TcpListener, TcpStream};
|
||||||
use board;
|
|
||||||
use proto::WriteExt;
|
use proto::WriteExt;
|
||||||
use mgmt_proto::*;
|
use mgmt_proto::*;
|
||||||
|
|
||||||
|
@ -86,14 +86,14 @@ fn worker(io: &Io, stream: &mut TcpStream) -> io::Result<()> {
|
||||||
Reply::RebootImminent.write_to(stream)?;
|
Reply::RebootImminent.write_to(stream)?;
|
||||||
stream.close()?;
|
stream.close()?;
|
||||||
stream.flush()?;
|
stream.flush()?;
|
||||||
unsafe { board::boot::hotswap(&firmware) }
|
unsafe { boot::hotswap(&firmware) }
|
||||||
},
|
},
|
||||||
|
|
||||||
Request::Reboot => {
|
Request::Reboot => {
|
||||||
Reply::RebootImminent.write_to(stream)?;
|
Reply::RebootImminent.write_to(stream)?;
|
||||||
stream.close()?;
|
stream.close()?;
|
||||||
warn!("rebooting");
|
warn!("rebooting");
|
||||||
unsafe { board::boot::reboot() }
|
unsafe { boot::reboot() }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,12 +226,13 @@ pub fn startup(io: &Io) {
|
||||||
info!("using external startup RTIO clock");
|
info!("using external startup RTIO clock");
|
||||||
RtioClock::External
|
RtioClock::External
|
||||||
},
|
},
|
||||||
Err(()) => {
|
Err(_) => {
|
||||||
info!("using internal startup RTIO clock (by default)");
|
info!("using internal startup RTIO clock (by default)");
|
||||||
RtioClock::Internal
|
RtioClock::Internal
|
||||||
},
|
},
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
error!("unrecognized startup_clock configuration entry, using internal RTIO clock");
|
error!("unrecognized startup_clock configuration entry, \
|
||||||
|
using internal RTIO clock");
|
||||||
RtioClock::Internal
|
RtioClock::Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use rtio_mgt;
|
||||||
use rtio_dma::Manager as DmaManager;
|
use rtio_dma::Manager as DmaManager;
|
||||||
use cache::Cache;
|
use cache::Cache;
|
||||||
use kern_hwreq;
|
use kern_hwreq;
|
||||||
|
use watchdog::WatchdogSet;
|
||||||
|
|
||||||
use rpc_proto as rpc;
|
use rpc_proto as rpc;
|
||||||
use session_proto as host;
|
use session_proto as host;
|
||||||
|
@ -66,7 +67,7 @@ enum KernelState {
|
||||||
struct Session<'a> {
|
struct Session<'a> {
|
||||||
congress: &'a mut Congress,
|
congress: &'a mut Congress,
|
||||||
kernel_state: KernelState,
|
kernel_state: KernelState,
|
||||||
watchdog_set: board::clock::WatchdogSet,
|
watchdog_set: WatchdogSet,
|
||||||
log_buffer: String
|
log_buffer: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ impl<'a> Session<'a> {
|
||||||
Session {
|
Session {
|
||||||
congress: congress,
|
congress: congress,
|
||||||
kernel_state: KernelState::Absent,
|
kernel_state: KernelState::Absent,
|
||||||
watchdog_set: board::clock::WatchdogSet::new(),
|
watchdog_set: WatchdogSet::new(),
|
||||||
log_buffer: String::new()
|
log_buffer: String::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +227,7 @@ fn process_host_message(io: &Io,
|
||||||
match host_read(stream)? {
|
match host_read(stream)? {
|
||||||
host::Request::SystemInfo => {
|
host::Request::SystemInfo => {
|
||||||
host_write(stream, host::Reply::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()
|
finished_cleanly: session.congress.finished_cleanly.get()
|
||||||
})?;
|
})?;
|
||||||
session.congress.finished_cleanly.set(true);
|
session.congress.finished_cleanly.set(true);
|
||||||
|
@ -238,7 +239,7 @@ fn process_host_message(io: &Io,
|
||||||
config::read(key, |result| {
|
config::read(key, |result| {
|
||||||
match result {
|
match result {
|
||||||
Ok(value) => host_write(stream, host::Reply::FlashRead(&value)),
|
Ok(value) => host_write(stream, host::Reply::FlashRead(&value)),
|
||||||
Err(()) => host_write(stream, host::Reply::FlashError)
|
Err(_) => host_write(stream, host::Reply::FlashError)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue