forked from M-Labs/artiq
Compare commits
No commits in common. "a1e392fb0e204c4ae6317919577c53c195d64a0f" and "86f692fe7b003866d502418c65fc3067148095f2" have entirely different histories.
a1e392fb0e
...
86f692fe7b
|
@ -1,7 +1,5 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import binascii
|
|
||||||
import logging
|
import logging
|
||||||
import io
|
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from sipyco.keepalive import create_connection
|
from sipyco.keepalive import create_connection
|
||||||
|
@ -25,8 +23,6 @@ class Request(Enum):
|
||||||
|
|
||||||
DebugAllocator = 8
|
DebugAllocator = 8
|
||||||
|
|
||||||
Flash = 9
|
|
||||||
|
|
||||||
|
|
||||||
class Reply(Enum):
|
class Reply(Enum):
|
||||||
Success = 1
|
Success = 1
|
||||||
|
@ -50,17 +46,15 @@ class LogLevel(Enum):
|
||||||
|
|
||||||
|
|
||||||
class CommMgmt:
|
class CommMgmt:
|
||||||
def __init__(self, host, port=1380, drtio_dest=0):
|
def __init__(self, host, port=1380):
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.drtio_dest = drtio_dest
|
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
if hasattr(self, "socket"):
|
if hasattr(self, "socket"):
|
||||||
return
|
return
|
||||||
self.socket = create_connection(self.host, self.port)
|
self.socket = create_connection(self.host, self.port)
|
||||||
self.socket.sendall(b"ARTIQ management\n")
|
self.socket.sendall(b"ARTIQ management\n")
|
||||||
self._write_int8(self.drtio_dest)
|
|
||||||
endian = self._read(1)
|
endian = self._read(1)
|
||||||
if endian == b"e":
|
if endian == b"e":
|
||||||
self.endian = "<"
|
self.endian = "<"
|
||||||
|
@ -200,45 +194,3 @@ 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):
|
|
||||||
self._write_header(Request.Flash)
|
|
||||||
|
|
||||||
addr_table = {}
|
|
||||||
with io.BytesIO() as image_buf, io.BytesIO() as bin_buf:
|
|
||||||
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:
|
|
||||||
bin_ = fi.read()
|
|
||||||
length = bin_buf.write(bin_)
|
|
||||||
|
|
||||||
bin_name_str = bin_name.encode("utf-8")
|
|
||||||
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))
|
|
||||||
|
|
||||||
self._write_bytes(image_buf.getvalue())
|
|
||||||
|
|
||||||
self._read_expect(Reply.RebootImminent)
|
|
||||||
|
|
|
@ -513,7 +513,6 @@ dependencies = [
|
||||||
"board_misoc",
|
"board_misoc",
|
||||||
"build_misoc",
|
"build_misoc",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"crc",
|
|
||||||
"cslice",
|
"cslice",
|
||||||
"dyld",
|
"dyld",
|
||||||
"eh",
|
"eh",
|
||||||
|
|
|
@ -259,12 +259,39 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(key: &str, value: &[u8]) -> Result<(), Error> {
|
pub fn write(key: &str, value: &[u8]) -> Result<(), Error> {
|
||||||
match append(key, value) {
|
fn flash_binary(origin: usize, payload: &[u8]) {
|
||||||
Err(Error::SpaceExhausted) => {
|
let mut offset = 0;
|
||||||
compact()?;
|
while offset < payload.len() {
|
||||||
append(key, value)
|
unsafe {
|
||||||
|
spiflash::erase_sector(origin + offset);
|
||||||
|
}
|
||||||
|
offset += spiflash::SECTOR_SIZE;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
spiflash::write(origin, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match key {
|
||||||
|
"gateware" => {
|
||||||
|
flash_binary(0, value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
"bootloader" => {
|
||||||
|
flash_binary(::mem::ROM_BASE, value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
"firmware" => {
|
||||||
|
flash_binary(::mem::FLASH_BOOT_ADDRESS, value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => match append(key, value) {
|
||||||
|
Err(Error::SpaceExhausted) => {
|
||||||
|
compact()?;
|
||||||
|
append(key, value)
|
||||||
|
}
|
||||||
|
res => res
|
||||||
}
|
}
|
||||||
res => res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,50 +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]) {
|
|
||||||
assert!((origin & (SECTOR_SIZE - 1)) == 0);
|
|
||||||
let mut offset = 0;
|
|
||||||
while offset < payload.len() {
|
|
||||||
erase_sector(origin + offset);
|
|
||||||
offset += SECTOR_SIZE;
|
|
||||||
}
|
|
||||||
write(origin, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(soc_platform = "kasli", soc_platform = "kc705"))]
|
#[cfg(any(soc_platform = "kasli", soc_platform = "kc705"))]
|
||||||
pub unsafe fn reload () -> ! {
|
pub unsafe fn reload () -> ! {
|
||||||
csr::icap::iprog_write(1);
|
csr::icap::iprog_write(1);
|
||||||
|
|
|
@ -127,21 +127,6 @@ pub enum Packet {
|
||||||
SubkernelException { last: bool, length: u16, data: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
SubkernelException { last: bool, length: u16, data: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
||||||
SubkernelMessage { source: u8, destination: u8, id: u32, status: PayloadStatus, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
SubkernelMessage { source: u8, destination: u8, id: u32, status: PayloadStatus, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
||||||
SubkernelMessageAck { destination: u8 },
|
SubkernelMessageAck { destination: u8 },
|
||||||
|
|
||||||
CoreMgmtGetLogRequest { destination: u8, clear: bool },
|
|
||||||
CoreMgmtClearLogRequest { destination: u8 },
|
|
||||||
CoreMgmtSetLogLevelRequest { destination: u8, log_level: u8 },
|
|
||||||
CoreMgmtSetUartLogLevelRequest { destination: u8, log_level: u8 },
|
|
||||||
CoreMgmtConfigReadRequest { destination: u8, length: u16, key: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
|
||||||
CoreMgmtConfigReadContinue { destination: u8 },
|
|
||||||
CoreMgmtConfigWriteRequest { destination: u8, last: bool, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
|
||||||
CoreMgmtConfigRemoveRequest { destination: u8, length: u16, key: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
|
||||||
CoreMgmtConfigEraseRequest { destination: u8 },
|
|
||||||
CoreMgmtRebootRequest { destination: u8 },
|
|
||||||
CoreMgmtAllocatorDebugRequest { destination: u8 },
|
|
||||||
CoreMgmtGetLogReply { last: bool, length: u16, data: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
|
||||||
CoreMgmtConfigReadReply { last: bool, length: u16, value: [u8; SAT_PAYLOAD_MAX_SIZE] },
|
|
||||||
CoreMgmtReply { succeeded: bool },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Packet {
|
impl Packet {
|
||||||
|
@ -416,94 +401,6 @@ impl Packet {
|
||||||
destination: reader.read_u8()?
|
destination: reader.read_u8()?
|
||||||
},
|
},
|
||||||
|
|
||||||
0xd0 => Packet::CoreMgmtGetLogRequest {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
clear: reader.read_bool()?,
|
|
||||||
},
|
|
||||||
0xd1 => Packet::CoreMgmtClearLogRequest {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
},
|
|
||||||
0xd2 => Packet::CoreMgmtSetLogLevelRequest {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
log_level: reader.read_u8()?,
|
|
||||||
},
|
|
||||||
0xd3 => Packet::CoreMgmtSetUartLogLevelRequest {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
log_level: reader.read_u8()?,
|
|
||||||
},
|
|
||||||
0xd4 => {
|
|
||||||
let destination = reader.read_u8()?;
|
|
||||||
let length = reader.read_u16()?;
|
|
||||||
let mut key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
|
|
||||||
reader.read_exact(&mut key[0..length as usize])?;
|
|
||||||
Packet::CoreMgmtConfigReadRequest {
|
|
||||||
destination: destination,
|
|
||||||
length: length,
|
|
||||||
key: key,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0xd5 => Packet::CoreMgmtConfigReadContinue {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
},
|
|
||||||
0xd6 => {
|
|
||||||
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::CoreMgmtConfigWriteRequest {
|
|
||||||
destination: destination,
|
|
||||||
last: last,
|
|
||||||
length: length,
|
|
||||||
data: data,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0xd7 => {
|
|
||||||
let destination = reader.read_u8()?;
|
|
||||||
let length = reader.read_u16()?;
|
|
||||||
let mut key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
|
|
||||||
reader.read_exact(&mut key[0..length as usize])?;
|
|
||||||
Packet::CoreMgmtConfigRemoveRequest {
|
|
||||||
destination: destination,
|
|
||||||
length: length,
|
|
||||||
key: key,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0xd8 => Packet::CoreMgmtConfigEraseRequest {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
},
|
|
||||||
0xd9 => Packet::CoreMgmtRebootRequest {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
},
|
|
||||||
0xda => Packet::CoreMgmtAllocatorDebugRequest {
|
|
||||||
destination: reader.read_u8()?,
|
|
||||||
},
|
|
||||||
0xdb => {
|
|
||||||
let last = reader.read_bool()?;
|
|
||||||
let length = reader.read_u16()?;
|
|
||||||
let mut data: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE];
|
|
||||||
reader.read_exact(&mut data[0..length as usize])?;
|
|
||||||
Packet::CoreMgmtGetLogReply {
|
|
||||||
last: last,
|
|
||||||
length: length,
|
|
||||||
data: data,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0xdc => {
|
|
||||||
let last = reader.read_bool()?;
|
|
||||||
let length = reader.read_u16()?;
|
|
||||||
let mut value: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE];
|
|
||||||
reader.read_exact(&mut value[0..length as usize])?;
|
|
||||||
Packet::CoreMgmtConfigReadReply {
|
|
||||||
last: last,
|
|
||||||
length: length,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0xdd => Packet::CoreMgmtReply {
|
|
||||||
succeeded: reader.read_bool()?,
|
|
||||||
},
|
|
||||||
|
|
||||||
ty => return Err(Error::UnknownPacket(ty))
|
ty => return Err(Error::UnknownPacket(ty))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -789,90 +686,6 @@ impl Packet {
|
||||||
writer.write_u8(0xcc)?;
|
writer.write_u8(0xcc)?;
|
||||||
writer.write_u8(destination)?;
|
writer.write_u8(destination)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Packet::CoreMgmtGetLogRequest { destination, clear } => {
|
|
||||||
writer.write_u8(0xd0)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
writer.write_bool(clear)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtClearLogRequest { destination } => {
|
|
||||||
writer.write_u8(0xd1)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtSetLogLevelRequest { destination, log_level } => {
|
|
||||||
writer.write_u8(0xd2)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
writer.write_u8(log_level)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtSetUartLogLevelRequest { destination, log_level } => {
|
|
||||||
writer.write_u8(0xd3)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
writer.write_u8(log_level)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtConfigReadRequest {
|
|
||||||
destination,
|
|
||||||
length,
|
|
||||||
key,
|
|
||||||
} => {
|
|
||||||
writer.write_u8(0xd4)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
writer.write_u16(length)?;
|
|
||||||
writer.write_all(&key[0..length as usize])?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtConfigReadContinue { destination } => {
|
|
||||||
writer.write_u8(0xd5)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtConfigWriteRequest {
|
|
||||||
destination,
|
|
||||||
last,
|
|
||||||
length,
|
|
||||||
data,
|
|
||||||
} => {
|
|
||||||
writer.write_u8(0xd6)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
writer.write_bool(last)?;
|
|
||||||
writer.write_u16(length)?;
|
|
||||||
writer.write_all(&data[0..length as usize])?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtConfigRemoveRequest {
|
|
||||||
destination,
|
|
||||||
length,
|
|
||||||
key,
|
|
||||||
} => {
|
|
||||||
writer.write_u8(0xd7)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
writer.write_u16(length)?;
|
|
||||||
writer.write_all(&key[0..length as usize])?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtConfigEraseRequest { destination } => {
|
|
||||||
writer.write_u8(0xd8)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtRebootRequest { destination } => {
|
|
||||||
writer.write_u8(0xd9)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtAllocatorDebugRequest { destination } => {
|
|
||||||
writer.write_u8(0xda)?;
|
|
||||||
writer.write_u8(destination)?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtGetLogReply { last, length, data } => {
|
|
||||||
writer.write_u8(0xdb)?;
|
|
||||||
writer.write_bool(last)?;
|
|
||||||
writer.write_u16(length)?;
|
|
||||||
writer.write_all(&data[0..length as usize])?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtConfigReadReply { last, length, value } => {
|
|
||||||
writer.write_u8(0xdc)?;
|
|
||||||
writer.write_bool(last)?;
|
|
||||||
writer.write_u16(length)?;
|
|
||||||
writer.write_all(&value[0..length as usize])?;
|
|
||||||
},
|
|
||||||
Packet::CoreMgmtReply { succeeded } => {
|
|
||||||
writer.write_u8(0xdd)?;
|
|
||||||
writer.write_bool(succeeded)?;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,7 @@ pub enum Error<T> {
|
||||||
#[fail(display = "invalid UTF-8: {}", _0)]
|
#[fail(display = "invalid UTF-8: {}", _0)]
|
||||||
Utf8(Utf8Error),
|
Utf8(Utf8Error),
|
||||||
#[fail(display = "{}", _0)]
|
#[fail(display = "{}", _0)]
|
||||||
Io(#[cause] IoError<T>),
|
Io(#[cause] IoError<T>)
|
||||||
#[fail(display = "drtio error")]
|
|
||||||
DrtioError,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<IoError<T>> for Error<T> {
|
impl<T> From<IoError<T>> for Error<T> {
|
||||||
|
@ -67,8 +65,6 @@ pub enum Request {
|
||||||
|
|
||||||
Reboot,
|
Reboot,
|
||||||
|
|
||||||
Flash { image: Vec<u8> },
|
|
||||||
|
|
||||||
DebugAllocator,
|
DebugAllocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +123,6 @@ impl Request {
|
||||||
|
|
||||||
8 => Request::DebugAllocator,
|
8 => Request::DebugAllocator,
|
||||||
|
|
||||||
9 => Request::Flash {
|
|
||||||
image: reader.read_bytes()?,
|
|
||||||
},
|
|
||||||
|
|
||||||
ty => return Err(Error::UnknownPacket(ty))
|
ty => return Err(Error::UnknownPacket(ty))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ build_misoc = { path = "../libbuild_misoc" }
|
||||||
failure = { version = "0.1", default-features = false }
|
failure = { version = "0.1", default-features = false }
|
||||||
failure_derive = { version = "0.1", default-features = false }
|
failure_derive = { version = "0.1", default-features = false }
|
||||||
byteorder = { version = "1.0", default-features = false }
|
byteorder = { version = "1.0", default-features = false }
|
||||||
crc = { version = "1.7", default-features = false }
|
|
||||||
cslice = { version = "0.3" }
|
cslice = { version = "0.3" }
|
||||||
log = { version = "=0.4.14", default-features = false }
|
log = { version = "=0.4.14", default-features = false }
|
||||||
managed = { version = "^0.7.1", default-features = false, features = ["alloc", "map"] }
|
managed = { version = "^0.7.1", default-features = false, features = ["alloc", "map"] }
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![feature(lang_items, panic_info_message, const_btree_new, iter_advance_by, never_type)]
|
#![feature(lang_items, panic_info_message, const_btree_new, iter_advance_by, never_type)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate crc;
|
|
||||||
extern crate dyld;
|
extern crate dyld;
|
||||||
extern crate eh;
|
extern crate eh;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -207,13 +206,7 @@ fn startup() {
|
||||||
|
|
||||||
rtio_mgt::startup(&io, &aux_mutex, &drtio_routing_table, &up_destinations, &ddma_mutex, &subkernel_mutex);
|
rtio_mgt::startup(&io, &aux_mutex, &drtio_routing_table, &up_destinations, &ddma_mutex, &subkernel_mutex);
|
||||||
|
|
||||||
{
|
io.spawn(4096, mgmt::thread);
|
||||||
let aux_mutex = aux_mutex.clone();
|
|
||||||
let ddma_mutex = ddma_mutex.clone();
|
|
||||||
let subkernel_mutex = subkernel_mutex.clone();
|
|
||||||
let drtio_routing_table = drtio_routing_table.clone();
|
|
||||||
io.spawn(4096, move |io| { mgmt::thread(io, &aux_mutex, &ddma_mutex, &subkernel_mutex, &drtio_routing_table) });
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
let aux_mutex = aux_mutex.clone();
|
let aux_mutex = aux_mutex.clone();
|
||||||
let drtio_routing_table = drtio_routing_table.clone();
|
let drtio_routing_table = drtio_routing_table.clone();
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use core::cell::RefCell;
|
use log::{self, LevelFilter};
|
||||||
|
|
||||||
use board_artiq::drtio_routing;
|
use io::{Write, ProtoWrite, Error as IoError};
|
||||||
use io::{ProtoRead, Write, Error as IoError};
|
use board_misoc::{config, spiflash};
|
||||||
|
use logger_artiq::BufferLogger;
|
||||||
use mgmt_proto::*;
|
use mgmt_proto::*;
|
||||||
use sched::{Io, Mutex, TcpListener, TcpStream, Error as SchedError};
|
use sched::{Io, TcpListener, TcpStream, Error as SchedError};
|
||||||
use urc::Urc;
|
|
||||||
|
|
||||||
impl From<SchedError> for Error<SchedError> {
|
impl From<SchedError> for Error<SchedError> {
|
||||||
fn from(value: SchedError) -> Error<SchedError> {
|
fn from(value: SchedError) -> Error<SchedError> {
|
||||||
|
@ -12,593 +12,121 @@ impl From<SchedError> for Error<SchedError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod local_coremgmt {
|
fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
||||||
use alloc::{string::String, vec::Vec};
|
|
||||||
use crc::crc32;
|
|
||||||
use log::LevelFilter;
|
|
||||||
|
|
||||||
use board_misoc::{config, mem, spiflash};
|
|
||||||
use io::{Cursor, Write, ProtoWrite, ProtoRead, Error as IoError};
|
|
||||||
use logger_artiq::BufferLogger;
|
|
||||||
use mgmt_proto::{Error, Reply};
|
|
||||||
use sched::{Io, TcpStream, Error as SchedError};
|
|
||||||
|
|
||||||
|
|
||||||
pub fn get_log(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
BufferLogger::with(|logger| {
|
|
||||||
let mut buffer = io.until_ok(|| logger.buffer())?;
|
|
||||||
Reply::LogContent(buffer.extract()).write_to(stream)
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_log(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
BufferLogger::with(|logger| -> Result<(), IoError<SchedError>> {
|
|
||||||
let mut buffer = io.until_ok(|| logger.buffer())?;
|
|
||||||
Ok(buffer.clear())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pull_log(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
BufferLogger::with(|logger| -> Result<(), IoError<SchedError>> {
|
|
||||||
loop {
|
|
||||||
// Do this *before* acquiring the buffer, since that sets the log level
|
|
||||||
// to OFF.
|
|
||||||
let log_level = log::max_level();
|
|
||||||
|
|
||||||
let mut buffer = io.until_ok(|| logger.buffer())?;
|
|
||||||
if buffer.is_empty() { continue }
|
|
||||||
|
|
||||||
stream.write_string(buffer.extract())?;
|
|
||||||
|
|
||||||
if log_level == LevelFilter::Trace {
|
|
||||||
// Hold exclusive access over the logger until we get positive
|
|
||||||
// acknowledgement; otherwise we get an infinite loop of network
|
|
||||||
// trace messages being transmitted and causing more network
|
|
||||||
// trace messages to be emitted.
|
|
||||||
//
|
|
||||||
// Any messages unrelated to this management socket that arrive
|
|
||||||
// while it is flushed are lost, but such is life.
|
|
||||||
stream.flush()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the log *after* flushing the network buffers, or we're just
|
|
||||||
// going to resend all the trace messages on the next iteration.
|
|
||||||
buffer.clear();
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_log_filter(_io: &Io, stream: &mut TcpStream, level: LevelFilter) -> Result<(), Error<SchedError>> {
|
|
||||||
info!("changing log level to {}", level);
|
|
||||||
log::set_max_level(level);
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_uart_log_filter(_io: &Io, stream: &mut TcpStream, level: LevelFilter) -> Result<(), Error<SchedError>> {
|
|
||||||
info!("changing UART log level to {}", level);
|
|
||||||
BufferLogger::with(|logger|
|
|
||||||
logger.set_uart_log_level(level));
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_read(_io: &Io, stream: &mut TcpStream, key: &String) -> Result<(), Error<SchedError>>{
|
|
||||||
config::read(key, |result| {
|
|
||||||
match result {
|
|
||||||
Ok(value) => Reply::ConfigData(&value).write_to(stream),
|
|
||||||
Err(_) => Reply::Error.write_to(stream)
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_write(_io: &Io, stream: &mut TcpStream, key: &String, value: &Vec<u8>) -> Result<(), Error<SchedError>> {
|
|
||||||
match config::write(key, value) {
|
|
||||||
Ok(_) => Reply::Success.write_to(stream),
|
|
||||||
Err(_) => Reply::Error.write_to(stream)
|
|
||||||
}?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_remove(_io: &Io, stream: &mut TcpStream, key: &String) -> Result<(), Error<SchedError>> {
|
|
||||||
match config::remove(key) {
|
|
||||||
Ok(()) => Reply::Success.write_to(stream),
|
|
||||||
Err(_) => Reply::Error.write_to(stream)
|
|
||||||
}?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_erase(_io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
match config::erase() {
|
|
||||||
Ok(()) => Reply::Success.write_to(stream),
|
|
||||||
Err(_) => Reply::Error.write_to(stream)
|
|
||||||
}?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reboot(_io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
Reply::RebootImminent.write_to(stream)?;
|
|
||||||
stream.close()?;
|
|
||||||
stream.flush()?;
|
|
||||||
|
|
||||||
warn!("restarting");
|
|
||||||
unsafe { spiflash::reload(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn debug_allocator(_io: &Io, _stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
unsafe { println!("{}", ::ALLOC) }
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flash(_io: &Io, stream: &mut TcpStream, image: &Vec<u8>) -> Result<(), Error<SchedError>> {
|
|
||||||
let mut reader = Cursor::new(&image[..]);
|
|
||||||
let expected_crc = reader.read_u32().unwrap();
|
|
||||||
|
|
||||||
let image = &image[4..];
|
|
||||||
let actual_crc = crc32::checksum_ieee(image);
|
|
||||||
|
|
||||||
if actual_crc == expected_crc {
|
|
||||||
info!("Checksum matched");
|
|
||||||
let header_size = reader.read_u32().unwrap() as usize;
|
|
||||||
let header_offset = reader.position();
|
|
||||||
let bin_offset = header_offset + header_size;
|
|
||||||
|
|
||||||
let header = &image[header_offset..bin_offset];
|
|
||||||
let binaries = &image[bin_offset..];
|
|
||||||
|
|
||||||
info!("found header of size {}", header.len());
|
|
||||||
|
|
||||||
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, &binaries[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)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
|
||||||
mod remote_coremgmt {
|
|
||||||
use alloc::{string::String, vec::Vec};
|
|
||||||
use log::LevelFilter;
|
|
||||||
|
|
||||||
use board_artiq::{drtioaux::Packet, drtio_routing};
|
|
||||||
use io::{Cursor, ProtoWrite};
|
|
||||||
use mgmt_proto::{Error, Reply};
|
|
||||||
use rtio_mgt::drtio;
|
|
||||||
use sched::{Io, Mutex, TcpStream, Error as SchedError};
|
|
||||||
use proto_artiq::drtioaux_proto::MASTER_PAYLOAD_MAX_SIZE;
|
|
||||||
|
|
||||||
|
|
||||||
impl From<drtio::Error> for Error<SchedError> {
|
|
||||||
fn from(_value: drtio::Error) -> Error<SchedError> {
|
|
||||||
Error::DrtioError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_log(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
loop {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtGetLogRequest { destination, clear: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtGetLogReply { last, length, data }) => {
|
|
||||||
buffer.push_str(
|
|
||||||
core::str::from_utf8(&data[..length as usize]).map_err(|_| Error::DrtioError)?);
|
|
||||||
if last {
|
|
||||||
Reply::LogContent(&buffer).write_to(stream)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
return Err(drtio::Error::UnexpectedReply.into());
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
return Err(e.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_log(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtClearLogRequest { destination }
|
|
||||||
);
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(drtio::Error::UnexpectedReply.into())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pull_log(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
loop {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtGetLogRequest { destination, clear: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtGetLogReply { last: _, length, data }) => {
|
|
||||||
stream.write_bytes(&data[..length as usize])?;
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
return Err(drtio::Error::UnexpectedReply.into());
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
return Err(e.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_log_filter(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream, level: LevelFilter) -> Result<(), Error<SchedError>> {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtSetLogLevelRequest { destination, log_level: level as u8 }
|
|
||||||
);
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(drtio::Error::UnexpectedReply.into())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_uart_log_filter(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream, level: LevelFilter) -> Result<(), Error<SchedError>> {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtSetUartLogLevelRequest { destination, log_level: level as u8 }
|
|
||||||
);
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(drtio::Error::UnexpectedReply.into())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_read(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream, key: &String) -> Result<(), Error<SchedError>> {
|
|
||||||
let mut config_key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
|
|
||||||
let len = key.len();
|
|
||||||
config_key[..len].clone_from_slice(key.as_bytes());
|
|
||||||
|
|
||||||
let mut reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtConfigReadRequest {
|
|
||||||
destination: destination,
|
|
||||||
length: len as u16,
|
|
||||||
key: config_key,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut buffer = Vec::<u8>::new();
|
|
||||||
loop {
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtConfigReadReply { length, last, value }) => {
|
|
||||||
buffer.extend(&value[..length as usize]);
|
|
||||||
|
|
||||||
if last {
|
|
||||||
Reply::ConfigData(&buffer).write_to(stream)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtConfigReadContinue {
|
|
||||||
destination: destination,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
return Err(drtio::Error::UnexpectedReply.into());
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
return Err(e.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_write(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream, key: &String, value: &Vec<u8>) -> Result<(), Error<SchedError>> {
|
|
||||||
let mut message = Cursor::new(Vec::with_capacity(key.len() + value.len() + 4 * 2));
|
|
||||||
message.write_string(key).unwrap();
|
|
||||||
message.write_bytes(value).unwrap();
|
|
||||||
|
|
||||||
match drtio::partition_data(message.get_ref(), |slice, status, len: usize| {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtConfigWriteRequest {
|
|
||||||
destination: destination, length: len as u16, last: status.is_last(), data: *slice});
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => Ok(()),
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Err(drtio::Error::UnexpectedReply)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Ok(()) => {
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(e.into())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_remove(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream, key: &String) -> Result<(), Error<SchedError>> {
|
|
||||||
let mut config_key: [u8; MASTER_PAYLOAD_MAX_SIZE] = [0; MASTER_PAYLOAD_MAX_SIZE];
|
|
||||||
let len = key.len();
|
|
||||||
config_key[..len].clone_from_slice(key.as_bytes());
|
|
||||||
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtConfigRemoveRequest {
|
|
||||||
destination: destination,
|
|
||||||
length: key.len() as u16,
|
|
||||||
key: config_key,
|
|
||||||
});
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(drtio::Error::UnexpectedReply.into())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_erase(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtConfigEraseRequest {
|
|
||||||
destination: destination,
|
|
||||||
});
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
|
||||||
Reply::Success.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(drtio::Error::UnexpectedReply.into())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reboot(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtRebootRequest {
|
|
||||||
destination: destination,
|
|
||||||
});
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
|
||||||
Reply::RebootImminent.write_to(stream)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(drtio::Error::UnexpectedReply.into())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Reply::Error.write_to(stream)?;
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn debug_allocator(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, _stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
let reply = drtio::aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
|
||||||
&Packet::CoreMgmtAllocatorDebugRequest {
|
|
||||||
destination: destination,
|
|
||||||
});
|
|
||||||
|
|
||||||
match reply {
|
|
||||||
Ok(Packet::CoreMgmtReply { succeeded: true }) => Ok(()),
|
|
||||||
Ok(packet) => {
|
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
|
||||||
Err(drtio::Error::UnexpectedReply.into())
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("aux packet error ({})", e);
|
|
||||||
Err(e.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flash(io: &Io, aux_mutex: &Mutex,
|
|
||||||
ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
|
||||||
routing_table: &drtio_routing::RoutingTable, linkno: u8,
|
|
||||||
destination: u8, stream: &mut TcpStream, image: &Vec<u8>) -> Result<(), Error<SchedError>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
|
||||||
macro_rules! process {
|
|
||||||
($io:ident, $aux_mutex:ident, $ddma_mutex:ident, $subkernel_mutex:ident, $routing_table:ident, $tcp_stream:ident, $destination: ident, $func:ident $(, $param:expr)*) => {{
|
|
||||||
let hop = $routing_table.0[$destination as usize][0];
|
|
||||||
if hop == 0 {
|
|
||||||
local_coremgmt::$func($io, $tcp_stream, $($param, )*)
|
|
||||||
} else {
|
|
||||||
let linkno = hop - 1;
|
|
||||||
remote_coremgmt::$func($io, $aux_mutex, $ddma_mutex, $subkernel_mutex, $routing_table, linkno, $destination, $tcp_stream, $($param, )*)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(has_drtio))]
|
|
||||||
macro_rules! process {
|
|
||||||
($io:ident, $aux_mutex:ident, $ddma_mutex:ident, $subkernel_mutex:ident, $routing_table:ident, $tcp_stream:ident, $_destination: ident, $func:ident $(, $param:expr)*) => {{
|
|
||||||
local_coremgmt::$func($io, $tcp_stream, $($param, )*)
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn worker(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _subkernel_mutex: &Mutex,
|
|
||||||
_routing_table: &drtio_routing::RoutingTable, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
|
||||||
read_magic(stream)?;
|
read_magic(stream)?;
|
||||||
let _destination = stream.read_u8()?;
|
|
||||||
Write::write_all(stream, "e".as_bytes())?;
|
Write::write_all(stream, "e".as_bytes())?;
|
||||||
info!("new connection from {}", stream.remote_endpoint());
|
info!("new connection from {}", stream.remote_endpoint());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match Request::read_from(stream)? {
|
match Request::read_from(stream)? {
|
||||||
Request::GetLog => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, get_log),
|
Request::GetLog => {
|
||||||
Request::ClearLog => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, clear_log),
|
BufferLogger::with(|logger| {
|
||||||
Request::PullLog => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, pull_log),
|
let mut buffer = io.until_ok(|| logger.buffer())?;
|
||||||
Request::SetLogFilter(level) => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, set_log_filter, level),
|
Reply::LogContent(buffer.extract()).write_to(stream)
|
||||||
Request::SetUartLogFilter(level) => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, set_uart_log_filter, level),
|
})?;
|
||||||
Request::ConfigRead { ref key } => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, config_read, key),
|
}
|
||||||
Request::ConfigWrite { ref key, ref value } => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, config_write, key, value),
|
Request::ClearLog => {
|
||||||
Request::ConfigRemove { ref key } => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, config_remove, key),
|
BufferLogger::with(|logger| -> Result<(), Error<SchedError>> {
|
||||||
Request::ConfigErase => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, config_erase),
|
let mut buffer = io.until_ok(|| logger.buffer())?;
|
||||||
Request::Reboot => process!(io, _aux_mutex, _ddma_mutex, _subkernel_mutex, _routing_table, stream, _destination, reboot),
|
Ok(buffer.clear())
|
||||||
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),
|
|
||||||
}?;
|
Reply::Success.write_to(stream)?;
|
||||||
|
}
|
||||||
|
Request::PullLog => {
|
||||||
|
BufferLogger::with(|logger| -> Result<(), Error<SchedError>> {
|
||||||
|
loop {
|
||||||
|
// Do this *before* acquiring the buffer, since that sets the log level
|
||||||
|
// to OFF.
|
||||||
|
let log_level = log::max_level();
|
||||||
|
|
||||||
|
let mut buffer = io.until_ok(|| logger.buffer())?;
|
||||||
|
if buffer.is_empty() { continue }
|
||||||
|
|
||||||
|
stream.write_string(buffer.extract())?;
|
||||||
|
|
||||||
|
if log_level == LevelFilter::Trace {
|
||||||
|
// Hold exclusive access over the logger until we get positive
|
||||||
|
// acknowledgement; otherwise we get an infinite loop of network
|
||||||
|
// trace messages being transmitted and causing more network
|
||||||
|
// trace messages to be emitted.
|
||||||
|
//
|
||||||
|
// Any messages unrelated to this management socket that arrive
|
||||||
|
// while it is flushed are lost, but such is life.
|
||||||
|
stream.flush()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the log *after* flushing the network buffers, or we're just
|
||||||
|
// going to resend all the trace messages on the next iteration.
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
Request::SetLogFilter(level) => {
|
||||||
|
info!("changing log level to {}", level);
|
||||||
|
log::set_max_level(level);
|
||||||
|
Reply::Success.write_to(stream)?;
|
||||||
|
}
|
||||||
|
Request::SetUartLogFilter(level) => {
|
||||||
|
info!("changing UART log level to {}", level);
|
||||||
|
BufferLogger::with(|logger|
|
||||||
|
logger.set_uart_log_level(level));
|
||||||
|
Reply::Success.write_to(stream)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Request::ConfigRead { ref key } => {
|
||||||
|
config::read(key, |result| {
|
||||||
|
match result {
|
||||||
|
Ok(value) => Reply::ConfigData(&value).write_to(stream),
|
||||||
|
Err(_) => Reply::Error.write_to(stream)
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
Request::ConfigWrite { ref key, ref value } => {
|
||||||
|
match config::write(key, value) {
|
||||||
|
Ok(_) => Reply::Success.write_to(stream),
|
||||||
|
Err(_) => Reply::Error.write_to(stream)
|
||||||
|
}?;
|
||||||
|
}
|
||||||
|
Request::ConfigRemove { ref key } => {
|
||||||
|
match config::remove(key) {
|
||||||
|
Ok(()) => Reply::Success.write_to(stream),
|
||||||
|
Err(_) => Reply::Error.write_to(stream)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
}
|
||||||
|
Request::ConfigErase => {
|
||||||
|
match config::erase() {
|
||||||
|
Ok(()) => Reply::Success.write_to(stream),
|
||||||
|
Err(_) => Reply::Error.write_to(stream)
|
||||||
|
}?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Request::Reboot => {
|
||||||
|
Reply::RebootImminent.write_to(stream)?;
|
||||||
|
stream.close()?;
|
||||||
|
stream.flush()?;
|
||||||
|
|
||||||
|
warn!("restarting");
|
||||||
|
unsafe { spiflash::reload(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Request::DebugAllocator =>
|
||||||
|
unsafe { println!("{}", ::ALLOC) },
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thread(io: Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, subkernel_mutex: &Mutex, routing_table: &Urc<RefCell<drtio_routing::RoutingTable>>) {
|
pub fn thread(io: Io) {
|
||||||
let listener = TcpListener::new(&io, 8192);
|
let listener = TcpListener::new(&io, 8192);
|
||||||
listener.listen(1380).expect("mgmt: cannot listen");
|
listener.listen(1380).expect("mgmt: cannot listen");
|
||||||
info!("management interface active");
|
info!("management interface active");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let aux_mutex = aux_mutex.clone();
|
|
||||||
let ddma_mutex = ddma_mutex.clone();
|
|
||||||
let subkernel_mutex = subkernel_mutex.clone();
|
|
||||||
let routing_table = routing_table.clone();
|
|
||||||
let stream = listener.accept().expect("mgmt: cannot accept").into_handle();
|
let stream = listener.accept().expect("mgmt: cannot accept").into_handle();
|
||||||
io.spawn(16384, move |io| {
|
io.spawn(4096, move |io| {
|
||||||
let routing_table = routing_table.borrow();
|
|
||||||
let mut stream = TcpStream::from_handle(&io, stream);
|
let mut stream = TcpStream::from_handle(&io, stream);
|
||||||
match worker(&io, &aux_mutex, &ddma_mutex, &subkernel_mutex, &routing_table, &mut stream) {
|
match worker(&io, &mut stream) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(Error::Io(IoError::UnexpectedEnd)) => (),
|
Err(Error::Io(IoError::UnexpectedEnd)) => (),
|
||||||
Err(err) => error!("aborted: {}", err)
|
Err(err) => error!("aborted: {}", err)
|
||||||
|
|
|
@ -469,7 +469,7 @@ pub mod drtio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn partition_data<F>(data: &[u8], send_f: F) -> Result<(), Error>
|
fn partition_data<F>(data: &[u8], send_f: F) -> Result<(), Error>
|
||||||
where F: Fn(&[u8; MASTER_PAYLOAD_MAX_SIZE], PayloadStatus, usize) -> Result<(), Error> {
|
where F: Fn(&[u8; MASTER_PAYLOAD_MAX_SIZE], PayloadStatus, usize) -> Result<(), Error> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < data.len() {
|
while i < data.len() {
|
||||||
|
|
|
@ -21,7 +21,6 @@ use board_artiq::si5324;
|
||||||
use board_artiq::si549;
|
use board_artiq::si549;
|
||||||
#[cfg(soc_platform = "kasli")]
|
#[cfg(soc_platform = "kasli")]
|
||||||
use board_misoc::irq;
|
use board_misoc::irq;
|
||||||
use board_misoc::spiflash;
|
|
||||||
use board_artiq::{spi, drtioaux, drtio_routing};
|
use board_artiq::{spi, drtioaux, drtio_routing};
|
||||||
#[cfg(soc_platform = "efc")]
|
#[cfg(soc_platform = "efc")]
|
||||||
use board_artiq::ad9117;
|
use board_artiq::ad9117;
|
||||||
|
@ -31,7 +30,6 @@ use board_artiq::drtio_eem;
|
||||||
use riscv::register::{mcause, mepc, mtval};
|
use riscv::register::{mcause, mepc, mtval};
|
||||||
use dma::Manager as DmaManager;
|
use dma::Manager as DmaManager;
|
||||||
use kernel::Manager as KernelManager;
|
use kernel::Manager as KernelManager;
|
||||||
use mgmt::Manager as CoreManager;
|
|
||||||
use analyzer::Analyzer;
|
use analyzer::Analyzer;
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
|
@ -43,7 +41,6 @@ mod dma;
|
||||||
mod analyzer;
|
mod analyzer;
|
||||||
mod kernel;
|
mod kernel;
|
||||||
mod cache;
|
mod cache;
|
||||||
mod mgmt;
|
|
||||||
|
|
||||||
fn drtiosat_reset(reset: bool) {
|
fn drtiosat_reset(reset: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -132,7 +129,7 @@ macro_rules! forward {
|
||||||
($router:expr, $routing_table:expr, $destination:expr, $rank:expr, $self_destination:expr, $repeaters:expr, $packet:expr) => {}
|
($router:expr, $routing_table:expr, $destination:expr, $rank:expr, $self_destination:expr, $repeaters:expr, $packet:expr) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmgr: &mut KernelManager, coremgr: &mut CoreManager,
|
fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmgr: &mut KernelManager,
|
||||||
_repeaters: &mut [repeater::Repeater], _routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8,
|
_repeaters: &mut [repeater::Repeater], _routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8,
|
||||||
router: &mut routing::Router, self_destination: &mut u8, packet: drtioaux::Packet
|
router: &mut routing::Router, self_destination: &mut u8, packet: drtioaux::Packet
|
||||||
) -> Result<(), drtioaux::Error<!>> {
|
) -> Result<(), drtioaux::Error<!>> {
|
||||||
|
@ -492,94 +489,6 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
drtioaux::Packet::CoreMgmtGetLogRequest { destination: _destination, .. } |
|
|
||||||
drtioaux::Packet::CoreMgmtClearLogRequest { destination: _destination } |
|
|
||||||
drtioaux::Packet::CoreMgmtSetLogLevelRequest {destination: _destination, .. } => {
|
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
|
||||||
|
|
||||||
error!("RISC-V satellite devices do not support buffered logging");
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
|
||||||
}
|
|
||||||
drtioaux::Packet::CoreMgmtSetUartLogLevelRequest { destination: _destination, .. } => {
|
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
|
||||||
|
|
||||||
error!("RISC-V satellite devices has fixed UART log level fixed at TRACE");
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
|
||||||
}
|
|
||||||
drtioaux::Packet::CoreMgmtConfigReadRequest {
|
|
||||||
destination: _destination,
|
|
||||||
length,
|
|
||||||
key,
|
|
||||||
} => {
|
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
|
||||||
|
|
||||||
let mut value_slice = [0; SAT_PAYLOAD_MAX_SIZE];
|
|
||||||
|
|
||||||
let key_slice = &key[..length as usize];
|
|
||||||
if !key_slice.is_ascii() {
|
|
||||||
error!("invalid key");
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
|
||||||
} else {
|
|
||||||
let key = core::str::from_utf8(key_slice).unwrap();
|
|
||||||
if coremgr.fetch_config_value(key).is_ok() {
|
|
||||||
let meta = coremgr.get_config_value_slice(&mut value_slice);
|
|
||||||
drtioaux::send(
|
|
||||||
0,
|
|
||||||
&drtioaux::Packet::CoreMgmtConfigReadReply {
|
|
||||||
length: meta.len as u16,
|
|
||||||
last: meta.status.is_last(),
|
|
||||||
value: value_slice,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drtioaux::Packet::CoreMgmtConfigReadContinue {
|
|
||||||
destination: _destination,
|
|
||||||
} => {
|
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
|
||||||
|
|
||||||
let mut value_slice = [0; SAT_PAYLOAD_MAX_SIZE];
|
|
||||||
let meta = coremgr.get_config_value_slice(&mut value_slice);
|
|
||||||
drtioaux::send(
|
|
||||||
0,
|
|
||||||
&drtioaux::Packet::CoreMgmtConfigReadReply {
|
|
||||||
length: meta.len as u16,
|
|
||||||
last: meta.status.is_last(),
|
|
||||||
value: value_slice,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
drtioaux::Packet::CoreMgmtConfigWriteRequest { destination: _destination, length, last, data } => {
|
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
|
||||||
|
|
||||||
coremgr.add_data(&data, length as usize);
|
|
||||||
if last {
|
|
||||||
coremgr.write_config()
|
|
||||||
} else {
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drtioaux::Packet::CoreMgmtConfigRemoveRequest { destination: _destination, length, key } => {
|
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
|
||||||
|
|
||||||
let key = core::str::from_utf8(&key[..length as usize]).unwrap();
|
|
||||||
let succeeded = config::remove(key)
|
|
||||||
.map_err(|err| warn!("error on removing config: {:?}", err))
|
|
||||||
.is_ok();
|
|
||||||
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded })
|
|
||||||
}
|
|
||||||
drtioaux::Packet::CoreMgmtRebootRequest { destination: _destination } => {
|
|
||||||
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
|
||||||
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })?;
|
|
||||||
warn!("restarting");
|
|
||||||
unsafe { spiflash::reload(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
warn!("received unexpected aux packet");
|
warn!("received unexpected aux packet");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -588,13 +497,13 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_aux_packets(dma_manager: &mut DmaManager, analyzer: &mut Analyzer,
|
fn process_aux_packets(dma_manager: &mut DmaManager, analyzer: &mut Analyzer,
|
||||||
kernelmgr: &mut KernelManager, coremgr: &mut CoreManager, repeaters: &mut [repeater::Repeater],
|
kernelmgr: &mut KernelManager, repeaters: &mut [repeater::Repeater],
|
||||||
routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8, router: &mut routing::Router,
|
routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8, router: &mut routing::Router,
|
||||||
destination: &mut u8) {
|
destination: &mut u8) {
|
||||||
let result =
|
let result =
|
||||||
drtioaux::recv(0).and_then(|packet| {
|
drtioaux::recv(0).and_then(|packet| {
|
||||||
if let Some(packet) = packet.or_else(|| router.get_local_packet()) {
|
if let Some(packet) = packet.or_else(|| router.get_local_packet()) {
|
||||||
process_aux_packet(dma_manager, analyzer, kernelmgr, coremgr,
|
process_aux_packet(dma_manager, analyzer, kernelmgr,
|
||||||
repeaters, routing_table, rank, router, destination, packet)
|
repeaters, routing_table, rank, router, destination, packet)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -914,7 +823,6 @@ pub extern fn main() -> i32 {
|
||||||
let mut dma_manager = DmaManager::new();
|
let mut dma_manager = DmaManager::new();
|
||||||
let mut analyzer = Analyzer::new();
|
let mut analyzer = Analyzer::new();
|
||||||
let mut kernelmgr = KernelManager::new();
|
let mut kernelmgr = KernelManager::new();
|
||||||
let mut coremgr = CoreManager::new();
|
|
||||||
|
|
||||||
cricon_select(RtioMaster::Drtio);
|
cricon_select(RtioMaster::Drtio);
|
||||||
drtioaux::reset(0);
|
drtioaux::reset(0);
|
||||||
|
@ -924,7 +832,7 @@ pub extern fn main() -> i32 {
|
||||||
while drtiosat_link_rx_up() {
|
while drtiosat_link_rx_up() {
|
||||||
drtiosat_process_errors();
|
drtiosat_process_errors();
|
||||||
process_aux_packets(&mut dma_manager, &mut analyzer,
|
process_aux_packets(&mut dma_manager, &mut analyzer,
|
||||||
&mut kernelmgr, &mut coremgr, &mut repeaters, &mut routing_table,
|
&mut kernelmgr, &mut repeaters, &mut routing_table,
|
||||||
&mut rank, &mut router, &mut destination);
|
&mut rank, &mut router, &mut destination);
|
||||||
for rep in repeaters.iter_mut() {
|
for rep in repeaters.iter_mut() {
|
||||||
rep.service(&routing_table, rank, destination, &mut router);
|
rep.service(&routing_table, rank, destination, &mut router);
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
use routing::{Sliceable, SliceMeta};
|
|
||||||
use board_artiq::drtioaux;
|
|
||||||
use board_misoc::{clock, config, csr, spiflash};
|
|
||||||
use io::{Cursor, ProtoRead, ProtoWrite};
|
|
||||||
use proto_artiq::drtioaux_proto::SAT_PAYLOAD_MAX_SIZE;
|
|
||||||
|
|
||||||
|
|
||||||
pub struct Manager {
|
|
||||||
current_payload: Cursor<Vec<u8>>,
|
|
||||||
last_value: Sliceable,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Manager {
|
|
||||||
pub fn new() -> Manager {
|
|
||||||
Manager {
|
|
||||||
current_payload: Cursor::new(Vec::new()),
|
|
||||||
last_value: Sliceable::new(0, Vec::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fetch_config_value(&mut self, key: &str) -> Result<(), ()> {
|
|
||||||
config::read(key, |result| result.map(
|
|
||||||
|value| self.last_value = Sliceable::new(0, value.to_vec())
|
|
||||||
)).map_err(|_err| warn!("read error: no such key"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_config_value_slice(&mut self, data_slice: &mut [u8; SAT_PAYLOAD_MAX_SIZE]) -> SliceMeta {
|
|
||||||
self.last_value.get_slice_sat(data_slice)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_data(&mut self, data: &[u8], data_len: usize) {
|
|
||||||
self.current_payload.write_all(&data[..data_len]).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_data(&mut self) {
|
|
||||||
self.current_payload.get_mut().clear();
|
|
||||||
self.current_payload.set_position(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_config(&mut self) -> Result<(), drtioaux::Error<!>> {
|
|
||||||
let key = match self.current_payload.read_string() {
|
|
||||||
Ok(key) => key,
|
|
||||||
Err(err) => {
|
|
||||||
self.clear_data();
|
|
||||||
error!("error on reading key: {:?}", err);
|
|
||||||
return drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = self.current_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| {
|
|
||||||
error!("error on writing config: {:?}", err);
|
|
||||||
}).is_ok();
|
|
||||||
|
|
||||||
self.clear_data();
|
|
||||||
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,9 +25,6 @@ def get_argparser():
|
||||||
help="Simulation - does not connect to device")
|
help="Simulation - does not connect to device")
|
||||||
parser.add_argument("core_addr", metavar="CORE_ADDR",
|
parser.add_argument("core_addr", metavar="CORE_ADDR",
|
||||||
help="hostname or IP address of the core device")
|
help="hostname or IP address of the core device")
|
||||||
parser.add_argument("-s", "--satellite", default=0,
|
|
||||||
metavar="DRTIO_ID", type=int,
|
|
||||||
help="the logged DRTIO destination")
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +39,7 @@ async def get_logs_sim(host):
|
||||||
log_with_name("firmware.simulation", logging.INFO, "hello " + host)
|
log_with_name("firmware.simulation", logging.INFO, "hello " + host)
|
||||||
|
|
||||||
|
|
||||||
async def get_logs(host, drtio_dest):
|
async def get_logs(host):
|
||||||
try:
|
try:
|
||||||
reader, writer = await async_open_connection(
|
reader, writer = await async_open_connection(
|
||||||
host,
|
host,
|
||||||
|
@ -52,7 +49,6 @@ async def get_logs(host, drtio_dest):
|
||||||
max_fails=3,
|
max_fails=3,
|
||||||
)
|
)
|
||||||
writer.write(b"ARTIQ management\n")
|
writer.write(b"ARTIQ management\n")
|
||||||
writer.write(drtio_dest.to_bytes(1))
|
|
||||||
endian = await reader.readexactly(1)
|
endian = await reader.readexactly(1)
|
||||||
if endian == b"e":
|
if endian == b"e":
|
||||||
endian = "<"
|
endian = "<"
|
||||||
|
@ -100,7 +96,7 @@ def main():
|
||||||
signal_handler.setup()
|
signal_handler.setup()
|
||||||
try:
|
try:
|
||||||
get_logs_task = asyncio.ensure_future(
|
get_logs_task = asyncio.ensure_future(
|
||||||
get_logs_sim(args.core_addr) if args.simulation else get_logs(args.core_addr, args.satellite),
|
get_logs_sim(args.core_addr) if args.simulation else get_logs(args.core_addr),
|
||||||
loop=loop)
|
loop=loop)
|
||||||
try:
|
try:
|
||||||
server = Server({"corelog": PingTarget()}, None, True)
|
server = Server({"corelog": PingTarget()}, None, True)
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
|
||||||
import struct
|
import struct
|
||||||
import tempfile
|
|
||||||
import atexit
|
|
||||||
|
|
||||||
from sipyco import common_args
|
from sipyco import common_args
|
||||||
|
|
||||||
|
@ -12,8 +9,6 @@ from artiq import __version__ as artiq_version
|
||||||
from artiq.master.databases import DeviceDB
|
from artiq.master.databases import DeviceDB
|
||||||
from artiq.coredevice.comm_kernel import CommKernel
|
from artiq.coredevice.comm_kernel import CommKernel
|
||||||
from artiq.coredevice.comm_mgmt import CommMgmt
|
from artiq.coredevice.comm_mgmt import CommMgmt
|
||||||
from artiq.frontend.bit2bin import bit2bin
|
|
||||||
from misoc.tools.mkmscimg import insert_crc
|
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
def get_argparser():
|
||||||
|
@ -90,13 +85,6 @@ def get_argparser():
|
||||||
t_boot = tools.add_parser("reboot",
|
t_boot = tools.add_parser("reboot",
|
||||||
help="reboot the running system")
|
help="reboot the running system")
|
||||||
|
|
||||||
# flashing
|
|
||||||
t_flash = tools.add_parser("flash",
|
|
||||||
help="flash the running system")
|
|
||||||
|
|
||||||
p_directory = t_flash.add_argument("directory", metavar="DIRECTORY", type=str,
|
|
||||||
help="directory that contains the binaries")
|
|
||||||
|
|
||||||
# misc debug
|
# misc debug
|
||||||
t_debug = tools.add_parser("debug",
|
t_debug = tools.add_parser("debug",
|
||||||
help="specialized debug functions")
|
help="specialized debug functions")
|
||||||
|
@ -107,11 +95,6 @@ def get_argparser():
|
||||||
p_allocator = subparsers.add_parser("allocator",
|
p_allocator = subparsers.add_parser("allocator",
|
||||||
help="show heap layout")
|
help="show heap layout")
|
||||||
|
|
||||||
# manage target
|
|
||||||
p_drtio_dest = parser.add_argument("-s", "--satellite", default=0,
|
|
||||||
metavar="DRTIO ID", type=int,
|
|
||||||
help="specify DRTIO destination that receives this command")
|
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,7 +107,7 @@ def main():
|
||||||
core_addr = ddb.get("core", resolve_alias=True)["arguments"]["host"]
|
core_addr = ddb.get("core", resolve_alias=True)["arguments"]["host"]
|
||||||
else:
|
else:
|
||||||
core_addr = args.device
|
core_addr = args.device
|
||||||
mgmt = CommMgmt(core_addr, drtio_dest=args.satellite)
|
mgmt = CommMgmt(core_addr)
|
||||||
|
|
||||||
if args.tool == "log":
|
if args.tool == "log":
|
||||||
if args.action == "set_level":
|
if args.action == "set_level":
|
||||||
|
@ -154,37 +137,6 @@ def main():
|
||||||
mgmt.config_remove(key)
|
mgmt.config_remove(key)
|
||||||
if args.action == "erase":
|
if args.action == "erase":
|
||||||
mgmt.config_erase()
|
mgmt.config_erase()
|
||||||
|
|
||||||
if args.tool == "flash":
|
|
||||||
def convert_gateware(bit_filename):
|
|
||||||
bin_handle, bin_filename = tempfile.mkstemp(
|
|
||||||
prefix="artiq_", suffix="_" + os.path.basename(bit_filename))
|
|
||||||
with open(bit_filename, "rb") as bit_file, open(bin_handle, "wb") as bin_file:
|
|
||||||
bit2bin(bit_file, bin_file)
|
|
||||||
atexit.register(lambda: os.unlink(bin_filename))
|
|
||||||
return bin_filename
|
|
||||||
|
|
||||||
gateware = convert_gateware(os.path.join(args.directory, "top.bit"))
|
|
||||||
bootloader = os.path.join(args.directory, "bootloader.bin")
|
|
||||||
|
|
||||||
firmwares = []
|
|
||||||
for firmware in "satman", "runtime":
|
|
||||||
filename = os.path.join(args.directory, firmware + ".fbi")
|
|
||||||
if os.path.exists(filename):
|
|
||||||
firmwares.append(filename)
|
|
||||||
if not firmwares:
|
|
||||||
raise FileNotFoundError("no firmware found")
|
|
||||||
if len(firmwares) > 1:
|
|
||||||
raise ValueError("more than one firmware file, please clean up your build directory. "
|
|
||||||
"Found firmware files: {}".format(" ".join(firmwares)))
|
|
||||||
firmware = firmwares[0]
|
|
||||||
|
|
||||||
bins = {
|
|
||||||
"gateware": gateware,
|
|
||||||
"bootloader": bootloader,
|
|
||||||
"firmware": firmware,
|
|
||||||
}
|
|
||||||
mgmt.flash(**bins)
|
|
||||||
|
|
||||||
if args.tool == "reboot":
|
if args.tool == "reboot":
|
||||||
mgmt.reboot()
|
mgmt.reboot()
|
||||||
|
|
Loading…
Reference in New Issue