firmware: implement the new bootloader.

This commit is contained in:
whitequark 2017-12-28 13:17:49 +00:00
parent b9754e7108
commit acd13837ff
19 changed files with 604 additions and 29 deletions

View File

@ -42,6 +42,17 @@ dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "bootloader"
version = "0.0.0"
dependencies = [
"board 0.0.0",
"build_misoc 0.0.0",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.6.0 (git+git://github.com/whitequark/crc-rs?rev=51cd356)",
"rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "build_artiq" name = "build_artiq"
version = "0.0.0" version = "0.0.0"
@ -49,6 +60,11 @@ 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_const"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "build_misoc" name = "build_misoc"
version = "0.0.0" version = "0.0.0"
@ -77,6 +93,14 @@ name = "compiler_builtins"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/m-labs/compiler-builtins?rev=97916b1#97916b17ca542eac0524b8570c7d05913891a0dc" source = "git+https://github.com/m-labs/compiler-builtins?rev=97916b1#97916b17ca542eac0524b8570c7d05913891a0dc"
[[package]]
name = "crc"
version = "1.6.0"
source = "git+git://github.com/whitequark/crc-rs?rev=51cd356#51cd3560aa9d3823061f2bb46797d8c61f4cfa9e"
dependencies = [
"build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "cslice" name = "cslice"
version = "0.3.0" version = "0.3.0"
@ -175,6 +199,11 @@ dependencies = [
"std_artiq 0.0.0", "std_artiq 0.0.0",
] ]
[[package]]
name = "rlibc"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "runtime" name = "runtime"
version = "0.0.0" version = "0.0.0"
@ -220,6 +249,7 @@ dependencies = [
"board 0.0.0", "board 0.0.0",
"board_artiq 0.0.0", "board_artiq 0.0.0",
"build_artiq 0.0.0", "build_artiq 0.0.0",
"build_misoc 0.0.0",
"compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)", "compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)",
"drtioaux 0.0.0", "drtioaux 0.0.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -263,10 +293,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" "checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
"checksum compiler_builtins 0.1.0 (git+https://github.com/m-labs/compiler-builtins?rev=97916b1)" = "<none>" "checksum compiler_builtins 0.1.0 (git+https://github.com/m-labs/compiler-builtins?rev=97916b1)" = "<none>"
"checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)" = "<none>" "checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)" = "<none>"
"checksum crc 1.6.0 (git+git://github.com/whitequark/crc-rs?rev=51cd356)" = "<none>"
"checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a" "checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a"
"checksum fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)" = "<none>" "checksum fringe 1.1.0 (git+https://github.com/m-labs/libfringe?rev=bd23494)" = "<none>"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
@ -275,6 +307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493" "checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493"
"checksum managed 0.4.0 (git+https://github.com/m-labs/rust-managed.git?rev=629a6786a1cf1692015f464ed16c04eafa5cb8d1)" = "<none>" "checksum managed 0.4.0 (git+https://github.com/m-labs/rust-managed.git?rev=629a6786a1cf1692015f464ed16c04eafa5cb8d1)" = "<none>"
"checksum rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe"
"checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704" "checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)" = "<none>" "checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)" = "<none>"

View File

@ -1,2 +1,2 @@
[workspace] [workspace]
members = ["runtime", "ksupport", "satman"] members = ["bootloader", "runtime", "ksupport", "satman"]

View File

@ -0,0 +1,19 @@
[package]
authors = ["M-Labs"]
name = "bootloader"
version = "0.0.0"
build = "build.rs"
[lib]
name = "bootloader"
crate-type = ["staticlib"]
path = "main.rs"
[build-dependencies]
build_misoc = { path = "../libbuild_misoc" }
[dependencies]
rlibc = "1.0"
byteorder = { version = "1.0", default-features = false }
crc = { git = "git://github.com/whitequark/crc-rs", rev = "51cd356", default-features = false }
board = { path = "../libboard", features = ["uart_console"] }

View File

@ -0,0 +1,18 @@
include ../include/generated/variables.mak
include $(MISOC_DIRECTORY)/software/common.mak
RUSTFLAGS += -Cpanic=abort
all:: bootloader.bin
.PHONY: $(RUSTOUT)/libbootloader.a
$(RUSTOUT)/libbootloader.a:
$(cargo) --manifest-path $(BOOTLOADER_DIRECTORY)/Cargo.toml -- \
-Clto
bootloader.elf: $(RUSTOUT)/libbootloader.a
$(link) -T $(BOOTLOADER_DIRECTORY)/bootloader.ld
%.bin: %.elf
$(objcopy) -O binary
$(MSCIMG) $@

View File

@ -0,0 +1,46 @@
INCLUDE generated/output_format.ld
INCLUDE generated/regions.ld
ENTRY(_reset_handler)
SECTIONS
{
.vectors :
{
_begin = .;
*(.vectors)
} > rom
.text :
{
*(.text .text.*)
} > rom
.rodata :
{
*(.rodata.*)
. = ALIGN(4);
_end = .;
} > rom
.crc ALIGN(4) :
{
_crc = .;
. += 4;
}
.bss ALIGN(4) :
{
_fbss = .;
*(.bss .bss.*)
. = ALIGN(4);
_ebss = .;
} > sram
.stack :
{
/* Ensure we have a certain amount of space available for stack. */
. = ORIGIN(sram) + LENGTH(sram) - 0x800;
. = ORIGIN(sram) + LENGTH(sram) - 4;
_fstack = .;
} > sram
}

View File

@ -0,0 +1,5 @@
extern crate build_misoc;
fn main() {
build_misoc::cfg();
}

View File

@ -0,0 +1,171 @@
#![no_std]
#![feature(lang_items)]
extern crate rlibc;
extern crate crc;
extern crate byteorder;
#[macro_use]
extern crate board;
use core::{ptr, slice};
use crc::crc32;
use byteorder::{ByteOrder, BigEndian};
use board::{boot, cache};
use board::uart_console::Console;
fn check_integrity() -> bool {
extern {
static _begin: u8;
static _end: u8;
static _crc: u32;
}
unsafe {
let length = &_end as *const u8 as usize -
&_begin as *const u8 as usize;
let bootloader = slice::from_raw_parts(&_begin as *const u8, length);
crc32::checksum_ieee(bootloader) == _crc
}
}
unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
const MEMORY: *mut u32 = board::mem::MAIN_RAM_BASE as *mut u32;
*total = 0;
*wrong = 0;
macro_rules! test {
(
$prepare:stmt;
for $i:ident in ($range:expr) {
MEMORY[$index:expr] = $data:expr
}
) => ({
$prepare;
for $i in $range {
ptr::write_volatile(MEMORY.offset($index as isize), $data);
*total += 1;
}
cache::flush_cpu_dcache();
cache::flush_l2_cache();
$prepare;
for $i in $range {
if ptr::read_volatile(MEMORY.offset($index as isize)) != $data {
*wrong += 1;
}
}
})
}
fn prng32(seed: &mut u32) -> u32 { *seed = 1664525 * *seed + 1013904223; *seed }
fn prng16(seed: &mut u16) -> u16 { *seed = 25173 * *seed + 13849; *seed }
// Test data bus
test!((); for i in (0..0x100) { MEMORY[i] = 0xAAAAAAAA });
test!((); for i in (0..0x100) { MEMORY[i] = 0x55555555 });
// Test counter addressing with random data
test!(let mut seed = 0;
for i in (0..0x100000) { MEMORY[i] = prng32(&mut seed) });
// Test random addressing with counter data
test!(let mut seed = 0;
for i in (0..0x10000) { MEMORY[prng16(&mut seed)] = i });
*wrong == 0
}
fn startup() -> bool {
if check_integrity() {
println!("Bootloader CRC passed");
} else {
println!("Bootloader CRC failed");
return false
}
println!("Initializing SDRAM...");
if unsafe { board::sdram::init(Some(&mut Console)) } {
println!("SDRAM initialized");
} else {
println!("SDRAM initialization failed");
return false
}
let (mut total, mut wrong) = (0, 0);
if unsafe { memory_test(&mut total, &mut wrong) } {
println!("Memory test passed");
} else {
println!("Memory test failed ({}/{} words incorrect)", wrong, total);
return false
}
true
}
unsafe fn flash_boot() {
const FIRMWARE: *mut u8 = board::mem::FLASH_BOOT_ADDRESS as *mut u8;
const MAIN_RAM: *mut u8 = board::mem::MAIN_RAM_BASE as *mut u8;
println!("Booting from flash...");
let header = slice::from_raw_parts(FIRMWARE, 8);
let length = BigEndian::read_u32(&header[0..]) as usize;
let expected_crc = BigEndian::read_u32(&header[4..]);
if length == 0xffffffff {
println!("No firmware present");
return
}
let firmware_in_flash = slice::from_raw_parts(FIRMWARE.offset(8), length);
let actual_crc = crc32::checksum_ieee(firmware_in_flash);
if actual_crc == expected_crc {
let firmware_in_sdram = slice::from_raw_parts_mut(MAIN_RAM, length);
firmware_in_sdram.copy_from_slice(firmware_in_flash);
println!("Starting firmware.");
boot::jump(MAIN_RAM as usize);
} else {
println!("Firmware CRC failed (actual {:08x}, expected {:08x}",
actual_crc, expected_crc);
}
}
#[no_mangle]
pub extern fn main() -> i32 {
println!("");
println!(r" __ __ _ ____ ____ ");
println!(r"| \/ (_) ___| ___ / ___|");
println!(r"| |\/| | \___ \ / _ \| | ");
println!(r"| | | | |___) | (_) | |___ ");
println!(r"|_| |_|_|____/ \___/ \____|");
println!("");
println!("MiSoC Bootloader");
println!("Copyright (c) 2017 M-Labs Limited");
println!("");
if startup() {
println!("");
unsafe { flash_boot() };
} else {
println!("Halting.");
}
loop {}
}
#[no_mangle]
pub extern fn exception(vect: u32, _regs: *const u32, pc: u32, ea: u32) {
panic!("exception {} at PC {:#08x}, EA {:#08x}", vect, pc, ea)
}
#[no_mangle]
#[lang = "panic_fmt"]
pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
println!("panic at {}:{}: {}", file, line, args);
loop {}
}

View File

@ -12,6 +12,7 @@ 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 sdram;
pub mod ident; pub mod ident;
pub mod clock; pub mod clock;
pub mod uart; pub mod uart;

View File

@ -1,18 +1,26 @@
use board::irq; use super::{irq, cache};
pub unsafe fn reboot() -> ! { pub unsafe fn reset() -> ! {
irq::set_ie(false); irq::set_ie(false);
#[cfg(target_arch="or1k")]
asm!(r#" asm!(r#"
l.j _reset_handler l.j _reset_handler
l.nop l.nop
"# : : : : "volatile"); "# : : : : "volatile");
loop {} loop {}
} }
pub unsafe fn hotswap(new_code: &[u8]) -> ! { pub unsafe fn jump(addr: usize) -> ! {
irq::set_ie(false);
cache::flush_cpu_icache();
asm!(r#"
l.jr $0
l.nop
"# : : "r"(addr) : : "volatile");
loop {}
}
pub unsafe fn hotswap(firmware: &[u8]) -> ! {
irq::set_ie(false); irq::set_ie(false);
#[cfg(target_arch="or1k")]
asm!(r#" asm!(r#"
# This loop overwrites itself, but it's structured in such a way # This loop overwrites itself, but it's structured in such a way
# that before that happens, it loads itself into I$$ fully. # that before that happens, it loads itself into I$$ fully.
@ -21,20 +29,20 @@ pub unsafe fn hotswap(new_code: &[u8]) -> ! {
l.or r7, r4, r0 l.or r7, r4, r0
0: l.sfnei r5, 0 0: l.sfnei r5, 0
l.bf 1f l.bf 1f
l.nop l.nop
l.jr r7 l.jr r7
l.nop l.nop
1: l.lwz r6, 0(r3) 1: l.lwz r6, 0(r3)
l.sw 0(r4), r6 l.sw 0(r4), r6
l.addi r3, r3, 4 l.addi r3, r3, 4
l.addi r4, r4, 4 l.addi r4, r4, 4
l.addi r5, r5, -4 l.addi r5, r5, -4
l.bf 0b l.bf 0b
l.nop l.nop
"# "#
: :
: "{r3}"(new_code.as_ptr() as usize), : "{r3}"(firmware.as_ptr() as usize),
"{r5}"(new_code.len()) "{r5}"(firmware.len())
: :
: "volatile"); : "volatile");
loop {} loop {}

View File

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

View File

@ -0,0 +1,271 @@
#[cfg(has_ddrphy)]
mod ddr {
use core::{ptr, fmt};
use core::cell::Cell;
use csr::{dfii, ddrphy};
use sdram_phy::{self, spin_cycles};
use sdram_phy::{DFII_COMMAND_CS, DFII_COMMAND_WE, DFII_COMMAND_CAS, DFII_COMMAND_RAS,
DFII_COMMAND_WRDATA, DFII_COMMAND_RDDATA};
use sdram_phy::{DFII_NPHASES, DFII_PIX_DATA_SIZE, DFII_PIX_WRDATA_ADDR, DFII_PIX_RDDATA_ADDR};
unsafe fn enable_write_leveling(enabled: bool) {
dfii::pi0_address_write(sdram_phy::DDR3_MR1 as u16 | ((enabled as u16) << 7));
dfii::pi0_baddress_write(1);
sdram_phy::command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
ddrphy::wlevel_en_write(enabled as u8);
}
#[cfg(kusddrphy)]
const DDRPHY_MAX_DELAY: u16 = 512;
#[cfg(not(kusddrphy))]
const DDRPHY_MAX_DELAY: u16 = 32;
const DQS_SIGNAL_COUNT: usize = DFII_PIX_DATA_SIZE / 2;
macro_rules! log {
($logger:expr, $( $arg:expr ),+) => (
if let &mut Some(ref mut f) = $logger {
let _ = write!(f, $( $arg ),+);
}
)
}
unsafe fn write_level(logger: &mut Option<&mut fmt::Write>,
delay: &mut [u16; DQS_SIGNAL_COUNT],
high_skew: &mut [bool; DQS_SIGNAL_COUNT]) -> bool {
log!(logger, "Write leveling: ");
enable_write_leveling(true);
spin_cycles(100);
let mut failed = false;
for n in 0..DQS_SIGNAL_COUNT {
let dq_addr = dfii::PI0_RDDATA_ADDR
.offset((DQS_SIGNAL_COUNT - 1 - n) as isize);
delay[n] = 0;
high_skew[n] = false;
ddrphy::dly_sel_write(1 << n);
ddrphy::wdly_dq_rst_write(1);
ddrphy::wdly_dqs_rst_write(1);
ddrphy::wlevel_strobe_write(1);
spin_cycles(10);
let mut incr_delay = || {
delay[n] += 1;
if delay[n] >= DDRPHY_MAX_DELAY {
failed = true;
return false
}
ddrphy::wdly_dq_inc_write(1);
ddrphy::wdly_dqs_inc_write(1);
ddrphy::wlevel_strobe_write(1);
spin_cycles(10);
true
};
let mut dq = ptr::read_volatile(dq_addr);
if dq != 0 {
// Assume this DQ group has between 1 and 2 bit times of skew.
// Bring DQS into the CK=0 zone before continuing leveling.
high_skew[n] = true;
while dq != 0 {
if !incr_delay() { break }
dq = ptr::read_volatile(dq_addr);
}
}
while dq == 0 {
if !incr_delay() { break }
dq = ptr::read_volatile(dq_addr);
}
}
enable_write_leveling(false);
for n in (0..DQS_SIGNAL_COUNT).rev() {
log!(logger, "{}{} ", delay[n], if high_skew[n] { "*" } else { "" });
}
if !failed {
log!(logger, "done\n")
} else {
log!(logger, "failed\n")
}
!failed
}
unsafe fn read_bitslip(logger: &mut Option<&mut fmt::Write>,
delay: &[u16; DQS_SIGNAL_COUNT],
high_skew: &[bool; DQS_SIGNAL_COUNT]) {
let threshold_opt = delay.iter().zip(high_skew.iter())
.filter_map(|(&delay, &high_skew)|
if high_skew { Some(delay) } else { None })
.min()
.map(|threshold| threshold / 2);
if let Some(threshold) = threshold_opt {
log!(logger, "Read bitslip: ");
for n in (0..DQS_SIGNAL_COUNT).rev() {
if delay[n] > threshold {
ddrphy::dly_sel_write(1 << n);
#[cfg(kusddrphy)]
ddrphy::rdly_dq_bitslip_write(1);
#[cfg(not(kusddrphy))]
for _ in 0..3 {
ddrphy::rdly_dq_bitslip_write(1);
}
log!(logger, "{} ", n);
}
}
log!(logger, "\n");
}
}
unsafe fn read_delays(logger: &mut Option<&mut fmt::Write>) {
log!(logger, "Read delays: ");
// Generate pseudo-random sequence
let mut prs = [0; DFII_NPHASES * DFII_PIX_DATA_SIZE];
let mut prv = 42;
for b in prs.iter_mut() {
prv = 1664525 * prv + 1013904223;
*b = prv as u8;
}
// Activate
dfii::pi0_address_write(0);
dfii::pi0_baddress_write(0);
sdram_phy::command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS);
spin_cycles(15);
// Write test pattern
for p in 0..DFII_NPHASES {
for offset in 0..DFII_PIX_DATA_SIZE {
let addr = DFII_PIX_WRDATA_ADDR[p].offset(offset as isize);
let data = prs[DFII_PIX_DATA_SIZE * p + offset];
ptr::write_volatile(addr, data as u32);
}
}
sdram_phy::dfii_piwr_address_write(0);
sdram_phy::dfii_piwr_baddress_write(0);
sdram_phy::command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|
DFII_COMMAND_WRDATA);
// Calibrate each DQ in turn
sdram_phy::dfii_pird_address_write(0);
sdram_phy::dfii_pird_baddress_write(0);
for n in 0..DQS_SIGNAL_COUNT {
ddrphy::dly_sel_write(1 << (DQS_SIGNAL_COUNT - n - 1));
ddrphy::rdly_dq_rst_write(1);
let delay = Cell::new(0);
let incr_delay_until = |expected| {
while delay.get() < DDRPHY_MAX_DELAY {
sdram_phy::command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|
DFII_COMMAND_RDDATA);
spin_cycles(15);
let mut working = true;
for p in 0..DFII_NPHASES {
for &offset in [n, n + DQS_SIGNAL_COUNT].iter() {
let addr = DFII_PIX_RDDATA_ADDR[p].offset(offset as isize);
let data = prs[DFII_PIX_DATA_SIZE * p + offset];
if ptr::read_volatile(addr) as u8 != data {
working = false;
}
}
}
if working == expected {
break
}
delay.set(delay.get() + 1);
ddrphy::rdly_dq_inc_write(1);
}
};
// Find smallest working delay
incr_delay_until(true);
let min_delay = delay.get();
// Get a bit further into the working zone
#[cfg(kusddrphy)]
for _ in 0..8 {
delay.set(delay.get() + 1);
ddrphy::rdly_dq_inc_write(1);
}
#[cfg(not(kusddrphy))]
{
delay.set(delay.get() + 1);
ddrphy::rdly_dq_inc_write(1);
}
// Find largest working delay
incr_delay_until(false);
let max_delay = delay.get();
log!(logger, "{}:{:02}-{:02} ", DQS_SIGNAL_COUNT - n - 1,
min_delay, max_delay);
// Set delay to the middle
ddrphy::rdly_dq_rst_write(1);
for _ in 0..(min_delay + max_delay) / 2 {
ddrphy::rdly_dq_inc_write(1);
}
}
// Precharge
dfii::pi0_address_write(0);
dfii::pi0_baddress_write(0);
sdram_phy::command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
spin_cycles(15);
log!(logger, "done\n");
}
pub unsafe fn level(logger: &mut Option<&mut fmt::Write>) -> bool {
let mut delay = [0; DQS_SIGNAL_COUNT];
let mut high_skew = [false; DQS_SIGNAL_COUNT];
if !write_level(logger, &mut delay, &mut high_skew) {
return false
}
read_bitslip(logger, &delay, &high_skew);
read_delays(logger);
true
}
}
use core::fmt;
use csr;
use sdram_phy;
pub unsafe fn init(mut _logger: Option<&mut fmt::Write>) -> bool {
sdram_phy::initialize();
#[cfg(has_ddrphy)]
{
if !ddr::level(&mut _logger) {
return false
}
}
csr::dfii::control_write(sdram_phy::DFII_CONTROL_SEL);
true
}

View File

@ -23,5 +23,3 @@ pub mod hmc830_7043;
mod ad9154_reg; mod ad9154_reg;
#[cfg(has_ad9154)] #[cfg(has_ad9154)]
pub mod ad9154; pub mod ad9154;
pub mod boot;

View File

@ -244,12 +244,12 @@ pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u3
println!("{:#08x}", ip); println!("{:#08x}", ip);
}); });
if config::read_str("panic_reboot", |r| r == Ok("1")) { if config::read_str("panic_reset", |r| r == Ok("1")) {
println!("rebooting..."); println!("restarting...");
unsafe { board_artiq::boot::reboot() } unsafe { board::boot::reset() }
} 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_reset 1` to restart instead");
loop {} loop {}
} }
} }

View File

@ -1,4 +1,4 @@
use board_artiq::boot; use board::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;
@ -92,8 +92,8 @@ fn worker(io: &Io, stream: &mut TcpStream) -> io::Result<()> {
Request::Reboot => { Request::Reboot => {
Reply::RebootImminent.write_to(stream)?; Reply::RebootImminent.write_to(stream)?;
stream.close()?; stream.close()?;
warn!("rebooting"); warn!("restarting");
unsafe { boot::reboot() } unsafe { boot::reset() }
} }
}; };
} }

View File

@ -259,8 +259,8 @@ def main():
if opts.srcbuild is None: if opts.srcbuild is None:
path = bin_dir path = bin_dir
else: else:
path = os.path.join(opts.srcbuild, "software", "bios") path = os.path.join(opts.srcbuild, "software", "bootloader")
programmer.flash_binary(*config["bootloader"], os.path.join(path, "bios.bin")) programmer.flash_binary(*config["bootloader"], os.path.join(path, "bootloader.bin"))
elif action == "storage": elif action == "storage":
programmer.flash_binary(*config["storage"], opts.storage) programmer.flash_binary(*config["storage"], opts.storage)
elif action == "runtime": elif action == "runtime":

View File

@ -45,11 +45,15 @@ class AMPSoC:
def build_artiq_soc(soc, argdict): def build_artiq_soc(soc, argdict):
firmware_dir = os.path.join(artiq_dir, "firmware")
builder = Builder(soc, **argdict) builder = Builder(soc, **argdict)
builder.software_packages = []
builder.add_software_package("libm") builder.add_software_package("libm")
builder.add_software_package("libprintf")
builder.add_software_package("libunwind") builder.add_software_package("libunwind")
builder.add_software_package("ksupport", os.path.join(artiq_dir, "firmware", "ksupport")) builder.add_software_package("bootloader", os.path.join(firmware_dir, "bootloader"))
builder.add_software_package("runtime", os.path.join(artiq_dir, "firmware", "runtime")) builder.add_software_package("ksupport", os.path.join(firmware_dir, "ksupport"))
builder.add_software_package("runtime", os.path.join(firmware_dir, "runtime"))
try: try:
builder.build() builder.build()
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:

View File

@ -5,5 +5,5 @@ mkdir -p $SOC_PREFIX
V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_clock V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_clock
cp misoc_nist_clock_kc705/gateware/top.bit $SOC_PREFIX cp misoc_nist_clock_kc705/gateware/top.bit $SOC_PREFIX
cp misoc_nist_clock_kc705/software/bios/bios.bin $SOC_PREFIX cp misoc_nist_clock_kc705/software/bootloader/bootloader.bin $SOC_PREFIX
cp misoc_nist_clock_kc705/software/runtime/runtime.{elf,fbi} $SOC_PREFIX cp misoc_nist_clock_kc705/software/runtime/runtime.{elf,fbi} $SOC_PREFIX

View File

@ -5,5 +5,5 @@ mkdir -p $SOC_PREFIX
V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_qc2 V=1 $PYTHON -m artiq.gateware.targets.kc705_dds -H nist_qc2
cp misoc_nist_qc2_kc705/gateware/top.bit $SOC_PREFIX cp misoc_nist_qc2_kc705/gateware/top.bit $SOC_PREFIX
cp misoc_nist_qc2_kc705/software/bios/bios.bin $SOC_PREFIX cp misoc_nist_qc2_kc705/software/bootloader/bootloader.bin $SOC_PREFIX
cp misoc_nist_qc2_kc705/software/runtime/runtime.{elf,fbi} $SOC_PREFIX cp misoc_nist_qc2_kc705/software/runtime/runtime.{elf,fbi} $SOC_PREFIX

View File

@ -5,5 +5,5 @@ mkdir -p $SOC_PREFIX
V=1 $PYTHON -m artiq.gateware.targets.sayma_amc_standalone --rtm-csr-csv $SP_DIR/artiq/binaries/sayma_rtm/sayma_rtm_csr.csv V=1 $PYTHON -m artiq.gateware.targets.sayma_amc_standalone --rtm-csr-csv $SP_DIR/artiq/binaries/sayma_rtm/sayma_rtm_csr.csv
cp misoc_standalone_sayma_amc/gateware/top.bit $SOC_PREFIX cp misoc_standalone_sayma_amc/gateware/top.bit $SOC_PREFIX
cp misoc_standalone_sayma_amc/software/bios/bios.bin $SOC_PREFIX cp misoc_standalone_sayma_amc/software/bootloader/bootloader.bin $SOC_PREFIX
cp misoc_standalone_sayma_amc/software/runtime/runtime.{elf,fbi} $SOC_PREFIX cp misoc_standalone_sayma_amc/software/runtime/runtime.{elf,fbi} $SOC_PREFIX