mgmt: implemented config write
This commit is contained in:
parent
1695076baf
commit
7dbffadf08
@ -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
|
||||
------------------------
|
||||
|
@ -14,7 +14,7 @@ let
|
||||
name = "zc706-firmware";
|
||||
|
||||
src = ./src;
|
||||
cargoSha256 = "0hjpxqz9ilr4fxi3w3xswn9dcrsh3g2m42vig80xdkpb7wn9gvs0";
|
||||
cargoSha256 = "1hmhnwvkn3z7qw4z6lxhczjl9r402k7xpycp987fnw7rfrqj9cp7";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.gnumake
|
||||
|
14
src/Cargo.lock
generated
14
src/Cargo.lock
generated
@ -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",
|
||||
|
@ -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]
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user