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" 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)",

View File

@ -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 = []

View File

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

View File

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

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)] #[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(())
} }
} }

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] #![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])
}
}

View File

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

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

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

View File

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

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! { bitflags! {
pub struct Counters: u32 { pub struct Counters: u32 {

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

View File

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

View File

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

View File

@ -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");

View File

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

View File

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

View File

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

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)
}
}