Compare commits

..

No commits in common. "abe0d6ff794186f70a3fdaaaac826b39bf811a9b" and "5f5b7148382b06be01ecbc57325b07e1b61c94e7" have entirely different histories.

6 changed files with 159 additions and 317 deletions

2
src/Cargo.lock generated
View File

@ -501,9 +501,7 @@ name = "satman"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"build_zynq", "build_zynq",
"byteorder",
"core_io", "core_io",
"crc",
"cslice", "cslice",
"embedded-hal", "embedded-hal",
"io", "io",

View File

@ -331,16 +331,6 @@ pub enum Packet {
CoreMgmtAllocatorDebugRequest { CoreMgmtAllocatorDebugRequest {
destination: u8, destination: u8,
}, },
CoreMgmtFlashRequest {
destination: u8,
last: bool,
length: u16,
data: [u8; MASTER_PAYLOAD_MAX_SIZE],
},
CoreMgmtDropLinkAck {
destination: u8,
},
CoreMgmtDropLink,
CoreMgmtGetLogReply { CoreMgmtGetLogReply {
last: bool, last: bool,
length: u16, length: u16,
@ -351,9 +341,8 @@ pub enum Packet {
length: u16, length: u16,
value: [u8; SAT_PAYLOAD_MAX_SIZE], value: [u8; SAT_PAYLOAD_MAX_SIZE],
}, },
CoreMgmtReply { CoreMgmtAck,
succeeded: bool, CoreMgmtNack,
},
} }
impl Packet { impl Packet {
@ -693,23 +682,6 @@ impl Packet {
destination: reader.read_u8()?, destination: reader.read_u8()?,
}, },
0xdb => { 0xdb => {
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,
}
}
0xdc => Packet::CoreMgmtDropLinkAck {
destination: reader.read_u8()?,
},
0xdd => Packet::CoreMgmtDropLink,
0xde => {
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16()?; let length = reader.read_u16()?;
let mut data: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE]; let mut data: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE];
@ -720,7 +692,7 @@ impl Packet {
data: data, data: data,
} }
} }
0xdf => { 0xdc => {
let last = reader.read_bool()?; let last = reader.read_bool()?;
let length = reader.read_u16()?; let length = reader.read_u16()?;
let mut value: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE]; let mut value: [u8; SAT_PAYLOAD_MAX_SIZE] = [0; SAT_PAYLOAD_MAX_SIZE];
@ -731,9 +703,8 @@ impl Packet {
value: value, value: value,
} }
} }
0xe0 => Packet::CoreMgmtReply { 0xdd => Packet::CoreMgmtAck,
succeeded: reader.read_bool()?, 0xde => Packet::CoreMgmtNack,
},
ty => return Err(Error::UnknownPacket(ty)), ty => return Err(Error::UnknownPacket(ty)),
}) })
@ -1178,39 +1149,20 @@ impl Packet {
writer.write_u8(0xda)?; writer.write_u8(0xda)?;
writer.write_u8(destination)?; writer.write_u8(destination)?;
} }
Packet::CoreMgmtFlashRequest {
destination,
last,
length,
data,
} => {
writer.write_u8(0xdb)?;
writer.write_u8(destination)?;
writer.write_bool(last)?;
writer.write_u16(length)?;
writer.write_all(&data[..length as usize])?;
}
Packet::CoreMgmtDropLinkAck { destination } => {
writer.write_u8(0xdc)?;
writer.write_u8(destination)?;
}
Packet::CoreMgmtDropLink => writer.write_u8(0xdd)?,
Packet::CoreMgmtGetLogReply { last, length, data } => { Packet::CoreMgmtGetLogReply { last, length, data } => {
writer.write_u8(0xde)?; writer.write_u8(0xdb)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16(length)?; writer.write_u16(length)?;
writer.write_all(&data[0..length as usize])?; writer.write_all(&data[0..length as usize])?;
} }
Packet::CoreMgmtConfigReadReply { last, length, value } => { Packet::CoreMgmtConfigReadReply { last, length, value } => {
writer.write_u8(0xdf)?; writer.write_u8(0xdc)?;
writer.write_bool(last)?; writer.write_bool(last)?;
writer.write_u16(length)?; writer.write_u16(length)?;
writer.write_all(&value[0..length as usize])?; writer.write_all(&value[0..length as usize])?;
} }
Packet::CoreMgmtReply { succeeded } => { Packet::CoreMgmtAck => writer.write_u8(0xdd)?,
writer.write_u8(0xe0)?; Packet::CoreMgmtNack => writer.write_u8(0xde)?,
writer.write_bool(succeeded)?;
}
} }
Ok(()) Ok(())
} }

View File

@ -3,18 +3,19 @@ use core::{cell::RefCell, ops::Deref};
use futures::{future::poll_fn, task::Poll}; use futures::{future::poll_fn, task::Poll};
use libasync::{smoltcp::TcpStream, task}; use libasync::{smoltcp::TcpStream, task};
use libboard_artiq::{drtio_routing::RoutingTable, use libboard_artiq::{drtio_routing,
drtio_routing::RoutingTable,
logger::{BufferLogger, LogBufferRef}}; logger::{BufferLogger, LogBufferRef}};
use libboard_zynq::{smoltcp, timer::GlobalTimer}; use libboard_zynq::{slcr, smoltcp, timer::GlobalTimer};
use libconfig::Config; use libconfig::Config;
use libcortex_a9::mutex::Mutex; use libcortex_a9::mutex::Mutex;
use log::{self, debug, error, info, warn}; use log::{self, debug, error, info, warn, LevelFilter};
use num_derive::FromPrimitive; use num_derive::FromPrimitive;
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use crate::proto_async::*; use crate::proto_async::*;
#[cfg(has_drtio)] #[cfg(has_drtio)]
use crate::rtio_mgt::drtio; use crate::rtio_mgt::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error { pub enum Error {
@ -69,8 +70,6 @@ pub enum Request {
ConfigErase = 15, ConfigErase = 15,
DebugAllocator = 8, DebugAllocator = 8,
Flash = 9,
} }
#[repr(i8)] #[repr(i8)]
@ -133,17 +132,16 @@ async fn read_key(stream: &mut TcpStream) -> Result<String> {
#[cfg(has_drtio)] #[cfg(has_drtio)]
mod remote_coremgmt { mod remote_coremgmt {
use core_io::Read; use io::{Cursor, ProtoWrite};
use io::ProtoWrite; use libboard_artiq::drtioaux_proto::{Packet, MASTER_PAYLOAD_MAX_SIZE};
use libboard_artiq::{drtioaux_async,
drtioaux_proto::{Packet, MASTER_PAYLOAD_MAX_SIZE}};
use super::*; use super::*;
use crate::rtio_mgt::drtio;
pub async fn get_log( pub async fn get_log(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -188,7 +186,7 @@ mod remote_coremgmt {
pub async fn clear_log( pub async fn clear_log(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -203,7 +201,7 @@ mod remote_coremgmt {
.await; .await;
match reply { match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) => { Ok(Packet::CoreMgmtAck) => {
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
@ -223,7 +221,7 @@ mod remote_coremgmt {
pub async fn pull_log( pub async fn pull_log(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -274,11 +272,11 @@ mod remote_coremgmt {
pub async fn set_log_filter( pub async fn set_log_filter(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
level: log::LevelFilter, level: LevelFilter,
) -> Result<()> { ) -> Result<()> {
let reply = drtio::aux_transact( let reply = drtio::aux_transact(
aux_mutex, aux_mutex,
@ -293,7 +291,7 @@ mod remote_coremgmt {
.await; .await;
match reply { match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) => { Ok(Packet::CoreMgmtAck) => {
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
@ -313,11 +311,11 @@ mod remote_coremgmt {
pub async fn set_uart_log_filter( pub async fn set_uart_log_filter(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
level: log::LevelFilter, level: LevelFilter,
) -> Result<()> { ) -> Result<()> {
let reply = drtio::aux_transact( let reply = drtio::aux_transact(
aux_mutex, aux_mutex,
@ -332,7 +330,7 @@ mod remote_coremgmt {
.await; .await;
match reply { match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) => { Ok(Packet::CoreMgmtAck) => {
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
@ -352,7 +350,7 @@ mod remote_coremgmt {
pub async fn config_read( pub async fn config_read(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -416,7 +414,7 @@ mod remote_coremgmt {
pub async fn config_write( pub async fn config_write(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -424,7 +422,7 @@ mod remote_coremgmt {
key: &String, key: &String,
value: Vec<u8>, value: Vec<u8>,
) -> Result<()> { ) -> Result<()> {
let mut message = Vec::with_capacity(key.len() + value.len() + 4 * 2); let mut message = Cursor::new(Vec::with_capacity(key.len() + value.len() + 4 * 2));
message.write_string(key).unwrap(); message.write_string(key).unwrap();
message.write_bytes(&value).unwrap(); message.write_bytes(&value).unwrap();
@ -433,7 +431,7 @@ mod remote_coremgmt {
aux_mutex, aux_mutex,
routing_table, routing_table,
timer, timer,
&message, message.get_ref(),
|slice, status, len: usize| Packet::CoreMgmtConfigWriteRequest { |slice, status, len: usize| Packet::CoreMgmtConfigWriteRequest {
destination: destination, destination: destination,
last: status.is_last(), last: status.is_last(),
@ -441,7 +439,7 @@ mod remote_coremgmt {
data: *slice, data: *slice,
}, },
|reply| match reply { |reply| match reply {
Packet::CoreMgmtReply { succeeded: true } => Ok(()), Packet::CoreMgmtAck => Ok(()),
packet => { packet => {
error!("received unexpected aux packet: {:?}", packet); error!("received unexpected aux packet: {:?}", packet);
Err(drtio::Error::UnexpectedReply) Err(drtio::Error::UnexpectedReply)
@ -465,7 +463,7 @@ mod remote_coremgmt {
pub async fn config_remove( pub async fn config_remove(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -490,7 +488,7 @@ mod remote_coremgmt {
.await; .await;
match reply { match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) => { Ok(Packet::CoreMgmtAck) => {
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
@ -510,7 +508,7 @@ mod remote_coremgmt {
pub async fn config_erase( pub async fn config_erase(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -527,7 +525,7 @@ mod remote_coremgmt {
.await; .await;
match reply { match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) => { Ok(Packet::CoreMgmtAck) => {
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
@ -547,7 +545,7 @@ mod remote_coremgmt {
pub async fn reboot( pub async fn reboot(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -565,7 +563,7 @@ mod remote_coremgmt {
.await; .await;
match reply { match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) => { Ok(Packet::CoreMgmtAck) => {
write_i8(stream, Reply::RebootImminent as i8).await?; write_i8(stream, Reply::RebootImminent as i8).await?;
Ok(()) Ok(())
} }
@ -585,7 +583,7 @@ mod remote_coremgmt {
pub async fn debug_allocator( pub async fn debug_allocator(
stream: &mut TcpStream, stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>, aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable, routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer, timer: GlobalTimer,
linkno: u8, linkno: u8,
destination: u8, destination: u8,
@ -602,7 +600,7 @@ mod remote_coremgmt {
.await; .await;
match reply { match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) => { Ok(Packet::CoreMgmtAck) => {
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
@ -616,69 +614,9 @@ mod remote_coremgmt {
} }
} }
} }
pub async fn image_write(
stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &RoutingTable,
timer: GlobalTimer,
linkno: u8,
destination: u8,
_cfg: &Rc<Config>,
image: Vec<u8>,
) -> Result<()> {
let mut image = &image[..];
while !image.is_empty() {
let mut data = [0; MASTER_PAYLOAD_MAX_SIZE];
let len = image.read(&mut data).unwrap();
let last = image.is_empty();
let reply = drtio::aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::CoreMgmtFlashRequest {
destination: destination,
last: last,
length: len as u16,
data: data,
},
timer,
)
.await;
match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) if !last => Ok(()),
Ok(Packet::CoreMgmtDropLink) if last => drtioaux_async::send(
linkno,
&Packet::CoreMgmtDropLinkAck {
destination: destination,
},
)
.await
.map_err(|_| drtio::Error::AuxError),
Ok(packet) => {
error!("received unexpected aux packet: {:?}", packet);
write_i8(stream, Reply::Error as i8).await?;
Err(drtio::Error::UnexpectedReply)
}
Err(e) => {
error!("aux packet error ({})", e);
write_i8(stream, Reply::Error as i8).await?;
Err(drtio::Error::AuxError)
}
}?;
}
write_i8(stream, Reply::RebootImminent as i8).await?;
Ok(())
}
} }
mod local_coremgmt { mod local_coremgmt {
use libboard_zynq::slcr;
use super::*; use super::*;
pub async fn get_log(stream: &mut TcpStream) -> Result<()> { pub async fn get_log(stream: &mut TcpStream) -> Result<()> {
@ -712,25 +650,25 @@ mod local_coremgmt {
buffer.clear(); buffer.clear();
core::mem::drop(buffer); core::mem::drop(buffer);
write_chunk(stream, &bytes).await?; write_chunk(stream, &bytes).await?;
if log::max_level() == log::LevelFilter::Trace { if log::max_level() == LevelFilter::Trace {
// temporarily discard all trace level log // temporarily discard all trace level log
let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() }; let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() };
logger.set_buffer_log_level(log::LevelFilter::Debug); logger.set_buffer_log_level(LevelFilter::Debug);
stream.flush().await?; stream.flush().await?;
logger.set_buffer_log_level(log::LevelFilter::Trace); logger.set_buffer_log_level(LevelFilter::Trace);
} }
} }
Ok(()) Ok(())
} }
pub async fn set_log_filter(stream: &mut TcpStream, lvl: log::LevelFilter) -> Result<()> { pub async fn set_log_filter(stream: &mut TcpStream, lvl: LevelFilter) -> Result<()> {
info!("Changing log level to {}", lvl); info!("Changing log level to {}", lvl);
log::set_max_level(lvl); log::set_max_level(lvl);
write_i8(stream, Reply::Success as i8).await?; write_i8(stream, Reply::Success as i8).await?;
Ok(()) Ok(())
} }
pub async fn set_uart_log_filter(stream: &mut TcpStream, lvl: log::LevelFilter) -> Result<()> { pub async fn set_uart_log_filter(stream: &mut TcpStream, lvl: LevelFilter) -> Result<()> {
info!("Changing UART log level to {}", lvl); info!("Changing UART log level to {}", lvl);
unsafe { unsafe {
BufferLogger::get_logger().as_ref().unwrap().set_uart_log_level(lvl); BufferLogger::get_logger().as_ref().unwrap().set_uart_log_level(lvl);
@ -796,18 +734,6 @@ mod local_coremgmt {
error!("zynq device does not support allocator debug print"); error!("zynq device does not support allocator debug print");
Ok(()) Ok(())
} }
pub async fn image_write(stream: &mut TcpStream, cfg: &Rc<Config>, image: Vec<u8>) -> Result<()> {
let value = cfg.write("boot", image);
if value.is_ok() {
reboot(stream).await?;
} else {
// this is an error because we do not expect write to fail
error!("failed to write boot file: {:?}", value);
write_i8(stream, Reply::Error as i8).await?;
}
Ok(())
}
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
@ -855,18 +781,43 @@ async fn handle_connection(
match msg { match msg {
Request::GetLog => process!(stream, _drtio_tuple, _destination, get_log), Request::GetLog => process!(stream, _drtio_tuple, _destination, get_log),
Request::ClearLog => process!(stream, _drtio_tuple, _destination, clear_log), Request::ClearLog => process!(stream, _drtio_tuple, _destination, clear_log),
Request::PullLog => process!(stream, _drtio_tuple, _destination, pull_log, &pull_id), Request::PullLog => process!(
stream,
_drtio_tuple,
_destination,
pull_log,
&pull_id
),
Request::SetLogFilter => { Request::SetLogFilter => {
let lvl = read_log_level_filter(stream).await?; let lvl = read_log_level_filter(stream).await?;
process!(stream, _drtio_tuple, _destination, set_log_filter, lvl) process!(
stream,
_drtio_tuple,
_destination,
set_log_filter,
lvl
)
} }
Request::SetUartLogFilter => { Request::SetUartLogFilter => {
let lvl = read_log_level_filter(stream).await?; let lvl = read_log_level_filter(stream).await?;
process!(stream, _drtio_tuple, _destination, set_uart_log_filter, lvl) process!(
stream,
_drtio_tuple,
_destination,
set_uart_log_filter,
lvl
)
} }
Request::ConfigRead => { Request::ConfigRead => {
let key = read_key(stream).await?; let key = read_key(stream).await?;
process!(stream, _drtio_tuple, _destination, config_read, &cfg, &key) process!(
stream,
_drtio_tuple,
_destination,
config_read,
&cfg,
&key
)
} }
Request::ConfigWrite => { Request::ConfigWrite => {
let key = read_key(stream).await?; let key = read_key(stream).await?;
@ -877,11 +828,26 @@ async fn handle_connection(
buffer.set_len(len); buffer.set_len(len);
} }
read_chunk(stream, &mut buffer).await?; read_chunk(stream, &mut buffer).await?;
process!(stream, _drtio_tuple, _destination, config_write, &cfg, &key, buffer) process!(
stream,
_drtio_tuple,
_destination,
config_write,
&cfg,
&key,
buffer
)
} }
Request::ConfigRemove => { Request::ConfigRemove => {
let key = read_key(stream).await?; let key = read_key(stream).await?;
process!(stream, _drtio_tuple, _destination, config_remove, &cfg, &key) process!(
stream,
_drtio_tuple,
_destination,
config_remove,
&cfg,
&key
)
} }
Request::Reboot => { Request::Reboot => {
process!(stream, _drtio_tuple, _destination, reboot) process!(stream, _drtio_tuple, _destination, reboot)
@ -890,28 +856,28 @@ async fn handle_connection(
process!(stream, _drtio_tuple, _destination, config_erase) process!(stream, _drtio_tuple, _destination, config_erase)
} }
Request::DebugAllocator => { Request::DebugAllocator => {
process!(stream, _drtio_tuple, _destination, debug_allocator) process!(
} stream,
Request::Flash => { _drtio_tuple,
let len = read_i32(stream).await?; _destination,
if len <= 0 { debug_allocator
write_i8(stream, Reply::Error as i8).await?; )
return Err(Error::UnexpectedPattern);
}
let mut buffer = Vec::with_capacity(len as usize);
unsafe {
buffer.set_len(len as usize);
}
read_chunk(stream, &mut buffer).await?;
process!(stream, _drtio_tuple, _destination, image_write, &cfg, buffer)
} }
}?; }?;
} }
} }
pub fn start(cfg: Config, drtio_tuple: Option<(&Rc<Mutex<bool>>, &Rc<RefCell<RoutingTable>>, GlobalTimer)>) { pub fn start(
let drtio_tuple = cfg: Config,
drtio_tuple.map(|(aux_mutex, routing_table, timer)| (aux_mutex.clone(), routing_table.clone(), timer)); drtio_tuple: Option<(
&Rc<Mutex<bool>>,
&Rc<RefCell<drtio_routing::RoutingTable>>,
GlobalTimer,
)>,
) {
let drtio_tuple = drtio_tuple.map(
|(aux_mutex, routing_table, timer)| (aux_mutex.clone(), routing_table.clone(), timer)
);
task::spawn(async move { task::spawn(async move {
let pull_id = Rc::new(RefCell::new(0u32)); let pull_id = Rc::new(RefCell::new(0u32));
let cfg = Rc::new(cfg); let cfg = Rc::new(cfg);
@ -925,12 +891,12 @@ pub fn start(cfg: Config, drtio_tuple: Option<(&Rc<Mutex<bool>>, &Rc<RefCell<Rou
info!("received connection"); info!("received connection");
// Avoid consuming the tuple // Avoid consuming the tuple
// Keep the borrowed value on stack // Keep the borrowed value on stack
let drtio_tuple = drtio_tuple let drtio_tuple = drtio_tuple.as_ref().map(
.as_ref() |(aux_mutex, routing_table, timer)| (aux_mutex, routing_table.borrow(), *timer)
.map(|(aux_mutex, routing_table, timer)| (aux_mutex, routing_table.borrow(), *timer)); );
let drtio_tuple = drtio_tuple let drtio_tuple = drtio_tuple.as_ref().map(
.as_ref() |(aux_mutex, routing_table, timer)| (*aux_mutex, routing_table.deref(), *timer)
.map(|(aux_mutex, routing_table, timer)| (*aux_mutex, routing_table.deref(), *timer)); );
let _ = handle_connection(&mut stream, pull_id, cfg, drtio_tuple) let _ = handle_connection(&mut stream, pull_id, cfg, drtio_tuple)
.await .await
.map_err(|e| warn!("connection terminated: {:?}", e)); .map_err(|e| warn!("connection terminated: {:?}", e));

View File

@ -15,9 +15,7 @@ build_zynq = { path = "../libbuild_zynq" }
[dependencies] [dependencies]
log = { version = "0.4", default-features = false } log = { version = "0.4", default-features = false }
byteorder = { version = "1.3", default-features = false }
core_io = { version = "0.1", features = ["collections"] } core_io = { version = "0.1", features = ["collections"] }
crc = { version = "1.7", default-features = false }
cslice = "0.3" cslice = "0.3"
embedded-hal = "0.2" embedded-hal = "0.2"

View File

@ -4,9 +4,7 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate byteorder;
extern crate core_io; extern crate core_io;
extern crate crc;
extern crate cslice; extern crate cslice;
extern crate embedded_hal; extern crate embedded_hal;
@ -1057,7 +1055,7 @@ fn process_aux_packet(
timer timer
); );
mgmt::clear_log(); mgmt::clear_log();
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} }
drtioaux::Packet::CoreMgmtSetLogLevelRequest { drtioaux::Packet::CoreMgmtSetLogLevelRequest {
destination: _destination, destination: _destination,
@ -1077,9 +1075,9 @@ fn process_aux_packet(
if let Ok(level_filter) = mgmt::byte_to_level_filter(log_level) { if let Ok(level_filter) = mgmt::byte_to_level_filter(log_level) {
info!("Changing log level to {}", level_filter); info!("Changing log level to {}", level_filter);
log::set_max_level(level_filter); log::set_max_level(level_filter);
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} else { } else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
} }
} }
drtioaux::Packet::CoreMgmtSetUartLogLevelRequest { drtioaux::Packet::CoreMgmtSetUartLogLevelRequest {
@ -1105,9 +1103,9 @@ fn process_aux_packet(
.unwrap() .unwrap()
.set_uart_log_level(level_filter); .set_uart_log_level(level_filter);
} }
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} else { } else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
} }
} }
drtioaux::Packet::CoreMgmtConfigReadRequest { drtioaux::Packet::CoreMgmtConfigReadRequest {
@ -1131,7 +1129,7 @@ fn process_aux_packet(
let key_slice = &key[..length as usize]; let key_slice = &key[..length as usize];
if !key_slice.is_ascii() { if !key_slice.is_ascii() {
error!("invalid key"); error!("invalid key");
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
} else { } else {
let key = core::str::from_utf8(key_slice).unwrap(); let key = core::str::from_utf8(key_slice).unwrap();
if core_manager.fetch_config_value(key).is_ok() { if core_manager.fetch_config_value(key).is_ok() {
@ -1145,7 +1143,7 @@ fn process_aux_packet(
}, },
) )
} else { } else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
} }
} }
} }
@ -1191,15 +1189,19 @@ fn process_aux_packet(
timer timer
); );
core_manager.add_config_data(&data, length as usize); core_manager.add_data(&data, length as usize);
let mut succeeded = true; let mut succeeded = true;
if last { if last {
succeeded = core_manager.write_config().is_ok(); succeeded = core_manager.write_config().is_ok();
core_manager.clear_config_data(); core_manager.clear_data();
} }
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded }) if succeeded {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
}
} }
drtioaux::Packet::CoreMgmtConfigRemoveRequest { drtioaux::Packet::CoreMgmtConfigRemoveRequest {
destination: _destination, destination: _destination,
@ -1220,11 +1222,14 @@ fn process_aux_packet(
let key_slice = &key[..length as usize]; let key_slice = &key[..length as usize];
if !key_slice.is_ascii() { if !key_slice.is_ascii() {
error!("invalid key"); error!("invalid key");
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
} else { } else {
let key = core::str::from_utf8(key_slice).unwrap(); let key = core::str::from_utf8(key_slice).unwrap();
let succeeded = core_manager.remove_config(key).is_ok(); if core_manager.remove_config(key).is_ok() {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
}
} }
} }
drtioaux::Packet::CoreMgmtConfigEraseRequest { drtioaux::Packet::CoreMgmtConfigEraseRequest {
@ -1242,7 +1247,7 @@ fn process_aux_packet(
); );
error!("config erase not supported on zynq device"); error!("config erase not supported on zynq device");
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
} }
drtioaux::Packet::CoreMgmtRebootRequest { drtioaux::Packet::CoreMgmtRebootRequest {
destination: _destination, destination: _destination,
@ -1259,11 +1264,10 @@ fn process_aux_packet(
timer timer
); );
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })?; drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)?;
info!("reboot imminent"); info!("reboot imminent");
slcr::reboot(); slcr::reboot();
Ok(())
unreachable!();
} }
drtioaux::Packet::CoreMgmtAllocatorDebugRequest { drtioaux::Packet::CoreMgmtAllocatorDebugRequest {
destination: _destination, destination: _destination,
@ -1280,54 +1284,7 @@ fn process_aux_packet(
); );
error!("debug allocator not supported on zynq device"); error!("debug allocator not supported on zynq device");
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
}
drtioaux::Packet::CoreMgmtFlashRequest {
destination: _destination,
last,
length,
data,
} => {
forward!(
router,
_routing_table,
_destination,
*rank,
*self_destination,
_repeaters,
&packet,
timer
);
core_manager.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,
timer
);
unsafe {
csr::gt_drtio::txenable_write(0);
}
core_manager.write_image();
info!("reboot imminent");
slcr::reboot();
Ok(())
} }
p => { p => {

View File

@ -1,25 +1,23 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use byteorder::{ByteOrder, NativeEndian}; use io::{Cursor, ProtoRead, ProtoWrite};
use crc::crc32;
use io::{ProtoRead, ProtoWrite};
use libboard_artiq::{drtioaux_proto::SAT_PAYLOAD_MAX_SIZE, use libboard_artiq::{drtioaux_proto::SAT_PAYLOAD_MAX_SIZE,
logger::{BufferLogger, LogBufferRef}}; logger::{BufferLogger, LogBufferRef}};
use libconfig::Config; use libconfig::Config;
use log::{debug, error, info, warn, LevelFilter}; use log::{self, debug, error, info, warn, LevelFilter};
use crate::routing::{SliceMeta, Sliceable}; use crate::routing::{SliceMeta, Sliceable};
type Result<T> = core::result::Result<T, ()>; type Result<T> = core::result::Result<T, ()>;
pub fn byte_to_level_filter(level_byte: u8) -> Result<LevelFilter> { pub fn byte_to_level_filter(level_byte: u8) -> Result<log::LevelFilter> {
Ok(match level_byte { Ok(match level_byte {
0 => LevelFilter::Off, 0 => log::LevelFilter::Off,
1 => LevelFilter::Error, 1 => log::LevelFilter::Error,
2 => LevelFilter::Warn, 2 => log::LevelFilter::Warn,
3 => LevelFilter::Info, 3 => log::LevelFilter::Info,
4 => LevelFilter::Debug, 4 => log::LevelFilter::Debug,
5 => LevelFilter::Trace, 5 => log::LevelFilter::Trace,
lv => { lv => {
error!("unknown log level: {}", lv); error!("unknown log level: {}", lv);
return Err(()); return Err(());
@ -48,9 +46,8 @@ pub fn clear_log() {
pub struct Manager<'a> { pub struct Manager<'a> {
cfg: &'a mut Config, cfg: &'a mut Config,
last_log: Sliceable, last_log: Sliceable,
config_payload: Vec<u8>, current_payload: Cursor<Vec<u8>>,
last_value: Sliceable, last_value: Sliceable,
image_payload: Vec<u8>,
} }
impl<'a> Manager<'_> { impl<'a> Manager<'_> {
@ -58,9 +55,8 @@ impl<'a> Manager<'_> {
Manager { Manager {
cfg: cfg, cfg: cfg,
last_log: Sliceable::new(0, Vec::new()), last_log: Sliceable::new(0, Vec::new()),
config_payload: Vec::new(), current_payload: Cursor::new(Vec::new()),
last_value: Sliceable::new(0, Vec::new()), last_value: Sliceable::new(0, Vec::new()),
image_payload: Vec::new(),
} }
} }
@ -87,19 +83,22 @@ impl<'a> Manager<'_> {
self.last_value.get_slice_satellite(data_slice) self.last_value.get_slice_satellite(data_slice)
} }
pub fn add_config_data(&mut self, data: &[u8], data_len: usize) { pub fn add_data(&mut self, data: &[u8], data_len: usize) {
self.config_payload.write_all(&data[..data_len]).unwrap(); self.current_payload.write_all(&data[..data_len]).unwrap();
} }
pub fn clear_config_data(&mut self) { pub fn clear_data(&mut self) {
self.config_payload.clear(); self.current_payload.get_mut().clear();
self.current_payload.set_position(0);
} }
pub fn write_config(&mut self) -> Result<()> { pub fn write_config(&mut self) -> Result<()> {
let mut payload = &self.config_payload[..]; let key = self
let key = payload.read_string().map_err(|_err| error!("error on reading key"))?; .current_payload
.read_string()
.map_err(|_err| error!("error on reading key"))?;
debug!("write key: {}", key); debug!("write key: {}", key);
let value = payload.read_bytes().unwrap(); let value = self.current_payload.read_bytes().unwrap();
self.cfg self.cfg
.write(&key, value) .write(&key, value)
@ -114,32 +113,4 @@ impl<'a> Manager<'_> {
.map(|()| debug!("erase success")) .map(|()| debug!("erase success"))
.map_err(|err| warn!("failed to erase: {:?}", err)) .map_err(|err| warn!("failed to erase: {:?}", err))
} }
pub fn add_image_data(&mut self, data: &[u8], data_len: usize) {
self.image_payload.extend(&data[..data_len]);
}
pub fn write_image(&self) {
let mut image = self.image_payload.clone();
let image_ref = &image[..];
let bin_len = image.len() - 4;
let (image_ref, expected_crc) = {
let (image_ref, crc_slice) = image_ref.split_at(bin_len);
(image_ref, NativeEndian::read_u32(crc_slice))
};
let actual_crc = crc32::checksum_ieee(image_ref);
if actual_crc == expected_crc {
info!("CRC passed. Writing boot image to SD card...");
image.truncate(bin_len);
self.cfg.write("boot", image).expect("failed to write boot image");
} else {
panic!(
"CRC failed in SDRAM (actual {:08x}, expected {:08x})",
actual_crc, expected_crc
);
}
}
} }