forked from M-Labs/artiq
Compare commits
5 Commits
a1e392fb0e
...
eec8f38e35
Author | SHA1 | Date |
---|---|---|
occheung | eec8f38e35 | |
occheung | c66c0f0bc1 | |
occheung | 0f2b15c584 | |
occheung | c17e0e2b71 | |
occheung | 64c69f46c9 |
|
@ -201,42 +201,17 @@ class CommMgmt:
|
||||||
def debug_allocator(self):
|
def debug_allocator(self):
|
||||||
self._write_header(Request.DebugAllocator)
|
self._write_header(Request.DebugAllocator)
|
||||||
|
|
||||||
def flash(self, **bin_paths):
|
def flash(self, bin_paths):
|
||||||
self._write_header(Request.Flash)
|
self._write_header(Request.Flash)
|
||||||
|
|
||||||
addr_table = {}
|
with io.BytesIO() as image_buf:
|
||||||
with io.BytesIO() as image_buf, io.BytesIO() as bin_buf:
|
for filename in bin_paths:
|
||||||
offset = 0
|
|
||||||
# Reserve 4-bytes for CRC
|
|
||||||
image_buf.write(struct.pack(self.endian + "I", 0))
|
|
||||||
# Reserve 4-bytes for header length
|
|
||||||
image_buf.write(struct.pack(self.endian + "I", 0))
|
|
||||||
image_buf.write(struct.pack(self.endian + "I", len(bin_paths)))
|
|
||||||
for bin_name, filename in bin_paths.items():
|
|
||||||
with open(filename, "rb") as fi:
|
with open(filename, "rb") as fi:
|
||||||
bin_ = fi.read()
|
bin_ = fi.read()
|
||||||
length = bin_buf.write(bin_)
|
image_buf.write(struct.pack(self.endian + "I", len(bin_)))
|
||||||
|
image_buf.write(bin_)
|
||||||
|
|
||||||
bin_name_str = bin_name.encode("utf-8")
|
crc = binascii.crc32(image_buf.getvalue())
|
||||||
image_buf.write(struct.pack(self.endian + "I", len(bin_name_str)))
|
|
||||||
image_buf.write(bin_name_str)
|
|
||||||
image_buf.write(struct.pack(self.endian + "II", offset, length))
|
|
||||||
|
|
||||||
offset += length
|
|
||||||
|
|
||||||
# header = image_buf.getvalue()
|
|
||||||
# image = image_buf.getvalue()
|
|
||||||
|
|
||||||
assert(image_buf.tell() == len(image_buf.getvalue()))
|
|
||||||
header_len = image_buf.tell() - 8
|
|
||||||
image_buf.seek(4, 0)
|
|
||||||
image_buf.write(struct.pack(self.endian + "I", header_len))
|
|
||||||
image_buf.seek(0, 2)
|
|
||||||
image_buf.write(bin_buf.getvalue())
|
|
||||||
|
|
||||||
image_buf.seek(4, 0)
|
|
||||||
crc = binascii.crc32(image_buf.read())
|
|
||||||
image_buf.seek(0, 0)
|
|
||||||
image_buf.write(struct.pack(self.endian + "I", crc))
|
image_buf.write(struct.pack(self.endian + "I", crc))
|
||||||
|
|
||||||
self._write_bytes(image_buf.getvalue())
|
self._write_bytes(image_buf.getvalue())
|
||||||
|
|
|
@ -554,6 +554,8 @@ dependencies = [
|
||||||
"board_artiq",
|
"board_artiq",
|
||||||
"board_misoc",
|
"board_misoc",
|
||||||
"build_misoc",
|
"build_misoc",
|
||||||
|
"byteorder",
|
||||||
|
"crc",
|
||||||
"cslice",
|
"cslice",
|
||||||
"eh",
|
"eh",
|
||||||
"io",
|
"io",
|
||||||
|
|
|
@ -114,40 +114,6 @@ pub unsafe fn write(mut addr: usize, mut data: &[u8]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub unsafe fn write_image(image: &[u8]) {
|
|
||||||
// let image = &image[..];
|
|
||||||
// let actual_crc = crc32::checksum_ieee(image);
|
|
||||||
|
|
||||||
// if actual_crc == expected_crc {
|
|
||||||
// let mut reader = Cursor::new(header);
|
|
||||||
// let bin_no = reader.read_u32().unwrap() as usize;
|
|
||||||
// for _ in 0..bin_no {
|
|
||||||
// let bin_name = reader.read_string().unwrap();
|
|
||||||
// let offset = reader.read_u32().unwrap() as usize;
|
|
||||||
// let len = reader.read_u32().unwrap() as usize;
|
|
||||||
|
|
||||||
// let origin = match bin_name.as_str() {
|
|
||||||
// "gateware" => 0,
|
|
||||||
// "bootloader" => mem::ROM_BASE,
|
|
||||||
// "firmware" => mem::FLASH_BOOT_ADDRESS,
|
|
||||||
// _ => {
|
|
||||||
// error!("unexpected binary component {}", bin_name);
|
|
||||||
// return Ok(Reply::Error.write_to(stream)?);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// unsafe {
|
|
||||||
// spiflash::flash_binary(origin, &image[offset..offset+len]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// reboot(_io, stream)?;
|
|
||||||
// } else {
|
|
||||||
// error!("CRC failed in SDRAM (actual {:08x}, expected {:08x})", actual_crc, expected_crc);
|
|
||||||
// Reply::Error.write_to(stream)?;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub unsafe fn flash_binary(origin: usize, payload: &[u8]) {
|
pub unsafe fn flash_binary(origin: usize, payload: &[u8]) {
|
||||||
assert!((origin & (SECTOR_SIZE - 1)) == 0);
|
assert!((origin & (SECTOR_SIZE - 1)) == 0);
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
|
|
@ -139,6 +139,9 @@ pub enum Packet {
|
||||||
CoreMgmtConfigEraseRequest { destination: u8 },
|
CoreMgmtConfigEraseRequest { destination: u8 },
|
||||||
CoreMgmtRebootRequest { destination: u8 },
|
CoreMgmtRebootRequest { destination: u8 },
|
||||||
CoreMgmtAllocatorDebugRequest { destination: u8 },
|
CoreMgmtAllocatorDebugRequest { destination: u8 },
|
||||||
|
CoreMgmtFlashRequest { destination: u8, last: bool, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
||||||
|
CoreMgmtDropLinkAck { destination: u8 },
|
||||||
|
CoreMgmtDropLink,
|
||||||
CoreMgmtGetLogReply { last: bool, length: u16, data: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
CoreMgmtGetLogReply { last: bool, length: u16, data: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
||||||
CoreMgmtConfigReadReply { last: bool, length: u16, value: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
CoreMgmtConfigReadReply { last: bool, length: u16, value: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
||||||
CoreMgmtReply { succeeded: bool },
|
CoreMgmtReply { succeeded: bool },
|
||||||
|
@ -503,6 +506,23 @@ impl Packet {
|
||||||
0xdd => Packet::CoreMgmtReply {
|
0xdd => Packet::CoreMgmtReply {
|
||||||
succeeded: reader.read_bool()?,
|
succeeded: reader.read_bool()?,
|
||||||
},
|
},
|
||||||
|
0xde => {
|
||||||
|
let destination = reader.read_u8()?;
|
||||||
|
let last = reader.read_bool()?;
|
||||||
|
let length = reader.read_u16()?;
|
||||||
|
let mut data: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
|
||||||
|
reader.read_exact(&mut data[0..length as usize])?;
|
||||||
|
Packet::CoreMgmtFlashRequest {
|
||||||
|
destination: destination,
|
||||||
|
last: last,
|
||||||
|
length: length,
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0xdf => Packet::CoreMgmtDropLink,
|
||||||
|
0xe0 => Packet::CoreMgmtDropLinkAck {
|
||||||
|
destination: reader.read_u8()?,
|
||||||
|
},
|
||||||
|
|
||||||
ty => return Err(Error::UnknownPacket(ty))
|
ty => return Err(Error::UnknownPacket(ty))
|
||||||
})
|
})
|
||||||
|
@ -873,6 +893,19 @@ impl Packet {
|
||||||
writer.write_u8(0xdd)?;
|
writer.write_u8(0xdd)?;
|
||||||
writer.write_bool(succeeded)?;
|
writer.write_bool(succeeded)?;
|
||||||
},
|
},
|
||||||
|
Packet::CoreMgmtFlashRequest { destination, last, length, data } => {
|
||||||
|
writer.write_u8(0xde)?;
|
||||||
|
writer.write_u8(destination)?;
|
||||||
|
writer.write_bool(last)?;
|
||||||
|
writer.write_u16(length)?;
|
||||||
|
writer.write_all(&data[..length as usize])?;
|
||||||
|
},
|
||||||
|
Packet::CoreMgmtDropLink =>
|
||||||
|
writer.write_u8(0xdf)?,
|
||||||
|
Packet::CoreMgmtDropLinkAck { destination } => {
|
||||||
|
writer.write_u8(0xe0)?;
|
||||||
|
writer.write_u8(destination)?;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,12 @@ impl From<SchedError> for Error<SchedError> {
|
||||||
|
|
||||||
mod local_coremgmt {
|
mod local_coremgmt {
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
|
use byteorder::{ByteOrder, NativeEndian};
|
||||||
use crc::crc32;
|
use crc::crc32;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
|
||||||
use board_misoc::{config, mem, spiflash};
|
use board_misoc::{config, mem, spiflash};
|
||||||
use io::{Cursor, Write, ProtoWrite, ProtoRead, Error as IoError};
|
use io::{Write, ProtoWrite, Error as IoError};
|
||||||
use logger_artiq::BufferLogger;
|
use logger_artiq::BufferLogger;
|
||||||
use mgmt_proto::{Error, Reply};
|
use mgmt_proto::{Error, Reply};
|
||||||
use sched::{Io, TcpStream, Error as SchedError};
|
use sched::{Io, TcpStream, Error as SchedError};
|
||||||
|
@ -136,44 +137,30 @@ mod local_coremgmt {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flash(_io: &Io, stream: &mut TcpStream, image: &Vec<u8>) -> Result<(), Error<SchedError>> {
|
pub fn flash(_io: &Io, stream: &mut TcpStream, image: &[u8]) -> Result<(), Error<SchedError>> {
|
||||||
let mut reader = Cursor::new(&image[..]);
|
let (expected_crc, mut image) = {
|
||||||
let expected_crc = reader.read_u32().unwrap();
|
let (image, crc_slice) = image.split_at(image.len() - 4);
|
||||||
|
(NativeEndian::read_u32(crc_slice), image)
|
||||||
|
};
|
||||||
|
|
||||||
let image = &image[4..];
|
|
||||||
let actual_crc = crc32::checksum_ieee(image);
|
let actual_crc = crc32::checksum_ieee(image);
|
||||||
|
|
||||||
if actual_crc == expected_crc {
|
if actual_crc == expected_crc {
|
||||||
info!("Checksum matched");
|
let bin_origins = [
|
||||||
let header_size = reader.read_u32().unwrap() as usize;
|
("gateware" , 0 ),
|
||||||
let header_offset = reader.position();
|
("bootloader", mem::ROM_BASE ),
|
||||||
let bin_offset = header_offset + header_size;
|
("firmware" , mem::FLASH_BOOT_ADDRESS),
|
||||||
|
];
|
||||||
|
|
||||||
let header = &image[header_offset..bin_offset];
|
for (name, origin) in bin_origins {
|
||||||
let binaries = &image[bin_offset..];
|
info!("Flashing {} binary...", name);
|
||||||
|
let size = NativeEndian::read_u32(&image[..4]) as usize;
|
||||||
|
image = &image[4..];
|
||||||
|
|
||||||
info!("found header of size {}", header.len());
|
let (bin, remaining) = image.split_at(size);
|
||||||
|
image = remaining;
|
||||||
|
|
||||||
let mut reader = Cursor::new(header);
|
unsafe { spiflash::flash_binary(origin, bin) };
|
||||||
let bin_no = reader.read_u32().unwrap() as usize;
|
|
||||||
for _ in 0..bin_no {
|
|
||||||
let bin_name = reader.read_string().unwrap();
|
|
||||||
let offset = reader.read_u32().unwrap() as usize;
|
|
||||||
let len = reader.read_u32().unwrap() as usize;
|
|
||||||
|
|
||||||
let origin = match bin_name.as_str() {
|
|
||||||
"gateware" => 0,
|
|
||||||
"bootloader" => mem::ROM_BASE,
|
|
||||||
"firmware" => mem::FLASH_BOOT_ADDRESS,
|
|
||||||
_ => {
|
|
||||||
error!("unexpected binary component {}", bin_name);
|
|
||||||
return Ok(Reply::Error.write_to(stream)?);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
spiflash::flash_binary(origin, &binaries[offset..offset+len]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reboot(_io, stream)?;
|
reboot(_io, stream)?;
|
||||||
|
@ -190,7 +177,7 @@ mod remote_coremgmt {
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
|
||||||
use board_artiq::{drtioaux::Packet, drtio_routing};
|
use board_artiq::{drtioaux, drtioaux::Packet, drtio_routing};
|
||||||
use io::{Cursor, ProtoWrite};
|
use io::{Cursor, ProtoWrite};
|
||||||
use mgmt_proto::{Error, Reply};
|
use mgmt_proto::{Error, Reply};
|
||||||
use rtio_mgt::drtio;
|
use rtio_mgt::drtio;
|
||||||
|
@ -534,8 +521,43 @@ mod remote_coremgmt {
|
||||||
pub fn flash(io: &Io, aux_mutex: &Mutex,
|
pub fn flash(io: &Io, aux_mutex: &Mutex,
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
||||||
destination: u8, stream: &mut TcpStream, image: &Vec<u8>) -> Result<(), Error<SchedError>> {
|
destination: u8, stream: &mut TcpStream, image: &[u8]) -> Result<(), Error<SchedError>> {
|
||||||
todo!()
|
|
||||||
|
match drtio::partition_data(&image, |slice, status, len: usize| {
|
||||||
|
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
||||||
|
&Packet::CoreMgmtFlashRequest {
|
||||||
|
destination: destination, length: len as u16, last: status.is_last(), data: *slice});
|
||||||
|
match reply {
|
||||||
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => Ok(()),
|
||||||
|
Ok(Packet::CoreMgmtDropLink) => {
|
||||||
|
if status.is_last() {
|
||||||
|
drtioaux::send(
|
||||||
|
linkno, &Packet::CoreMgmtDropLinkAck { destination: destination }
|
||||||
|
).map_err(|_| drtio::Error::AuxError)
|
||||||
|
} else {
|
||||||
|
error!("received unexpected drop link packet");
|
||||||
|
Err(drtio::Error::UnexpectedReply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(packet) => {
|
||||||
|
error!("received unexpected aux packet: {:?}", packet);
|
||||||
|
Err(drtio::Error::UnexpectedReply)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("aux packet error ({})", e);
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Ok(()) => {
|
||||||
|
Reply::RebootImminent.write_to(stream)?;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
Reply::Error.write_to(stream)?;
|
||||||
|
Err(e.into())
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,7 +601,7 @@ fn worker(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _subkernel_mutex: &M
|
||||||
Request::ConfigErase => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, config_erase),
|
Request::ConfigErase => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, config_erase),
|
||||||
Request::Reboot => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, reboot),
|
Request::Reboot => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, reboot),
|
||||||
Request::DebugAllocator => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, debug_allocator),
|
Request::DebugAllocator => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, debug_allocator),
|
||||||
Request::Flash { ref image } => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, flash, image),
|
Request::Flash { ref image } => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, flash, &image[..]),
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ build_misoc = { path = "../libbuild_misoc" }
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = { version = "0.4", default-features = false }
|
log = { version = "0.4", default-features = false }
|
||||||
io = { path = "../libio", features = ["byteorder", "alloc"] }
|
io = { path = "../libio", features = ["byteorder", "alloc"] }
|
||||||
|
byteorder = { version = "1.0", default-features = false }
|
||||||
|
crc = { version = "1.7", default-features = false }
|
||||||
cslice = { version = "0.3" }
|
cslice = { version = "0.3" }
|
||||||
board_misoc = { path = "../libboard_misoc", features = ["uart_console", "log"] }
|
board_misoc = { path = "../libboard_misoc", features = ["uart_console", "log"] }
|
||||||
board_artiq = { path = "../libboard_artiq", features = ["alloc"] }
|
board_artiq = { path = "../libboard_artiq", features = ["alloc"] }
|
||||||
|
|
|
@ -9,6 +9,8 @@ extern crate board_artiq;
|
||||||
extern crate riscv;
|
extern crate riscv;
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate proto_artiq;
|
extern crate proto_artiq;
|
||||||
|
extern crate byteorder;
|
||||||
|
extern crate crc;
|
||||||
extern crate cslice;
|
extern crate cslice;
|
||||||
extern crate io;
|
extern crate io;
|
||||||
extern crate eh;
|
extern crate eh;
|
||||||
|
@ -552,10 +554,10 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtConfigWriteRequest { destination: _destination, length, last, data } => {
|
drtioaux::Packet::CoreMgmtConfigWriteRequest { destination: _destination, last, length, data } => {
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
||||||
|
|
||||||
coremgr.add_data(&data, length as usize);
|
coremgr.add_config_data(&data, length as usize);
|
||||||
if last {
|
if last {
|
||||||
coremgr.write_config()
|
coremgr.write_config()
|
||||||
} else {
|
} else {
|
||||||
|
@ -579,6 +581,33 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
|
||||||
warn!("restarting");
|
warn!("restarting");
|
||||||
unsafe { spiflash::reload(); }
|
unsafe { spiflash::reload(); }
|
||||||
}
|
}
|
||||||
|
drtioaux::Packet::CoreMgmtFlashRequest { destination: _destination, last, length, data } => {
|
||||||
|
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
||||||
|
|
||||||
|
coremgr.add_image_data(&data, length as usize);
|
||||||
|
if last {
|
||||||
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtDropLink)
|
||||||
|
} else {
|
||||||
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drtioaux::Packet::CoreMgmtDropLinkAck { destination: _destination } => {
|
||||||
|
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
||||||
|
|
||||||
|
#[cfg(not(soc_platform = "efc"))]
|
||||||
|
unsafe {
|
||||||
|
csr::gt_drtio::txenable_write(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_drtio_eem)]
|
||||||
|
unsafe {
|
||||||
|
csr::eem_transceiver::txenable_write(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
coremgr.flash_image();
|
||||||
|
warn!("restarting");
|
||||||
|
unsafe { spiflash::reload(); }
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
warn!("received unexpected aux packet");
|
warn!("received unexpected aux packet");
|
||||||
|
|
|
@ -1,21 +1,25 @@
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use byteorder::{ByteOrder, NativeEndian};
|
||||||
|
use crc::crc32;
|
||||||
|
|
||||||
use routing::{Sliceable, SliceMeta};
|
use routing::{Sliceable, SliceMeta};
|
||||||
use board_artiq::drtioaux;
|
use board_artiq::drtioaux;
|
||||||
use board_misoc::{clock, config, csr, spiflash};
|
use board_misoc::{mem, config, spiflash};
|
||||||
use io::{Cursor, ProtoRead, ProtoWrite};
|
use io::{Cursor, ProtoRead, ProtoWrite};
|
||||||
use proto_artiq::drtioaux_proto::SAT_PAYLOAD_MAX_SIZE;
|
use proto_artiq::drtioaux_proto::SAT_PAYLOAD_MAX_SIZE;
|
||||||
|
|
||||||
|
|
||||||
pub struct Manager {
|
pub struct Manager {
|
||||||
current_payload: Cursor<Vec<u8>>,
|
config_payload: Cursor<Vec<u8>>,
|
||||||
|
image_payload: Cursor<Vec<u8>>,
|
||||||
last_value: Sliceable,
|
last_value: Sliceable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn new() -> Manager {
|
pub fn new() -> Manager {
|
||||||
Manager {
|
Manager {
|
||||||
current_payload: Cursor::new(Vec::new()),
|
config_payload: Cursor::new(Vec::new()),
|
||||||
|
image_payload: Cursor::new(Vec::new()),
|
||||||
last_value: Sliceable::new(0, Vec::new()),
|
last_value: Sliceable::new(0, Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,49 +34,70 @@ impl Manager {
|
||||||
self.last_value.get_slice_sat(data_slice)
|
self.last_value.get_slice_sat(data_slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_data(&mut self, data: &[u8], data_len: usize) {
|
pub fn add_config_data(&mut self, data: &[u8], data_len: usize) {
|
||||||
self.current_payload.write_all(&data[..data_len]).unwrap();
|
self.config_payload.write_all(&data[..data_len]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_data(&mut self) {
|
pub fn clear_config_data(&mut self) {
|
||||||
self.current_payload.get_mut().clear();
|
self.config_payload.get_mut().clear();
|
||||||
self.current_payload.set_position(0);
|
self.config_payload.set_position(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_config(&mut self) -> Result<(), drtioaux::Error<!>> {
|
pub fn write_config(&mut self) -> Result<(), drtioaux::Error<!>> {
|
||||||
let key = match self.current_payload.read_string() {
|
let key = match self.config_payload.read_string() {
|
||||||
Ok(key) => key,
|
Ok(key) => key,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.clear_data();
|
self.clear_config_data();
|
||||||
error!("error on reading key: {:?}", err);
|
error!("error on reading key: {:?}", err);
|
||||||
return drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false });
|
return drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = self.current_payload.read_bytes().unwrap();
|
let value = self.config_payload.read_bytes().unwrap();
|
||||||
|
|
||||||
match key.as_str() {
|
|
||||||
"gateware" | "bootloader" | "firmware" => {
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })?;
|
|
||||||
#[cfg(not(soc_platform = "efc"))]
|
|
||||||
unsafe {
|
|
||||||
clock::spin_us(10000);
|
|
||||||
csr::gt_drtio::txenable_write(0);
|
|
||||||
}
|
|
||||||
config::write(&key, &value).expect("failed to write to flash storage");
|
|
||||||
warn!("restarting");
|
|
||||||
unsafe { spiflash::reload(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
let succeeded = config::write(&key, &value).map_err(|err| {
|
let succeeded = config::write(&key, &value).map_err(|err| {
|
||||||
error!("error on writing config: {:?}", err);
|
error!("error on writing config: {:?}", err);
|
||||||
}).is_ok();
|
}).is_ok();
|
||||||
|
|
||||||
self.clear_data();
|
self.clear_config_data();
|
||||||
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded })
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_image_data(&mut self, data: &[u8], data_len: usize) {
|
||||||
|
self.image_payload.write_all(&data[..data_len]).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flash_image(&self) {
|
||||||
|
let image = &self.image_payload.get_ref()[..];
|
||||||
|
|
||||||
|
let (expected_crc, mut image) = {
|
||||||
|
let (image, crc_slice) = image.split_at(image.len() - 4);
|
||||||
|
(NativeEndian::read_u32(crc_slice), image)
|
||||||
|
};
|
||||||
|
|
||||||
|
let actual_crc = crc32::checksum_ieee(image);
|
||||||
|
|
||||||
|
if actual_crc == expected_crc {
|
||||||
|
let bin_origins = [
|
||||||
|
("gateware" , 0 ),
|
||||||
|
("bootloader", mem::ROM_BASE ),
|
||||||
|
("firmware" , mem::FLASH_BOOT_ADDRESS),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (name, origin) in bin_origins {
|
||||||
|
info!("flashing {} binary...", name);
|
||||||
|
let size = NativeEndian::read_u32(&image[..4]) as usize;
|
||||||
|
image = &image[4..];
|
||||||
|
|
||||||
|
let (bin, remaining) = image.split_at(size);
|
||||||
|
image = remaining;
|
||||||
|
|
||||||
|
unsafe { spiflash::flash_binary(origin, bin) };
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
panic!("CRC failed in SDRAM (actual {:08x}, expected {:08x})", actual_crc, expected_crc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,10 @@ def get_argparser():
|
||||||
p_directory = t_flash.add_argument("directory", metavar="DIRECTORY", type=str,
|
p_directory = t_flash.add_argument("directory", metavar="DIRECTORY", type=str,
|
||||||
help="directory that contains the binaries")
|
help="directory that contains the binaries")
|
||||||
|
|
||||||
|
p_srcbuild = t_flash.add_argument("--srcbuild",
|
||||||
|
help="board binaries directory is laid out as a source build tree",
|
||||||
|
default=False, action="store_true")
|
||||||
|
|
||||||
# misc debug
|
# misc debug
|
||||||
t_debug = tools.add_parser("debug",
|
t_debug = tools.add_parser("debug",
|
||||||
help="specialized debug functions")
|
help="specialized debug functions")
|
||||||
|
@ -156,6 +160,15 @@ def main():
|
||||||
mgmt.config_erase()
|
mgmt.config_erase()
|
||||||
|
|
||||||
if args.tool == "flash":
|
if args.tool == "flash":
|
||||||
|
def artifact_path(this_binary_dir, *path_filename):
|
||||||
|
if args.srcbuild:
|
||||||
|
# source tree - use path elements to locate file
|
||||||
|
return os.path.join(this_binary_dir, *path_filename)
|
||||||
|
else:
|
||||||
|
# flat tree - all files in the same directory, discard path elements
|
||||||
|
*_, filename = path_filename
|
||||||
|
return os.path.join(this_binary_dir, filename)
|
||||||
|
|
||||||
def convert_gateware(bit_filename):
|
def convert_gateware(bit_filename):
|
||||||
bin_handle, bin_filename = tempfile.mkstemp(
|
bin_handle, bin_filename = tempfile.mkstemp(
|
||||||
prefix="artiq_", suffix="_" + os.path.basename(bit_filename))
|
prefix="artiq_", suffix="_" + os.path.basename(bit_filename))
|
||||||
|
@ -164,12 +177,13 @@ def main():
|
||||||
atexit.register(lambda: os.unlink(bin_filename))
|
atexit.register(lambda: os.unlink(bin_filename))
|
||||||
return bin_filename
|
return bin_filename
|
||||||
|
|
||||||
gateware = convert_gateware(os.path.join(args.directory, "top.bit"))
|
gateware = convert_gateware(
|
||||||
bootloader = os.path.join(args.directory, "bootloader.bin")
|
artifact_path(args.directory, "gateware", "top.bit"))
|
||||||
|
bootloader = artifact_path(args.directory, "software", "bootloader", "bootloader.bin")
|
||||||
|
|
||||||
firmwares = []
|
firmwares = []
|
||||||
for firmware in "satman", "runtime":
|
for firmware in "satman", "runtime":
|
||||||
filename = os.path.join(args.directory, firmware + ".fbi")
|
filename = artifact_path(args.directory, "software", firmware, firmware + ".fbi")
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
firmwares.append(filename)
|
firmwares.append(filename)
|
||||||
if not firmwares:
|
if not firmwares:
|
||||||
|
@ -179,12 +193,8 @@ def main():
|
||||||
"Found firmware files: {}".format(" ".join(firmwares)))
|
"Found firmware files: {}".format(" ".join(firmwares)))
|
||||||
firmware = firmwares[0]
|
firmware = firmwares[0]
|
||||||
|
|
||||||
bins = {
|
bins = [ gateware, bootloader, firmware ]
|
||||||
"gateware": gateware,
|
mgmt.flash(bins)
|
||||||
"bootloader": bootloader,
|
|
||||||
"firmware": firmware,
|
|
||||||
}
|
|
||||||
mgmt.flash(**bins)
|
|
||||||
|
|
||||||
if args.tool == "reboot":
|
if args.tool == "reboot":
|
||||||
mgmt.reboot()
|
mgmt.reboot()
|
||||||
|
|
Loading…
Reference in New Issue