forked from M-Labs/artiq
runtime: get rid of config_dummy.rs. NFC.
Use the same strategy as elsewhere.
This commit is contained in:
parent
0ede5d8638
commit
6cbf8786d8
|
@ -1,192 +1,220 @@
|
||||||
use core::str;
|
#[cfg(has_spiflash)]
|
||||||
use std::btree_map::BTreeMap;
|
mod imp {
|
||||||
use byteorder::{ByteOrder, BigEndian};
|
use core::str;
|
||||||
use board::{mem, csr, cache, spiflash};
|
use std::btree_map::BTreeMap;
|
||||||
|
use byteorder::{ByteOrder, BigEndian};
|
||||||
|
use board::{mem, csr, cache, spiflash};
|
||||||
|
|
||||||
const ADDR: usize = mem::FLASH_BOOT_ADDRESS + 0x80000 /* max runtime size */;
|
const ADDR: usize = mem::FLASH_BOOT_ADDRESS + 0x80000 /* max runtime size */;
|
||||||
const SIZE: usize = csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize;
|
const SIZE: usize = csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize;
|
||||||
|
|
||||||
mod lock {
|
mod lock {
|
||||||
use core::slice;
|
use core::slice;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
static LOCKED: AtomicUsize = AtomicUsize::new(0);
|
static LOCKED: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
pub struct Lock;
|
pub struct Lock;
|
||||||
|
|
||||||
impl Lock {
|
impl Lock {
|
||||||
pub fn take() -> Result<Lock, ()> {
|
pub fn take() -> Result<Lock, ()> {
|
||||||
if LOCKED.swap(1, Ordering::SeqCst) != 0 {
|
if LOCKED.swap(1, Ordering::SeqCst) != 0 {
|
||||||
Err(()) // already locked
|
Err(()) // already locked
|
||||||
} else {
|
} else {
|
||||||
Ok(Lock) // locked now
|
Ok(Lock) // locked now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data(&self) -> &'static [u8] {
|
||||||
|
unsafe { slice::from_raw_parts(super::ADDR as *const u8, super::SIZE) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn data(&self) -> &'static [u8] {
|
impl Drop for Lock {
|
||||||
unsafe { slice::from_raw_parts(super::ADDR as *const u8, super::SIZE) }
|
fn drop(&mut self) {
|
||||||
}
|
LOCKED.store(0, Ordering::SeqCst)
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Lock {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
LOCKED.store(0, Ordering::SeqCst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use self::lock::Lock;
|
|
||||||
|
|
||||||
struct Iter<'a> {
|
|
||||||
data: &'a [u8],
|
|
||||||
offset: usize
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iter<'a> {
|
|
||||||
fn new(data: &'a [u8]) -> Iter<'a> {
|
|
||||||
Iter { data: data, offset: 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for Iter<'a> {
|
|
||||||
type Item = Result<(&'a [u8], &'a [u8]), ()>;
|
|
||||||
|
|
||||||
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(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
let record_size = BigEndian::read_u32(data) as usize;
|
|
||||||
if record_size < 4 {
|
|
||||||
error!("offset {}: invalid record size", self.offset);
|
|
||||||
return Some(Err(()))
|
|
||||||
}
|
|
||||||
if record_size == !0 /* all ones; erased flash */ {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
|
|
||||||
let record_body = &data[4..record_size];
|
|
||||||
match record_body.iter().position(|&x| x == 0) {
|
|
||||||
None => {
|
|
||||||
error!("offset {}: missing separator", self.offset);
|
|
||||||
Some(Err(()))
|
|
||||||
}
|
|
||||||
Some(pos) => {
|
|
||||||
self.offset += record_size;
|
|
||||||
|
|
||||||
let (key, zero_and_value) = record_body.split_at(pos);
|
|
||||||
Some(Ok((key, &zero_and_value[1..])))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(key: &str, f: F) -> R {
|
use self::lock::Lock;
|
||||||
f(Lock::take().and_then(|lock| {
|
|
||||||
let mut iter = Iter::new(lock.data());
|
struct Iter<'a> {
|
||||||
let mut value = &[][..];
|
data: &'a [u8],
|
||||||
while let Some(result) = iter.next() {
|
offset: usize
|
||||||
let (record_key, record_value) = result?;
|
}
|
||||||
if key.as_bytes() == record_key {
|
|
||||||
// last write wins
|
impl<'a> Iter<'a> {
|
||||||
value = record_value
|
fn new(data: &'a [u8]) -> Iter<'a> {
|
||||||
|
Iter { data: data, offset: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for Iter<'a> {
|
||||||
|
type Item = Result<(&'a [u8], &'a [u8]), ()>;
|
||||||
|
|
||||||
|
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(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
let record_size = BigEndian::read_u32(data) as usize;
|
||||||
|
if record_size < 4 {
|
||||||
|
error!("offset {}: invalid record size", self.offset);
|
||||||
|
return Some(Err(()))
|
||||||
|
}
|
||||||
|
if record_size == !0 /* all ones; erased flash */ {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
let record_body = &data[4..record_size];
|
||||||
|
match record_body.iter().position(|&x| x == 0) {
|
||||||
|
None => {
|
||||||
|
error!("offset {}: missing separator", self.offset);
|
||||||
|
Some(Err(()))
|
||||||
|
}
|
||||||
|
Some(pos) => {
|
||||||
|
self.offset += record_size;
|
||||||
|
|
||||||
|
let (key, zero_and_value) = record_body.split_at(pos);
|
||||||
|
Some(Ok((key, &zero_and_value[1..])))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(value)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(key: &str, f: F) -> R {
|
|
||||||
read(key, |result| {
|
|
||||||
f(result.and_then(|value| str::from_utf8(value).map_err(|_| ())))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_at(mut offset: usize, key: &[u8], value: &[u8]) -> Result<usize, ()> {
|
|
||||||
let record_size = 4 + key.len() + 1 + value.len();
|
|
||||||
if offset + record_size > SIZE {
|
|
||||||
return Err(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut record_size_bytes = [0u8; 4];
|
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(key: &str, f: F) -> R {
|
||||||
BigEndian::write_u32(&mut record_size_bytes[..], record_size as u32);
|
f(Lock::take().and_then(|lock| {
|
||||||
|
let mut iter = Iter::new(lock.data());
|
||||||
|
let mut value = &[][..];
|
||||||
|
while let Some(result) = iter.next() {
|
||||||
|
let (record_key, record_value) = result?;
|
||||||
|
if key.as_bytes() == record_key {
|
||||||
|
// last write wins
|
||||||
|
value = record_value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(value)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
spiflash::write(ADDR + offset, &record_size_bytes[..]);
|
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(key: &str, f: F) -> R {
|
||||||
offset += record_size_bytes.len();
|
read(key, |result| {
|
||||||
|
f(result.and_then(|value| str::from_utf8(value).map_err(|_| ())))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
spiflash::write(ADDR + offset, key);
|
fn append_at(mut offset: usize, key: &[u8], value: &[u8]) -> Result<usize, ()> {
|
||||||
offset += key.len();
|
let record_size = 4 + key.len() + 1 + value.len();
|
||||||
|
if offset + record_size > SIZE {
|
||||||
spiflash::write(ADDR + offset, &[0]);
|
return Err(())
|
||||||
offset += 1;
|
|
||||||
|
|
||||||
spiflash::write(ADDR + offset, value);
|
|
||||||
offset += value.len();
|
|
||||||
|
|
||||||
cache::flush_l2_cache();
|
|
||||||
Ok(offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compact() -> Result<(), ()> {
|
|
||||||
let lock = Lock::take()?;
|
|
||||||
|
|
||||||
let mut items = BTreeMap::new();
|
|
||||||
{
|
|
||||||
let mut iter = Iter::new(lock.data());
|
|
||||||
while let Some(result) = iter.next() {
|
|
||||||
let (key, value) = result?;
|
|
||||||
items.insert(key, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut record_size_bytes = [0u8; 4];
|
||||||
|
BigEndian::write_u32(&mut record_size_bytes[..], record_size as u32);
|
||||||
|
|
||||||
|
spiflash::write(ADDR + offset, &record_size_bytes[..]);
|
||||||
|
offset += record_size_bytes.len();
|
||||||
|
|
||||||
|
spiflash::write(ADDR + offset, key);
|
||||||
|
offset += key.len();
|
||||||
|
|
||||||
|
spiflash::write(ADDR + offset, &[0]);
|
||||||
|
offset += 1;
|
||||||
|
|
||||||
|
spiflash::write(ADDR + offset, value);
|
||||||
|
offset += value.len();
|
||||||
|
|
||||||
|
cache::flush_l2_cache();
|
||||||
|
Ok(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
spiflash::erase_sector(ADDR);
|
fn compact() -> Result<(), ()> {
|
||||||
cache::flush_l2_cache();
|
let lock = Lock::take()?;
|
||||||
|
|
||||||
let mut offset = 0;
|
let mut items = BTreeMap::new();
|
||||||
for (key, value) in items {
|
{
|
||||||
offset = append_at(offset, key, value)?;
|
let mut iter = Iter::new(lock.data());
|
||||||
}
|
while let Some(result) = iter.next() {
|
||||||
Ok(())
|
let (key, value) = result?;
|
||||||
}
|
items.insert(key, value);
|
||||||
|
}
|
||||||
fn append(key: &str, value: &[u8]) -> Result<(), ()> {
|
|
||||||
let lock = Lock::take()?;
|
|
||||||
|
|
||||||
let free_offset = {
|
|
||||||
let mut iter = Iter::new(lock.data());
|
|
||||||
while let Some(result) = iter.next() {
|
|
||||||
let _ = result?;
|
|
||||||
}
|
}
|
||||||
iter.offset
|
|
||||||
};
|
|
||||||
|
|
||||||
append_at(free_offset, key.as_bytes(), value)?;
|
spiflash::erase_sector(ADDR);
|
||||||
Ok(())
|
cache::flush_l2_cache();
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(key: &str, value: &[u8]) -> Result<(), ()> {
|
let mut offset = 0;
|
||||||
match append(key, value) {
|
for (key, value) in items {
|
||||||
Ok(()) => (),
|
offset = append_at(offset, key, value)?;
|
||||||
Err(()) => {
|
|
||||||
compact()?;
|
|
||||||
append(key, value)?;
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append(key: &str, value: &[u8]) -> Result<(), ()> {
|
||||||
|
let lock = Lock::take()?;
|
||||||
|
|
||||||
|
let free_offset = {
|
||||||
|
let mut iter = Iter::new(lock.data());
|
||||||
|
while let Some(result) = iter.next() {
|
||||||
|
let _ = result?;
|
||||||
|
}
|
||||||
|
iter.offset
|
||||||
|
};
|
||||||
|
|
||||||
|
append_at(free_offset, key.as_bytes(), value)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(key: &str, value: &[u8]) -> Result<(), ()> {
|
||||||
|
match append(key, value) {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(()) => {
|
||||||
|
compact()?;
|
||||||
|
append(key, value)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(key: &str) -> Result<(), ()> {
|
||||||
|
write(key, &[])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn erase() -> Result<(), ()> {
|
||||||
|
let _lock = Lock::take()?;
|
||||||
|
|
||||||
|
spiflash::erase_sector(ADDR);
|
||||||
|
cache::flush_l2_cache();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(key: &str) -> Result<(), ()> {
|
#[cfg(not(has_spiflash))]
|
||||||
write(key, &[])
|
mod imp {
|
||||||
|
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(_key: &str, f: F) -> R {
|
||||||
|
f(Err(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(_key: &str, f: F) -> R {
|
||||||
|
f(Err(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(_key: &str, _value: &[u8]) -> Result<(), ()> {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(_key: &str) -> Result<(), ()> {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn erase() -> Result<(), ()> {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn erase() -> Result<(), ()> {
|
pub use self::imp::*;
|
||||||
let _lock = Lock::take()?;
|
|
||||||
|
|
||||||
spiflash::erase_sector(ADDR);
|
|
||||||
cache::flush_l2_cache();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
pub fn read<F: FnOnce(Result<&[u8], ()>) -> R, R>(_key: &str, f: F) -> R {
|
|
||||||
f(Err(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_str<F: FnOnce(Result<&str, ()>) -> R, R>(_key: &str, f: F) -> R {
|
|
||||||
f(Err(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(_key: &str, _value: &[u8]) -> Result<(), ()> {
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove(_key: &str) -> Result<(), ()> {
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn erase() -> Result<(), ()> {
|
|
||||||
Err(())
|
|
||||||
}
|
|
|
@ -34,10 +34,7 @@ macro_rules! borrow_mut {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(has_spiflash)]
|
|
||||||
mod config;
|
mod config;
|
||||||
#[cfg(not(has_spiflash))]
|
|
||||||
#[path="config_dummy.rs"] mod config;
|
|
||||||
mod ethmac;
|
mod ethmac;
|
||||||
mod rtio_mgt;
|
mod rtio_mgt;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue