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",
|
"build_misoc 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)",
|
||||||
|
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=507d2fe)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -49,8 +50,9 @@ dependencies = [
|
||||||
"board 0.0.0",
|
"board 0.0.0",
|
||||||
"build_misoc 0.0.0",
|
"build_misoc 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)",
|
||||||
"crc 1.6.0 (git+git://github.com/whitequark/crc-rs?rev=51cd356)",
|
"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]]
|
[[package]]
|
||||||
|
@ -199,11 +201,6 @@ 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"
|
||||||
|
@ -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 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>"
|
||||||
|
|
|
@ -13,7 +13,17 @@ path = "main.rs"
|
||||||
build_misoc = { path = "../libbuild_misoc" }
|
build_misoc = { path = "../libbuild_misoc" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rlibc = "1.0"
|
|
||||||
byteorder = { version = "1.0", default-features = false }
|
byteorder = { version = "1.0", default-features = false }
|
||||||
crc = { git = "git://github.com/whitequark/crc-rs", rev = "51cd356", 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;
|
. += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bss ALIGN(4) :
|
.bss :
|
||||||
{
|
{
|
||||||
_fbss = .;
|
_fbss = .;
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items, compiler_builtins_lib)]
|
||||||
|
|
||||||
extern crate rlibc;
|
extern crate compiler_builtins;
|
||||||
extern crate crc;
|
extern crate crc;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
extern crate smoltcp;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate board;
|
extern crate board;
|
||||||
|
|
||||||
use core::{ptr, slice};
|
use core::{ptr, slice};
|
||||||
use crc::crc32;
|
use crc::crc32;
|
||||||
use byteorder::{ByteOrder, BigEndian};
|
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;
|
use board::uart_console::Console;
|
||||||
|
|
||||||
fn check_integrity() -> bool {
|
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;
|
const MEMORY: *mut u32 = board::mem::MAIN_RAM_BASE as *mut u32;
|
||||||
|
|
||||||
*total = 0;
|
*total = 0;
|
||||||
|
@ -43,7 +45,7 @@ unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
|
||||||
) => ({
|
) => ({
|
||||||
$prepare;
|
$prepare;
|
||||||
for $i in $range {
|
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;
|
*total += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +54,7 @@ unsafe fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
|
||||||
|
|
||||||
$prepare;
|
$prepare;
|
||||||
for $i in $range {
|
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;
|
*wrong += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +97,7 @@ fn startup() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut total, mut wrong) = (0, 0);
|
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");
|
println!("Memory test passed");
|
||||||
} else {
|
} else {
|
||||||
println!("Memory test failed ({}/{} words incorrect)", wrong, total);
|
println!("Memory test failed ({}/{} words incorrect)", wrong, total);
|
||||||
|
@ -105,36 +107,81 @@ fn startup() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn flash_boot() {
|
fn flash_boot() {
|
||||||
const FIRMWARE: *mut u8 = board::mem::FLASH_BOOT_ADDRESS as *mut u8;
|
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;
|
const MAIN_RAM: *mut u8 = board::mem::MAIN_RAM_BASE as *mut u8;
|
||||||
|
|
||||||
println!("Booting from flash...");
|
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 length = BigEndian::read_u32(&header[0..]) as usize;
|
||||||
let expected_crc = BigEndian::read_u32(&header[4..]);
|
let expected_crc = BigEndian::read_u32(&header[4..]);
|
||||||
|
|
||||||
if length == 0xffffffff {
|
if length == 0xffffffff {
|
||||||
println!("No firmware present");
|
println!("No firmware present");
|
||||||
return
|
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);
|
let actual_crc = crc32::checksum_ieee(firmware_in_flash);
|
||||||
|
|
||||||
if actual_crc == expected_crc {
|
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);
|
firmware_in_sdram.copy_from_slice(firmware_in_flash);
|
||||||
|
|
||||||
println!("Starting firmware.");
|
println!("Starting firmware.");
|
||||||
boot::jump(MAIN_RAM as usize);
|
unsafe { boot::jump(MAIN_RAM as usize) }
|
||||||
} else {
|
} else {
|
||||||
println!("Firmware CRC failed (actual {:08x}, expected {:08x}",
|
println!("Firmware CRC failed (actual {:08x}, expected {:08x})",
|
||||||
actual_crc, expected_crc);
|
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]
|
#[no_mangle]
|
||||||
pub extern fn main() -> i32 {
|
pub extern fn main() -> i32 {
|
||||||
println!("");
|
println!("");
|
||||||
|
@ -150,7 +197,8 @@ pub extern fn main() -> i32 {
|
||||||
|
|
||||||
if startup() {
|
if startup() {
|
||||||
println!("");
|
println!("");
|
||||||
unsafe { flash_boot() };
|
flash_boot();
|
||||||
|
network_boot();
|
||||||
} else {
|
} else {
|
||||||
println!("Halting.");
|
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)
|
panic!("exception {} at PC {:#08x}, EA {:#08x}", vect, pc, ea)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn abort() {
|
||||||
|
println!("aborted");
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[lang = "panic_fmt"]
|
#[lang = "panic_fmt"]
|
||||||
pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
|
pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
|
||||||
|
|
Loading…
Reference in New Issue