forked from M-Labs/artiq
bootloader: add basic network support.
This commit is contained in:
parent
d2687ce3c4
commit
3505878176
|
@ -29,6 +29,7 @@ dependencies = [
|
|||
"build_misoc 0.0.0",
|
||||
"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)",
|
||||
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -49,8 +50,9 @@ dependencies = [
|
|||
"board 0.0.0",
|
||||
"build_misoc 0.0.0",
|
||||
"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)",
|
||||
"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)",
|
||||
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -199,11 +201,6 @@ dependencies = [
|
|||
"std_artiq 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlibc"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "runtime"
|
||||
version = "0.0.0"
|
||||
|
@ -307,7 +304,6 @@ 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_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 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 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>"
|
||||
|
|
|
@ -13,7 +13,17 @@ path = "main.rs"
|
|||
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"] }
|
||||
board = { path = "../libboard", features = ["uart_console", "smoltcp"] }
|
||||
|
||||
[dependencies.compiler_builtins]
|
||||
git = "https://github.com/m-labs/compiler-builtins"
|
||||
rev = "97916b1"
|
||||
features = ["mem"]
|
||||
|
||||
[dependencies.smoltcp]
|
||||
git = "https://github.com/m-labs/smoltcp"
|
||||
rev = "507d2fe"
|
||||
default-features = false
|
||||
features = ["proto-ipv4", "socket-tcp"]
|
||||
|
|
|
@ -28,7 +28,7 @@ SECTIONS
|
|||
. += 4;
|
||||
}
|
||||
|
||||
.bss ALIGN(4) :
|
||||
.bss :
|
||||
{
|
||||
_fbss = .;
|
||||
*(.bss .bss.*)
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
#![no_std]
|
||||
#![feature(lang_items)]
|
||||
#![feature(lang_items, compiler_builtins_lib)]
|
||||
|
||||
extern crate rlibc;
|
||||
extern crate compiler_builtins;
|
||||
extern crate crc;
|
||||
extern crate byteorder;
|
||||
extern crate smoltcp;
|
||||
#[macro_use]
|
||||
extern crate board;
|
||||
|
||||
use core::{ptr, slice};
|
||||
use crc::crc32;
|
||||
use byteorder::{ByteOrder, BigEndian};
|
||||
use board::{boot, cache};
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
|
||||
use board::{boot, cache, clock, config, ethmac};
|
||||
use board::uart_console::Console;
|
||||
|
||||
fn check_integrity() -> bool {
|
||||
|
@ -28,7 +30,7 @@ fn check_integrity() -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
|
||||
fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
|
||||
const MEMORY: *mut u32 = board::mem::MAIN_RAM_BASE as *mut u32;
|
||||
|
||||
*total = 0;
|
||||
|
@ -43,7 +45,7 @@ unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
|
|||
) => ({
|
||||
$prepare;
|
||||
for $i in $range {
|
||||
ptr::write_volatile(MEMORY.offset($index as isize), $data);
|
||||
unsafe { ptr::write_volatile(MEMORY.offset($index as isize), $data) };
|
||||
*total += 1;
|
||||
}
|
||||
|
||||
|
@ -52,7 +54,7 @@ unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
|
|||
|
||||
$prepare;
|
||||
for $i in $range {
|
||||
if ptr::read_volatile(MEMORY.offset($index as isize)) != $data {
|
||||
if unsafe { ptr::read_volatile(MEMORY.offset($index as isize)) } != $data {
|
||||
*wrong += 1;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +97,7 @@ fn startup() -> bool {
|
|||
}
|
||||
|
||||
let (mut total, mut wrong) = (0, 0);
|
||||
if unsafe { memory_test(&mut total, &mut wrong) } {
|
||||
if memory_test(&mut total, &mut wrong) {
|
||||
println!("Memory test passed");
|
||||
} else {
|
||||
println!("Memory test failed ({}/{} words incorrect)", wrong, total);
|
||||
|
@ -105,36 +107,81 @@ fn startup() -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
unsafe fn flash_boot() {
|
||||
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 header = unsafe { 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
|
||||
} else if length > 4 * 1024 * 1024 {
|
||||
println!("Firmware too large (is it corrupted?)");
|
||||
return
|
||||
}
|
||||
|
||||
let firmware_in_flash = slice::from_raw_parts(FIRMWARE.offset(8), length);
|
||||
let firmware_in_flash = unsafe { 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);
|
||||
let firmware_in_sdram = unsafe { 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);
|
||||
unsafe { boot::jump(MAIN_RAM as usize) }
|
||||
} else {
|
||||
println!("Firmware CRC failed (actual {:08x}, expected {:08x}",
|
||||
println!("Firmware CRC failed (actual {:08x}, expected {:08x})",
|
||||
actual_crc, expected_crc);
|
||||
}
|
||||
}
|
||||
|
||||
fn network_boot() {
|
||||
println!("Initializing network...");
|
||||
|
||||
let eth_addr = match config::read_str("mac", |r| r.map(|s| s.parse())) {
|
||||
Ok(Ok(addr)) => addr,
|
||||
_ => EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01])
|
||||
};
|
||||
|
||||
let ip_addr = match config::read_str("ip", |r| r.map(|s| s.parse())) {
|
||||
Ok(Ok(addr)) => addr,
|
||||
_ => IpAddress::v4(192, 168, 1, 50)
|
||||
};
|
||||
|
||||
println!("Using MAC address {} and IP address {}", eth_addr, ip_addr);
|
||||
|
||||
let net_device = unsafe { ethmac::EthernetDevice::new() };
|
||||
let mut neighbor_cache_storage = [None; 2];
|
||||
let neighbor_cache =
|
||||
smoltcp::iface::NeighborCache::new(&mut neighbor_cache_storage[..]);
|
||||
let mut ip_addrs = [IpCidr::new(ip_addr, 0)];
|
||||
let mut interface =
|
||||
smoltcp::iface::EthernetInterfaceBuilder::new(net_device)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.ethernet_addr(eth_addr)
|
||||
.ip_addrs(&mut ip_addrs[..])
|
||||
.finalize();
|
||||
|
||||
let mut socket_set_storage = [];
|
||||
let mut sockets =
|
||||
smoltcp::socket::SocketSet::new(&mut socket_set_storage[..]);
|
||||
|
||||
println!("Waiting for connections...");
|
||||
|
||||
loop {
|
||||
match interface.poll(&mut sockets, clock::get_ms()) {
|
||||
Ok(_) => (),
|
||||
Err(smoltcp::Error::Unrecognized) => (),
|
||||
Err(err) => println!("Network error: {}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn main() -> i32 {
|
||||
println!("");
|
||||
|
@ -150,7 +197,8 @@ pub extern fn main() -> i32 {
|
|||
|
||||
if startup() {
|
||||
println!("");
|
||||
unsafe { flash_boot() };
|
||||
flash_boot();
|
||||
network_boot();
|
||||
} else {
|
||||
println!("Halting.");
|
||||
}
|
||||
|
@ -163,6 +211,12 @@ 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]
|
||||
pub extern fn abort() {
|
||||
println!("aborted");
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[lang = "panic_fmt"]
|
||||
pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
|
||||
|
|
Loading…
Reference in New Issue