From 8c19d90179ae897dfc78ee8839fd4b9ca1b9223e Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 28 Dec 2017 12:20:34 +0800 Subject: [PATCH] firmware: prepare config block for access from BIOS/bootloader. This is in 3.2 so that users lose storage only once. --- artiq/firmware/Cargo.lock | 1 + artiq/firmware/libboard/Cargo.toml | 1 + .../firmware/{runtime => libboard}/config.rs | 63 ++++++------ artiq/firmware/libboard/lib.rs | 2 + artiq/firmware/libboard/spiflash.rs | 99 +++++++++---------- artiq/firmware/runtime/lib.rs | 3 +- artiq/firmware/runtime/rtio_mgt.rs | 3 +- artiq/firmware/runtime/runtime.ld | 9 -- artiq/firmware/runtime/session.rs | 4 +- artiq/frontend/artiq_flash.py | 4 +- conda/artiq-dev/meta.yaml | 2 +- 11 files changed, 89 insertions(+), 102 deletions(-) rename artiq/firmware/{runtime => libboard}/config.rs (82%) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 0fcaac872..36a5db4e9 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -28,6 +28,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "build_artiq 0.0.0", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/artiq/firmware/libboard/Cargo.toml b/artiq/firmware/libboard/Cargo.toml index 950fbcff2..0120a0d19 100644 --- a/artiq/firmware/libboard/Cargo.toml +++ b/artiq/firmware/libboard/Cargo.toml @@ -9,6 +9,7 @@ name = "board" path = "lib.rs" [dependencies] +byteorder = { version = "1.0", default-features = false } log = { version = "0.3", default-features = false } [features] diff --git a/artiq/firmware/runtime/config.rs b/artiq/firmware/libboard/config.rs similarity index 82% rename from artiq/firmware/runtime/config.rs rename to artiq/firmware/libboard/config.rs index fd3c14efe..5c673da5b 100644 --- a/artiq/firmware/runtime/config.rs +++ b/artiq/firmware/libboard/config.rs @@ -1,14 +1,17 @@ #[cfg(has_spiflash)] mod imp { use core::str; - use std::btree_map::BTreeMap; use byteorder::{ByteOrder, BigEndian}; - use board::{cache, spiflash}; + use cache; + use spiflash; + + // One flash sector immediately after the bootloader. + const ADDR: usize = ::mem::FLASH_BOOT_ADDRESS - spiflash::PAGE_SIZE; + const SIZE: usize = spiflash::PAGE_SIZE; mod lock { use core::slice; use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; - use board; static LOCKED: AtomicUsize = ATOMIC_USIZE_INIT; @@ -24,22 +27,7 @@ mod imp { } pub fn data(&self) -> &'static [u8] { - extern { - static _ftext: u8; - static _fstorage: u8; - static _estorage: u8; - } - - unsafe { - let base = &_ftext as *const _ as usize; - let begin = &_fstorage as *const _ as usize; - let end = &_estorage as *const _ as usize; - - let ptr = board::mem::FLASH_BOOT_ADDRESS + (begin - base); - let len = end - begin; - - slice::from_raw_parts(ptr as *const u8, len) - } + unsafe { slice::from_raw_parts(super::ADDR as *const u8, super::SIZE) } } } @@ -52,6 +40,7 @@ mod imp { use self::lock::Lock; + #[derive(Clone)] struct Iter<'a> { data: &'a [u8], offset: usize @@ -140,28 +129,39 @@ mod imp { spiflash::write(data.as_ptr() as usize, value); data = &data[value.len()..]; + cache::flush_l2_cache(); + Ok(data) } 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); - } - } + static mut OLD_DATA: [u8; SIZE] = [0; SIZE]; + let old_data = unsafe { + OLD_DATA.copy_from_slice(lock.data()); + &OLD_DATA[..] + }; let mut data = lock.data(); - spiflash::erase_sector(data.as_ptr() as usize); - for (key, value) in items { + unsafe { spiflash::erase_sector(data.as_ptr() as usize) }; + + // This is worst-case quadratic, but we're limited by a small SPI flash sector size, + // so it does not really matter. + let mut iter = Iter::new(old_data); + while let Some(result) = iter.next() { + let (key, mut value) = result?; + + let mut next_iter = iter.clone(); + while let Some(next_result) = next_iter.next() { + let (next_key, next_value) = next_result?; + if key == next_key { + value = next_value + } + } data = unsafe { append_at(data, key, value)? }; } - cache::flush_l2_cache(); Ok(()) } @@ -178,7 +178,6 @@ mod imp { unsafe { append_at(free, key.as_bytes(), value)? }; - cache::flush_l2_cache(); Ok(()) } @@ -200,7 +199,7 @@ mod imp { pub fn erase() -> Result<(), ()> { let lock = Lock::take()?; - spiflash::erase_sector(lock.data().as_ptr() as usize); + unsafe { spiflash::erase_sector(lock.data().as_ptr() as usize) }; cache::flush_l2_cache(); Ok(()) diff --git a/artiq/firmware/libboard/lib.rs b/artiq/firmware/libboard/lib.rs index d0c6ecc77..d31c9e4e2 100644 --- a/artiq/firmware/libboard/lib.rs +++ b/artiq/firmware/libboard/lib.rs @@ -1,6 +1,7 @@ #![feature(asm, lang_items)] #![no_std] +extern crate byteorder; #[macro_use] extern crate log; @@ -18,6 +19,7 @@ pub mod uart_console; #[cfg(has_spiflash)] pub mod spiflash; +pub mod config; pub mod i2c; pub mod spi; diff --git a/artiq/firmware/libboard/spiflash.rs b/artiq/firmware/libboard/spiflash.rs index 26c5cbbc6..643a2160c 100644 --- a/artiq/firmware/libboard/spiflash.rs +++ b/artiq/firmware/libboard/spiflash.rs @@ -3,6 +3,10 @@ use core::cmp; use csr; +pub const PAGE_SIZE: usize = csr::CONFIG_SPIFLASH_PAGE_SIZE as usize; + +const PAGE_MASK: usize = PAGE_SIZE - 1; + const CMD_PP: u8 = 0x02; const CMD_WRDI: u8 = 0x04; const CMD_RDSR: u8 = 0x05; @@ -15,28 +19,24 @@ const PIN_DQ_I: u8 = 1 << 3; const SR_WIP: u8 = 1; -fn write_byte(mut byte: u8) { - unsafe { - csr::spiflash::bitbang_write(0); - for _ in 0..8 { - csr::spiflash::bitbang_write((byte & 0x80) >> 7); - csr::spiflash::bitbang_write((byte & 0x80) >> 7 | PIN_CLK); - byte <<= 1; - } - csr::spiflash::bitbang_write(0); +unsafe fn write_byte(mut byte: u8) { + csr::spiflash::bitbang_write(0); + for _ in 0..8 { + csr::spiflash::bitbang_write((byte & 0x80) >> 7); + csr::spiflash::bitbang_write((byte & 0x80) >> 7 | PIN_CLK); + byte <<= 1; } + csr::spiflash::bitbang_write(0); } -fn write_addr(mut addr: usize) { - unsafe { - csr::spiflash::bitbang_write(0); - for _ in 0..24 { - csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8); - csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8 | PIN_CLK); - addr <<= 1; - } - csr::spiflash::bitbang_write(0); +unsafe fn write_addr(mut addr: usize) { + csr::spiflash::bitbang_write(0); + for _ in 0..24 { + csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8); + csr::spiflash::bitbang_write(((addr & 0x800000) >> 23) as u8 | PIN_CLK); + addr <<= 1; } + csr::spiflash::bitbang_write(0); } fn wait_until_ready() { @@ -59,54 +59,47 @@ fn wait_until_ready() { } } -pub fn erase_sector(addr: usize) { - unsafe { - let sector_addr = addr & !(csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize - 1); +pub unsafe fn erase_sector(addr: usize) { + let sector_addr = addr & !(csr::CONFIG_SPIFLASH_SECTOR_SIZE as usize - 1); - csr::spiflash::bitbang_en_write(1); + csr::spiflash::bitbang_en_write(1); - wait_until_ready(); + wait_until_ready(); - write_byte(CMD_WREN); - csr::spiflash::bitbang_write(PIN_CS_N); + write_byte(CMD_WREN); + csr::spiflash::bitbang_write(PIN_CS_N); - write_byte(CMD_SE); - write_addr(sector_addr); - csr::spiflash::bitbang_write(PIN_CS_N); + write_byte(CMD_SE); + write_addr(sector_addr); + csr::spiflash::bitbang_write(PIN_CS_N); - wait_until_ready(); + wait_until_ready(); - csr::spiflash::bitbang_en_write(0); - } + csr::spiflash::bitbang_en_write(0); } -fn write_page(addr: usize, data: &[u8]) { - unsafe { - csr::spiflash::bitbang_en_write(1); +unsafe fn write_page(addr: usize, data: &[u8]) { + csr::spiflash::bitbang_en_write(1); - wait_until_ready(); + wait_until_ready(); - write_byte(CMD_WREN); - csr::spiflash::bitbang_write(PIN_CS_N); - write_byte(CMD_PP); - write_addr(addr); - for &byte in data { - write_byte(byte) - } - - csr::spiflash::bitbang_write(PIN_CS_N); - csr::spiflash::bitbang_write(0); - - wait_until_ready(); - - csr::spiflash::bitbang_en_write(0); + write_byte(CMD_WREN); + csr::spiflash::bitbang_write(PIN_CS_N); + write_byte(CMD_PP); + write_addr(addr); + for &byte in data { + write_byte(byte) } + + csr::spiflash::bitbang_write(PIN_CS_N); + csr::spiflash::bitbang_write(0); + + wait_until_ready(); + + csr::spiflash::bitbang_en_write(0); } -const PAGE_SIZE: usize = csr::CONFIG_SPIFLASH_PAGE_SIZE as usize; -const PAGE_MASK: usize = PAGE_SIZE - 1; - -pub fn write(mut addr: usize, mut data: &[u8]) { +pub unsafe fn write(mut addr: usize, mut data: &[u8]) { if addr & PAGE_MASK != 0 { let size = cmp::min((PAGE_SIZE - (addr & PAGE_MASK)) as usize, data.len()); write_page(addr, &data[..size]); diff --git a/artiq/firmware/runtime/lib.rs b/artiq/firmware/runtime/lib.rs index 9949f210c..f2c30c938 100644 --- a/artiq/firmware/runtime/lib.rs +++ b/artiq/firmware/runtime/lib.rs @@ -23,10 +23,11 @@ extern crate amp; extern crate drtioaux; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; + +use board::config; use proto::{mgmt_proto, analyzer_proto, moninj_proto, rpc_proto, session_proto, kernel_proto}; use amp::{mailbox, rpc_queue}; -mod config; mod ethmac; mod rtio_mgt; diff --git a/artiq/firmware/runtime/rtio_mgt.rs b/artiq/firmware/runtime/rtio_mgt.rs index 9fd924936..35083315c 100644 --- a/artiq/firmware/runtime/rtio_mgt.rs +++ b/artiq/firmware/runtime/rtio_mgt.rs @@ -1,5 +1,4 @@ -use config; -use board::csr; +use board::{csr, config}; use sched::Io; #[cfg(has_rtio_crg)] diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index d629e4ff8..1d21c61fb 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -66,15 +66,6 @@ SECTIONS _edata = .; } > runtime - .storage : - { - /* Keep in sync with artiq_flash.py */ - . = _ftext + 0x100000; - _fstorage = .; - . += /*SPIFLASH_SECTOR_SIZE*/ 0x10000; - _estorage = .; - } > runtime - .bss : { . = ALIGN(4); diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index ed31860b0..59e3ed425 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -3,14 +3,14 @@ use std::{mem, str}; use std::cell::{Cell, RefCell}; use std::io::{self, Read, Write}; use std::error::Error; -use {config, rtio_mgt, mailbox, rpc_queue, kernel}; +use {rtio_mgt, mailbox, rpc_queue, kernel}; use cache::Cache; use rtio_dma::Manager as DmaManager; use urc::Urc; use sched::{ThreadHandle, Io}; use sched::{TcpListener, TcpStream}; use byteorder::{ByteOrder, NetworkEndian}; -use board; +use board::{self, config}; use rpc_proto as rpc; use session_proto as host; diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index 1f52b86be..61199af60 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -69,8 +69,8 @@ def main(): "start": "xc7_program xc7.tap", "gateware": 0x000000, "bios": 0xaf0000, - "runtime": 0xb00000, - "storage": 0xc00000, + "storage": 0xb00000, + "runtime": 0xb10000, }, }[opts.target] diff --git a/conda/artiq-dev/meta.yaml b/conda/artiq-dev/meta.yaml index d20acc519..6b12cd9fb 100644 --- a/conda/artiq-dev/meta.yaml +++ b/conda/artiq-dev/meta.yaml @@ -15,7 +15,7 @@ requirements: - python >=3.5.3,<3.6 - setuptools 33.1.1 - migen 0.5 - - misoc 0.8.dev py35_30+gitd95f4edb + - misoc 0.8.dev py35_35+git6845fc0a - jesd204b 0.3 - binutils-or1k-linux >=2.27 - llvm-or1k 4.0.1