diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 8e265999e..9513f1a81 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -21,6 +21,7 @@ use board_artiq::si5324; use board_artiq::si549; #[cfg(soc_platform = "kasli")] use board_misoc::irq; +use board_misoc::spiflash; use board_artiq::{spi, drtioaux, drtio_routing}; #[cfg(soc_platform = "efc")] use board_artiq::ad9117; @@ -30,6 +31,7 @@ use board_artiq::drtio_eem; use riscv::register::{mcause, mepc, mtval}; use dma::Manager as DmaManager; use kernel::Manager as KernelManager; +use mgmt::Manager as CoreManager; use analyzer::Analyzer; #[global_allocator] @@ -41,6 +43,7 @@ mod dma; mod analyzer; mod kernel; mod cache; +mod mgmt; fn drtiosat_reset(reset: bool) { unsafe { @@ -129,7 +132,7 @@ macro_rules! forward { ($router:expr, $routing_table:expr, $destination:expr, $rank:expr, $self_destination:expr, $repeaters:expr, $packet:expr) => {} } -fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmgr: &mut KernelManager, +fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmgr: &mut KernelManager, coremgr: &mut CoreManager, _repeaters: &mut [repeater::Repeater], _routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8, router: &mut routing::Router, self_destination: &mut u8, packet: drtioaux::Packet ) -> Result<(), drtioaux::Error> { @@ -495,6 +498,105 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg Ok(()) } + drtioaux::Packet::CoreMgmtGetLogRequest { destination: _destination, .. } | + drtioaux::Packet::CoreMgmtClearLogRequest { destination: _destination } | + drtioaux::Packet::CoreMgmtSetLogLevelRequest {destination: _destination, .. } => { + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); + + error!("RISC-V satellite devices do not support buffered logging"); + drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack) + } + drtioaux::Packet::CoreMgmtSetUartLogLevelRequest { destination: _destination, .. } => { + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); + + error!("RISC-V satellite devices has fixed UART log level fixed at TRACE"); + drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack) + } + drtioaux::Packet::CoreMgmtConfigReadRequest { + destination: _destination, + length, + key, + } => { + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); + + let mut value_slice = [0; SAT_PAYLOAD_MAX_SIZE]; + + let key_slice = &key[..length as usize]; + if !key_slice.is_ascii() { + error!("invalid key"); + drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack) + } else { + let key = core::str::from_utf8(key_slice).unwrap(); + if coremgr.fetch_config_value(key).is_ok() { + let meta = coremgr.get_config_value_slice(&mut value_slice); + drtioaux::send( + 0, + &drtioaux::Packet::CoreMgmtConfigReadReply { + length: meta.len as u16, + last: meta.status.is_last(), + value: value_slice, + }, + ) + } else { + drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack) + } + } + } + drtioaux::Packet::CoreMgmtConfigReadContinue { + destination: _destination, + } => { + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); + + let mut value_slice = [0; SAT_PAYLOAD_MAX_SIZE]; + let meta = coremgr.get_config_value_slice(&mut value_slice); + drtioaux::send( + 0, + &drtioaux::Packet::CoreMgmtConfigReadReply { + length: meta.len as u16, + last: meta.status.is_last(), + value: value_slice, + }, + ) + } + drtioaux::Packet::CoreMgmtConfigWriteRequest { destination: _destination, length, last, data } => { + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); + + coremgr.add_data(&data, length as usize); + let mut succeeded = true; + if last { + succeeded = coremgr.write_config().is_ok(); + debug!("Write succeeded: {}", succeeded); + coremgr.clear_data(); + } + + if succeeded { + drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck) + } else { + drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack) + } + } + drtioaux::Packet::CoreMgmtConfigRemoveRequest { destination: _destination, length, key } => { + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); + + let key = core::str::from_utf8(&key[..length as usize]).unwrap(); + let succeeded = config::remove(key) + .map_err(|err| warn!("error on removing config: {:?}", err)) + .is_ok(); + + if succeeded { + drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck) + } else { + drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack) + } + } + drtioaux::Packet::CoreMgmtRebootRequest { destination: _destination } => { + forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); + + drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)?; + warn!("restarting"); + unsafe { spiflash::reload(); } + } + _ => { warn!("received unexpected aux packet"); Ok(()) @@ -503,13 +605,13 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg } fn process_aux_packets(dma_manager: &mut DmaManager, analyzer: &mut Analyzer, - kernelmgr: &mut KernelManager, repeaters: &mut [repeater::Repeater], + kernelmgr: &mut KernelManager, coremgr: &mut CoreManager, repeaters: &mut [repeater::Repeater], routing_table: &mut drtio_routing::RoutingTable, rank: &mut u8, router: &mut routing::Router, destination: &mut u8) { let result = drtioaux::recv(0).and_then(|packet| { if let Some(packet) = packet.or_else(|| router.get_local_packet()) { - process_aux_packet(dma_manager, analyzer, kernelmgr, + process_aux_packet(dma_manager, analyzer, kernelmgr, coremgr, repeaters, routing_table, rank, router, destination, packet) } else { Ok(()) @@ -834,6 +936,7 @@ pub extern fn main() -> i32 { let mut dma_manager = DmaManager::new(); let mut analyzer = Analyzer::new(); let mut kernelmgr = KernelManager::new(); + let mut coremgr = CoreManager::new(); cricon_select(RtioMaster::Drtio); drtioaux::reset(0); @@ -843,7 +946,7 @@ pub extern fn main() -> i32 { while drtiosat_link_rx_up() { drtiosat_process_errors(); process_aux_packets(&mut dma_manager, &mut analyzer, - &mut kernelmgr, &mut repeaters, &mut routing_table, + &mut kernelmgr, &mut coremgr, &mut repeaters, &mut routing_table, &mut rank, &mut router, &mut destination); for rep in repeaters.iter_mut() { rep.service(&routing_table, rank, destination, &mut router); diff --git a/artiq/firmware/satman/mgmt.rs b/artiq/firmware/satman/mgmt.rs new file mode 100644 index 000000000..01c64dcef --- /dev/null +++ b/artiq/firmware/satman/mgmt.rs @@ -0,0 +1,52 @@ +use alloc::vec::Vec; + +use routing::{Sliceable, SliceMeta}; +use board_misoc::config; +use io::{Cursor, ProtoRead, ProtoWrite}; +use proto_artiq::drtioaux_proto::SAT_PAYLOAD_MAX_SIZE; + + +type Result = core::result::Result; + +pub struct Manager { + current_payload: Cursor>, + last_value: Sliceable, +} + +impl Manager { + pub fn new() -> Manager { + Manager { + current_payload: Cursor::new(Vec::new()), + last_value: Sliceable::new(0, Vec::new()), + } + } + + pub fn fetch_config_value(&mut self, key: &str) -> Result<()> { + config::read(key, |result| result.map( + |value| self.last_value = Sliceable::new(0, value.to_vec()) + )).map_err(|_err| warn!("read error: no such key")) + } + + pub fn get_config_value_slice(&mut self, data_slice: &mut [u8; SAT_PAYLOAD_MAX_SIZE]) -> SliceMeta { + self.last_value.get_slice_sat(data_slice) + } + + pub fn add_data(&mut self, data: &[u8], data_len: usize) { + self.current_payload.write_all(&data[..data_len]).unwrap(); + } + + pub fn clear_data(&mut self) { + self.current_payload.get_mut().clear(); + self.current_payload.set_position(0); + } + + pub fn write_config(&mut self) -> Result<()> { + let key = self.current_payload.read_string().map_err( + |err| error!("error on reading key: {:?}", err))?; + let value = self.current_payload.read_bytes().unwrap(); + + config::write(&key, &value).map_err(|err| { + error!("error on writing config: {:?}", err); + }) + } +} \ No newline at end of file