mgmt: implemented config write

exception
pca006132 2020-10-30 16:59:24 +08:00
parent 1695076baf
commit 7dbffadf08
7 changed files with 102 additions and 18 deletions

View File

@ -25,6 +25,10 @@ The following configuration keys are available:
- ``ip6``: IPv6 address.
- ``startup``: startup kernel in ELF format (as produced by ``artiq_compile``).
- ``rtioclk``: source of RTIO clock; valid values are ``external`` and ``internal``.
- ``boot``: SD card "boot.bin" file, for replacing the boot firmware/gateware. Write only.
Configurations can be read/written/removed via ``artiq_coremgmt``. Config erase is
not implemented as it seems not very useful.
Development instructions
------------------------

View File

@ -14,7 +14,7 @@ let
name = "zc706-firmware";
src = ./src;
cargoSha256 = "0hjpxqz9ilr4fxi3w3xswn9dcrsh3g2m42vig80xdkpb7wn9gvs0";
cargoSha256 = "1hmhnwvkn3z7qw4z6lxhczjl9r402k7xpycp987fnw7rfrqj9cp7";
nativeBuildInputs = [
pkgs.gnumake

14
src/Cargo.lock generated
View File

@ -56,7 +56,7 @@ checksum = "e3fcd8aba10d17504c87ef12d4f62ef404c6a4703d16682a9eb5543e6cf24455"
[[package]]
name = "core_io"
version = "0.1.20200410"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#0efc7a616f90f1fdc495f7d112d1b3d2f604c3a8"
dependencies = [
"memchr",
]
@ -186,7 +186,7 @@ dependencies = [
[[package]]
name = "libasync"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#0efc7a616f90f1fdc495f7d112d1b3d2f604c3a8"
dependencies = [
"embedded-hal",
"libcortex_a9",
@ -198,7 +198,7 @@ dependencies = [
[[package]]
name = "libboard_zynq"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#0efc7a616f90f1fdc495f7d112d1b3d2f604c3a8"
dependencies = [
"bit_field",
"embedded-hal",
@ -222,7 +222,7 @@ dependencies = [
[[package]]
name = "libconfig"
version = "0.1.0"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#0efc7a616f90f1fdc495f7d112d1b3d2f604c3a8"
dependencies = [
"core_io",
"fatfs",
@ -233,7 +233,7 @@ dependencies = [
[[package]]
name = "libcortex_a9"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#0efc7a616f90f1fdc495f7d112d1b3d2f604c3a8"
dependencies = [
"bit_field",
"libregister",
@ -249,7 +249,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
[[package]]
name = "libregister"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#0efc7a616f90f1fdc495f7d112d1b3d2f604c3a8"
dependencies = [
"bit_field",
"vcell",
@ -259,7 +259,7 @@ dependencies = [
[[package]]
name = "libsupport_zynq"
version = "0.0.0"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#6266d280951c3fe5d4963a4b1ca45ce369d6b773"
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#0efc7a616f90f1fdc495f7d112d1b3d2f604c3a8"
dependencies = [
"compiler_builtins",
"libboard_zynq",

View File

@ -6,7 +6,7 @@ authors = ["M-Labs"]
edition = "2018"
[features]
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706"]
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
default = ["target_zc706"]
[dependencies]

View File

@ -343,8 +343,8 @@ async fn handle_connection(stream: &TcpStream, control: Rc<RefCell<kernel::Contr
}
}
pub fn main(timer: GlobalTimer, cfg: &Config) {
let net_addresses = net_settings::get_adresses(cfg);
pub fn main(timer: GlobalTimer, cfg: Config) {
let net_addresses = net_settings::get_adresses(&cfg);
info!("network addresses: {}", net_addresses);
let eth = zynq::eth::Eth::eth0(net_addresses.hardware_addr.0.clone());
@ -384,7 +384,6 @@ pub fn main(timer: GlobalTimer, cfg: &Config) {
Sockets::init(32);
mgmt::start();
analyzer::start();
moninj::start(timer);
@ -401,6 +400,8 @@ pub fn main(timer: GlobalTimer, cfg: &Config) {
}
}
mgmt::start(cfg);
task::spawn(async move {
let connection = Rc::new(Semaphore::new(1, 1));
let terminate = Rc::new(Semaphore::new(0, 1));

View File

@ -192,5 +192,5 @@ pub fn main_core0() {
init_rtio(&mut timer, &cfg);
task::spawn(report_async_rtio_errors());
comms::main(timer, &cfg);
comms::main(timer, cfg);
}

View File

@ -1,9 +1,10 @@
use futures::{future::poll_fn, task::Poll};
use libasync::{smoltcp::TcpStream, task};
use libboard_zynq::smoltcp;
use libconfig::Config;
use core::cell::RefCell;
use alloc::rc::Rc;
use log::{self, info, warn, LevelFilter};
use alloc::{rc::Rc, vec::Vec, string::String};
use log::{self, info, debug, warn, error, LevelFilter};
use crate::logger::{BufferLogger, LogBufferRef};
use crate::proto_async::*;
@ -44,12 +45,18 @@ pub enum Request {
PullLog = 7,
SetLogFilter = 3,
SetUartLogFilter = 6,
ConfigRead = 12,
ConfigWrite = 13,
ConfigRemove = 14,
}
#[repr(i8)]
pub enum Reply {
Success = 1,
LogContent = 2,
Error = 6,
ConfigData = 7,
}
async fn read_log_level_filter(stream: &mut TcpStream) -> Result<log::LevelFilter> {
@ -85,7 +92,28 @@ async fn get_logger_buffer() -> LogBufferRef<'static> {
get_logger_buffer_pred(|_| true).await
}
async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) -> Result<()> {
async fn read_key(stream: &mut TcpStream) -> Result<String> {
let len = read_i32(stream).await?;
if len <= 0 {
write_i8(stream, Reply::Error as i8).await?;
return Err(Error::UnexpectedPattern);
}
let mut buffer = Vec::with_capacity(len as usize);
for _ in 0..len {
buffer.push(0);
}
read_chunk(stream, &mut buffer).await?;
if !buffer.is_ascii() {
write_i8(stream, Reply::Error as i8).await?;
return Err(Error::UnexpectedPattern);
}
Ok(String::from_utf8(buffer).unwrap())
}
async fn handle_connection(
stream: &mut TcpStream,
pull_id: Rc<RefCell<u32>>,
cfg: Rc<Config>) -> Result<()> {
if !expect(&stream, b"ARTIQ management\n").await? {
return Err(Error::UnexpectedPattern);
}
@ -150,19 +178,70 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
}
write_i8(stream, Reply::Success as i8).await?;
}
Request::ConfigRead => {
let key = read_key(stream).await?;
debug!("read key: {}", key);
let value = cfg.read(&key);
if let Ok(value) = value {
debug!("got value");
write_i8(stream, Reply::ConfigData as i8).await?;
write_chunk(stream, &value).await?;
} else {
warn!("read error: no such key");
write_i8(stream, Reply::Error as i8).await?;
}
},
Request::ConfigWrite => {
let key = read_key(stream).await?;
warn!("write key: {}", key);
let len = read_i32(stream).await?;
let len = if len <= 0 {
0
} else {
len as usize
};
let mut buffer = Vec::with_capacity(len);
unsafe {
buffer.set_len(len);
}
read_chunk(stream, &mut buffer).await?;
let value = cfg.write(&key, buffer);
if value.is_ok() {
debug!("write success");
write_i8(stream, Reply::Success as i8).await?;
} else {
// this is an error because we do not expect write to fail
error!("failed to write: {:?}", value);
write_i8(stream, Reply::Error as i8).await?;
}
},
Request::ConfigRemove => {
let key = read_key(stream).await?;
debug!("erase key: {}", key);
let value = cfg.remove(&key);
if value.is_ok() {
debug!("erase success");
write_i8(stream, Reply::Success as i8).await?;
} else {
warn!("erase failed");
write_i8(stream, Reply::Error as i8).await?;
}
}
}
}
}
pub fn start() {
pub fn start(cfg: Config) {
task::spawn(async move {
let pull_id = Rc::new(RefCell::new(0u32));
let cfg = Rc::new(cfg);
loop {
let mut stream = TcpStream::accept(1380, 2048, 2048).await.unwrap();
let pull_id = pull_id.clone();
let cfg = cfg.clone();
task::spawn(async move {
info!("received connection");
let _ = handle_connection(&mut stream, pull_id)
let _ = handle_connection(&mut stream, pull_id, cfg)
.await
.map_err(|e| warn!("connection terminated: {:?}", e));
let _ = stream.flush().await;