forked from M-Labs/artiq-zynq
Compare commits
8 Commits
5f5b714838
...
abe0d6ff79
Author | SHA1 | Date |
---|---|---|
occheung | abe0d6ff79 | |
occheung | 25835868b7 | |
occheung | b47a1d0907 | |
occheung | 1103fb0dfc | |
occheung | 299cecd962 | |
occheung | fc1fd96f71 | |
occheung | c8f286307a | |
occheung | 5b4202cde7 |
|
@ -501,7 +501,9 @@ 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",
|
||||||
|
|
|
@ -331,6 +331,16 @@ 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,
|
||||||
|
@ -341,8 +351,9 @@ pub enum Packet {
|
||||||
length: u16,
|
length: u16,
|
||||||
value: [u8; SAT_PAYLOAD_MAX_SIZE],
|
value: [u8; SAT_PAYLOAD_MAX_SIZE],
|
||||||
},
|
},
|
||||||
CoreMgmtAck,
|
CoreMgmtReply {
|
||||||
CoreMgmtNack,
|
succeeded: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Packet {
|
impl Packet {
|
||||||
|
@ -682,6 +693,23 @@ 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];
|
||||||
|
@ -692,7 +720,7 @@ impl Packet {
|
||||||
data: data,
|
data: data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0xdc => {
|
0xdf => {
|
||||||
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];
|
||||||
|
@ -703,8 +731,9 @@ impl Packet {
|
||||||
value: value,
|
value: value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0xdd => Packet::CoreMgmtAck,
|
0xe0 => Packet::CoreMgmtReply {
|
||||||
0xde => Packet::CoreMgmtNack,
|
succeeded: reader.read_bool()?,
|
||||||
|
},
|
||||||
|
|
||||||
ty => return Err(Error::UnknownPacket(ty)),
|
ty => return Err(Error::UnknownPacket(ty)),
|
||||||
})
|
})
|
||||||
|
@ -1149,20 +1178,39 @@ impl Packet {
|
||||||
writer.write_u8(0xda)?;
|
writer.write_u8(0xda)?;
|
||||||
writer.write_u8(destination)?;
|
writer.write_u8(destination)?;
|
||||||
}
|
}
|
||||||
Packet::CoreMgmtGetLogReply { last, length, data } => {
|
Packet::CoreMgmtFlashRequest {
|
||||||
|
destination,
|
||||||
|
last,
|
||||||
|
length,
|
||||||
|
data,
|
||||||
|
} => {
|
||||||
writer.write_u8(0xdb)?;
|
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 } => {
|
||||||
|
writer.write_u8(0xde)?;
|
||||||
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(0xdc)?;
|
writer.write_u8(0xdf)?;
|
||||||
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::CoreMgmtAck => writer.write_u8(0xdd)?,
|
Packet::CoreMgmtReply { succeeded } => {
|
||||||
Packet::CoreMgmtNack => writer.write_u8(0xde)?,
|
writer.write_u8(0xe0)?;
|
||||||
|
writer.write_bool(succeeded)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,18 @@ 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,
|
use libboard_artiq::{drtio_routing::RoutingTable,
|
||||||
drtio_routing::RoutingTable,
|
|
||||||
logger::{BufferLogger, LogBufferRef}};
|
logger::{BufferLogger, LogBufferRef}};
|
||||||
use libboard_zynq::{slcr, smoltcp, timer::GlobalTimer};
|
use libboard_zynq::{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, LevelFilter};
|
use log::{self, debug, error, info, warn};
|
||||||
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::*;
|
use crate::rtio_mgt::drtio;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -70,6 +69,8 @@ pub enum Request {
|
||||||
ConfigErase = 15,
|
ConfigErase = 15,
|
||||||
|
|
||||||
DebugAllocator = 8,
|
DebugAllocator = 8,
|
||||||
|
|
||||||
|
Flash = 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(i8)]
|
#[repr(i8)]
|
||||||
|
@ -132,16 +133,17 @@ async fn read_key(stream: &mut TcpStream) -> Result<String> {
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
mod remote_coremgmt {
|
mod remote_coremgmt {
|
||||||
use io::{Cursor, ProtoWrite};
|
use core_io::Read;
|
||||||
use libboard_artiq::drtioaux_proto::{Packet, MASTER_PAYLOAD_MAX_SIZE};
|
use io::ProtoWrite;
|
||||||
|
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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -186,7 +188,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -201,7 +203,7 @@ mod remote_coremgmt {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::CoreMgmtAck) => {
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
||||||
write_i8(stream, Reply::Success as i8).await?;
|
write_i8(stream, Reply::Success as i8).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -221,7 +223,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -272,11 +274,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
level: LevelFilter,
|
level: log::LevelFilter,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let reply = drtio::aux_transact(
|
let reply = drtio::aux_transact(
|
||||||
aux_mutex,
|
aux_mutex,
|
||||||
|
@ -291,7 +293,7 @@ mod remote_coremgmt {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::CoreMgmtAck) => {
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
||||||
write_i8(stream, Reply::Success as i8).await?;
|
write_i8(stream, Reply::Success as i8).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -311,11 +313,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
level: LevelFilter,
|
level: log::LevelFilter,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let reply = drtio::aux_transact(
|
let reply = drtio::aux_transact(
|
||||||
aux_mutex,
|
aux_mutex,
|
||||||
|
@ -330,7 +332,7 @@ mod remote_coremgmt {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::CoreMgmtAck) => {
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
||||||
write_i8(stream, Reply::Success as i8).await?;
|
write_i8(stream, Reply::Success as i8).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -350,7 +352,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -414,7 +416,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -422,7 +424,7 @@ mod remote_coremgmt {
|
||||||
key: &String,
|
key: &String,
|
||||||
value: Vec<u8>,
|
value: Vec<u8>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut message = Cursor::new(Vec::with_capacity(key.len() + value.len() + 4 * 2));
|
let mut message = 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();
|
||||||
|
|
||||||
|
@ -431,7 +433,7 @@ mod remote_coremgmt {
|
||||||
aux_mutex,
|
aux_mutex,
|
||||||
routing_table,
|
routing_table,
|
||||||
timer,
|
timer,
|
||||||
message.get_ref(),
|
&message,
|
||||||
|slice, status, len: usize| Packet::CoreMgmtConfigWriteRequest {
|
|slice, status, len: usize| Packet::CoreMgmtConfigWriteRequest {
|
||||||
destination: destination,
|
destination: destination,
|
||||||
last: status.is_last(),
|
last: status.is_last(),
|
||||||
|
@ -439,7 +441,7 @@ mod remote_coremgmt {
|
||||||
data: *slice,
|
data: *slice,
|
||||||
},
|
},
|
||||||
|reply| match reply {
|
|reply| match reply {
|
||||||
Packet::CoreMgmtAck => Ok(()),
|
Packet::CoreMgmtReply { succeeded: true } => Ok(()),
|
||||||
packet => {
|
packet => {
|
||||||
error!("received unexpected aux packet: {:?}", packet);
|
error!("received unexpected aux packet: {:?}", packet);
|
||||||
Err(drtio::Error::UnexpectedReply)
|
Err(drtio::Error::UnexpectedReply)
|
||||||
|
@ -463,7 +465,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -488,7 +490,7 @@ mod remote_coremgmt {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::CoreMgmtAck) => {
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
||||||
write_i8(stream, Reply::Success as i8).await?;
|
write_i8(stream, Reply::Success as i8).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -508,7 +510,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -525,7 +527,7 @@ mod remote_coremgmt {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::CoreMgmtAck) => {
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
||||||
write_i8(stream, Reply::Success as i8).await?;
|
write_i8(stream, Reply::Success as i8).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -545,7 +547,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -563,7 +565,7 @@ mod remote_coremgmt {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::CoreMgmtAck) => {
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
||||||
write_i8(stream, Reply::RebootImminent as i8).await?;
|
write_i8(stream, Reply::RebootImminent as i8).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -583,7 +585,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: &drtio_routing::RoutingTable,
|
routing_table: &RoutingTable,
|
||||||
timer: GlobalTimer,
|
timer: GlobalTimer,
|
||||||
linkno: u8,
|
linkno: u8,
|
||||||
destination: u8,
|
destination: u8,
|
||||||
|
@ -600,7 +602,7 @@ mod remote_coremgmt {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match reply {
|
match reply {
|
||||||
Ok(Packet::CoreMgmtAck) => {
|
Ok(Packet::CoreMgmtReply { succeeded: true }) => {
|
||||||
write_i8(stream, Reply::Success as i8).await?;
|
write_i8(stream, Reply::Success as i8).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -614,9 +616,69 @@ 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<()> {
|
||||||
|
@ -650,25 +712,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() == LevelFilter::Trace {
|
if log::max_level() == log::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(LevelFilter::Debug);
|
logger.set_buffer_log_level(log::LevelFilter::Debug);
|
||||||
stream.flush().await?;
|
stream.flush().await?;
|
||||||
logger.set_buffer_log_level(LevelFilter::Trace);
|
logger.set_buffer_log_level(log::LevelFilter::Trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_log_filter(stream: &mut TcpStream, lvl: LevelFilter) -> Result<()> {
|
pub async fn set_log_filter(stream: &mut TcpStream, lvl: log::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: LevelFilter) -> Result<()> {
|
pub async fn set_uart_log_filter(stream: &mut TcpStream, lvl: log::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);
|
||||||
|
@ -734,6 +796,18 @@ 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)]
|
||||||
|
@ -781,43 +855,18 @@ 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!(
|
Request::PullLog => process!(stream, _drtio_tuple, _destination, pull_log, &pull_id),
|
||||||
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!(
|
process!(stream, _drtio_tuple, _destination, set_log_filter, lvl)
|
||||||
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!(
|
process!(stream, _drtio_tuple, _destination, set_uart_log_filter, lvl)
|
||||||
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!(
|
process!(stream, _drtio_tuple, _destination, config_read, &cfg, &key)
|
||||||
stream,
|
|
||||||
_drtio_tuple,
|
|
||||||
_destination,
|
|
||||||
config_read,
|
|
||||||
&cfg,
|
|
||||||
&key
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Request::ConfigWrite => {
|
Request::ConfigWrite => {
|
||||||
let key = read_key(stream).await?;
|
let key = read_key(stream).await?;
|
||||||
|
@ -828,26 +877,11 @@ 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!(
|
process!(stream, _drtio_tuple, _destination, config_write, &cfg, &key, buffer)
|
||||||
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!(
|
process!(stream, _drtio_tuple, _destination, config_remove, &cfg, &key)
|
||||||
stream,
|
|
||||||
_drtio_tuple,
|
|
||||||
_destination,
|
|
||||||
config_remove,
|
|
||||||
&cfg,
|
|
||||||
&key
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Request::Reboot => {
|
Request::Reboot => {
|
||||||
process!(stream, _drtio_tuple, _destination, reboot)
|
process!(stream, _drtio_tuple, _destination, reboot)
|
||||||
|
@ -856,28 +890,28 @@ async fn handle_connection(
|
||||||
process!(stream, _drtio_tuple, _destination, config_erase)
|
process!(stream, _drtio_tuple, _destination, config_erase)
|
||||||
}
|
}
|
||||||
Request::DebugAllocator => {
|
Request::DebugAllocator => {
|
||||||
process!(
|
process!(stream, _drtio_tuple, _destination, debug_allocator)
|
||||||
stream,
|
}
|
||||||
_drtio_tuple,
|
Request::Flash => {
|
||||||
_destination,
|
let len = read_i32(stream).await?;
|
||||||
debug_allocator
|
if len <= 0 {
|
||||||
)
|
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(
|
pub fn start(cfg: Config, drtio_tuple: Option<(&Rc<Mutex<bool>>, &Rc<RefCell<RoutingTable>>, GlobalTimer)>) {
|
||||||
cfg: Config,
|
let drtio_tuple =
|
||||||
drtio_tuple: Option<(
|
drtio_tuple.map(|(aux_mutex, routing_table, timer)| (aux_mutex.clone(), routing_table.clone(), timer));
|
||||||
&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);
|
||||||
|
@ -891,12 +925,12 @@ pub fn start(
|
||||||
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.as_ref().map(
|
let drtio_tuple = drtio_tuple
|
||||||
|(aux_mutex, routing_table, timer)| (aux_mutex, routing_table.borrow(), *timer)
|
.as_ref()
|
||||||
);
|
.map(|(aux_mutex, routing_table, timer)| (aux_mutex, routing_table.borrow(), *timer));
|
||||||
let drtio_tuple = drtio_tuple.as_ref().map(
|
let drtio_tuple = drtio_tuple
|
||||||
|(aux_mutex, routing_table, timer)| (*aux_mutex, routing_table.deref(), *timer)
|
.as_ref()
|
||||||
);
|
.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));
|
||||||
|
|
|
@ -15,7 +15,9 @@ 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"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
#[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;
|
||||||
|
|
||||||
|
@ -1055,7 +1057,7 @@ fn process_aux_packet(
|
||||||
timer
|
timer
|
||||||
);
|
);
|
||||||
mgmt::clear_log();
|
mgmt::clear_log();
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtSetLogLevelRequest {
|
drtioaux::Packet::CoreMgmtSetLogLevelRequest {
|
||||||
destination: _destination,
|
destination: _destination,
|
||||||
|
@ -1075,9 +1077,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::CoreMgmtAck)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })
|
||||||
} else {
|
} else {
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtSetUartLogLevelRequest {
|
drtioaux::Packet::CoreMgmtSetUartLogLevelRequest {
|
||||||
|
@ -1103,9 +1105,9 @@ fn process_aux_packet(
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_uart_log_level(level_filter);
|
.set_uart_log_level(level_filter);
|
||||||
}
|
}
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })
|
||||||
} else {
|
} else {
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtConfigReadRequest {
|
drtioaux::Packet::CoreMgmtConfigReadRequest {
|
||||||
|
@ -1129,7 +1131,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::CoreMgmtNack)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
||||||
} 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() {
|
||||||
|
@ -1143,7 +1145,7 @@ fn process_aux_packet(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1189,19 +1191,15 @@ fn process_aux_packet(
|
||||||
timer
|
timer
|
||||||
);
|
);
|
||||||
|
|
||||||
core_manager.add_data(&data, length as usize);
|
core_manager.add_config_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_data();
|
core_manager.clear_config_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
if succeeded {
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded })
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
|
|
||||||
} else {
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtConfigRemoveRequest {
|
drtioaux::Packet::CoreMgmtConfigRemoveRequest {
|
||||||
destination: _destination,
|
destination: _destination,
|
||||||
|
@ -1222,14 +1220,11 @@ 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::CoreMgmtNack)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
||||||
} else {
|
} else {
|
||||||
let key = core::str::from_utf8(key_slice).unwrap();
|
let key = core::str::from_utf8(key_slice).unwrap();
|
||||||
if core_manager.remove_config(key).is_ok() {
|
let succeeded = core_manager.remove_config(key).is_ok();
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded })
|
||||||
} else {
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtConfigEraseRequest {
|
drtioaux::Packet::CoreMgmtConfigEraseRequest {
|
||||||
|
@ -1247,7 +1242,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::CoreMgmtNack)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtRebootRequest {
|
drtioaux::Packet::CoreMgmtRebootRequest {
|
||||||
destination: _destination,
|
destination: _destination,
|
||||||
|
@ -1264,10 +1259,11 @@ fn process_aux_packet(
|
||||||
timer
|
timer
|
||||||
);
|
);
|
||||||
|
|
||||||
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)?;
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true })?;
|
||||||
info!("reboot imminent");
|
info!("reboot imminent");
|
||||||
slcr::reboot();
|
slcr::reboot();
|
||||||
Ok(())
|
|
||||||
|
unreachable!();
|
||||||
}
|
}
|
||||||
drtioaux::Packet::CoreMgmtAllocatorDebugRequest {
|
drtioaux::Packet::CoreMgmtAllocatorDebugRequest {
|
||||||
destination: _destination,
|
destination: _destination,
|
||||||
|
@ -1284,7 +1280,54 @@ 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::CoreMgmtNack)
|
drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false })
|
||||||
|
}
|
||||||
|
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 => {
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use io::{Cursor, ProtoRead, ProtoWrite};
|
use byteorder::{ByteOrder, NativeEndian};
|
||||||
|
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::{self, debug, error, info, warn, LevelFilter};
|
use log::{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<log::LevelFilter> {
|
pub fn byte_to_level_filter(level_byte: u8) -> Result<LevelFilter> {
|
||||||
Ok(match level_byte {
|
Ok(match level_byte {
|
||||||
0 => log::LevelFilter::Off,
|
0 => LevelFilter::Off,
|
||||||
1 => log::LevelFilter::Error,
|
1 => LevelFilter::Error,
|
||||||
2 => log::LevelFilter::Warn,
|
2 => LevelFilter::Warn,
|
||||||
3 => log::LevelFilter::Info,
|
3 => LevelFilter::Info,
|
||||||
4 => log::LevelFilter::Debug,
|
4 => LevelFilter::Debug,
|
||||||
5 => log::LevelFilter::Trace,
|
5 => LevelFilter::Trace,
|
||||||
lv => {
|
lv => {
|
||||||
error!("unknown log level: {}", lv);
|
error!("unknown log level: {}", lv);
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -46,8 +48,9 @@ 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,
|
||||||
current_payload: Cursor<Vec<u8>>,
|
config_payload: Vec<u8>,
|
||||||
last_value: Sliceable,
|
last_value: Sliceable,
|
||||||
|
image_payload: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Manager<'_> {
|
impl<'a> Manager<'_> {
|
||||||
|
@ -55,8 +58,9 @@ impl<'a> Manager<'_> {
|
||||||
Manager {
|
Manager {
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
last_log: Sliceable::new(0, Vec::new()),
|
last_log: Sliceable::new(0, Vec::new()),
|
||||||
current_payload: Cursor::new(Vec::new()),
|
config_payload: Vec::new(),
|
||||||
last_value: Sliceable::new(0, Vec::new()),
|
last_value: Sliceable::new(0, Vec::new()),
|
||||||
|
image_payload: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,22 +87,19 @@ impl<'a> Manager<'_> {
|
||||||
self.last_value.get_slice_satellite(data_slice)
|
self.last_value.get_slice_satellite(data_slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_data(&mut self, data: &[u8], data_len: usize) {
|
pub fn add_config_data(&mut self, data: &[u8], data_len: usize) {
|
||||||
self.current_payload.write_all(&data[..data_len]).unwrap();
|
self.config_payload.write_all(&data[..data_len]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_data(&mut self) {
|
pub fn clear_config_data(&mut self) {
|
||||||
self.current_payload.get_mut().clear();
|
self.config_payload.clear();
|
||||||
self.current_payload.set_position(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_config(&mut self) -> Result<()> {
|
pub fn write_config(&mut self) -> Result<()> {
|
||||||
let key = self
|
let mut payload = &self.config_payload[..];
|
||||||
.current_payload
|
let key = payload.read_string().map_err(|_err| error!("error on reading key"))?;
|
||||||
.read_string()
|
|
||||||
.map_err(|_err| error!("error on reading key"))?;
|
|
||||||
debug!("write key: {}", key);
|
debug!("write key: {}", key);
|
||||||
let value = self.current_payload.read_bytes().unwrap();
|
let value = payload.read_bytes().unwrap();
|
||||||
|
|
||||||
self.cfg
|
self.cfg
|
||||||
.write(&key, value)
|
.write(&key, value)
|
||||||
|
@ -113,4 +114,32 @@ 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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue