forked from M-Labs/artiq
1
0
Fork 0

remote coremgmt: restart device gracefully after flashing

This commit is contained in:
occheung 2024-08-29 12:30:15 +08:00
parent b563533bc8
commit 67a2c63d2d
4 changed files with 46 additions and 19 deletions

View File

@ -143,6 +143,7 @@ pub enum Packet {
CoreMgmtConfigReadReply { last: bool, length: u16, value: [u8; SAT_PAYLOAD_MAX_SIZE] }, CoreMgmtConfigReadReply { last: bool, length: u16, value: [u8; SAT_PAYLOAD_MAX_SIZE] },
CoreMgmtAck, CoreMgmtAck,
CoreMgmtNack, CoreMgmtNack,
CoreMgmtRebootImminent,
} }
impl Packet { impl Packet {
@ -503,6 +504,7 @@ impl Packet {
}, },
0xdd => Packet::CoreMgmtAck, 0xdd => Packet::CoreMgmtAck,
0xde => Packet::CoreMgmtNack, 0xde => Packet::CoreMgmtNack,
0xdf => Packet::CoreMgmtRebootImminent,
ty => return Err(Error::UnknownPacket(ty)) ty => return Err(Error::UnknownPacket(ty))
}) })
@ -871,6 +873,7 @@ impl Packet {
}, },
Packet::CoreMgmtAck => writer.write_u8(0xdd)?, Packet::CoreMgmtAck => writer.write_u8(0xdd)?,
Packet::CoreMgmtNack => writer.write_u8(0xde)?, Packet::CoreMgmtNack => writer.write_u8(0xde)?,
Packet::CoreMgmtRebootImminent => writer.write_u8(0xdf)?,
} }
Ok(()) Ok(())
} }

View File

@ -352,6 +352,7 @@ mod remote_coremgmt {
destination: destination, length: len as u16, last: status.is_last(), data: *slice}); destination: destination, length: len as u16, last: status.is_last(), data: *slice});
match reply { match reply {
Ok(Packet::CoreMgmtAck) => Ok(()), Ok(Packet::CoreMgmtAck) => Ok(()),
Ok(Packet::CoreMgmtRebootImminent) if status.is_last() => Ok(()),
Ok(packet) => { Ok(packet) => {
error!("received unexpected aux packet: {:?}", packet); error!("received unexpected aux packet: {:?}", packet);
Err(drtio::Error::UnexpectedReply) Err(drtio::Error::UnexpectedReply)

View File

@ -556,17 +556,10 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
coremgr.add_data(&data, length as usize); coremgr.add_data(&data, length as usize);
let mut succeeded = true;
if last { if last {
succeeded = coremgr.write_config().is_ok(); coremgr.write_config()
debug!("Write succeeded: {}", succeeded);
coremgr.clear_data();
}
if succeeded {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} else { } else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack) drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} }
} }
drtioaux::Packet::CoreMgmtConfigRemoveRequest { destination: _destination, length, key } => { drtioaux::Packet::CoreMgmtConfigRemoveRequest { destination: _destination, length, key } => {

View File

@ -1,13 +1,12 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use routing::{Sliceable, SliceMeta}; use routing::{Sliceable, SliceMeta};
use board_misoc::config; use board_artiq::drtioaux;
use board_misoc::{clock, config, csr, spiflash};
use io::{Cursor, ProtoRead, ProtoWrite}; use io::{Cursor, ProtoRead, ProtoWrite};
use proto_artiq::drtioaux_proto::SAT_PAYLOAD_MAX_SIZE; use proto_artiq::drtioaux_proto::SAT_PAYLOAD_MAX_SIZE;
type Result<T> = core::result::Result<T, ()>;
pub struct Manager { pub struct Manager {
current_payload: Cursor<Vec<u8>>, current_payload: Cursor<Vec<u8>>,
last_value: Sliceable, last_value: Sliceable,
@ -21,7 +20,7 @@ impl Manager {
} }
} }
pub fn fetch_config_value(&mut self, key: &str) -> Result<()> { pub fn fetch_config_value(&mut self, key: &str) -> Result<(), ()> {
config::read(key, |result| result.map( config::read(key, |result| result.map(
|value| self.last_value = Sliceable::new(0, value.to_vec()) |value| self.last_value = Sliceable::new(0, value.to_vec())
)).map_err(|_err| warn!("read error: no such key")) )).map_err(|_err| warn!("read error: no such key"))
@ -40,13 +39,44 @@ impl Manager {
self.current_payload.set_position(0); self.current_payload.set_position(0);
} }
pub fn write_config(&mut self) -> Result<()> { pub fn write_config(&mut self) -> Result<(), drtioaux::Error<!>> {
let key = self.current_payload.read_string().map_err( let key = match self.current_payload.read_string() {
|err| error!("error on reading key: {:?}", err))?; Ok(key) => key,
Err(err) => {
self.clear_data();
error!("error on reading key: {:?}", err);
return drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack);
}
};
let value = self.current_payload.read_bytes().unwrap(); let value = self.current_payload.read_bytes().unwrap();
config::write(&key, &value).map_err(|err| { match key.as_str() {
"gateware" | "bootloader" | "firmware" => {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtRebootImminent)?;
#[cfg(not(soc_platform = "efc"))]
unsafe {
clock::spin_us(10000);
csr::gt_drtio::txenable_write(0);
}
config::write(&key, &value).expect("failed to write to flash storage");
warn!("restarting");
unsafe { spiflash::reload(); }
}
_ => {
let succeeded = config::write(&key, &value).map_err(|err| {
error!("error on writing config: {:?}", err); error!("error on writing config: {:?}", err);
}) }).is_ok();
self.clear_data();
if succeeded {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtAck)
} else {
drtioaux::send(0, &drtioaux::Packet::CoreMgmtNack)
}
}
}
} }
} }