diff --git a/services/com/src/lib.rs b/services/com/src/lib.rs index 97292e0b5..f2ad850ad 100644 --- a/services/com/src/lib.rs +++ b/services/com/src/lib.rs @@ -59,10 +59,16 @@ impl Com { ).map(|_| ()) } + /// ship mode is synchronous, so that we can schedule order-of-operation dependent tasks around it pub fn ship_mode(&self) -> Result<(), xous::Error> { - send_message(self.conn, - Message::new_scalar(Opcode::ShipMode.to_usize().unwrap(), 0, 0, 0, 0) - ).map(|_| ()) + let response = send_message(self.conn, + Message::new_blocking_scalar(Opcode::ShipMode.to_usize().unwrap(), 0, 0, 0, 0))?; + if let xous::Result::Scalar1(_) = response { + Ok(()) + } else { + log::error!("ship_mode failed to execute"); + Err(xous::Error::InternalError) + } } pub fn get_wf200_fw_rev(&self) -> Result<(u8, u8, u8), xous::Error> { diff --git a/services/com/src/main.rs b/services/com/src/main.rs index b20e5db20..0f59c61d7 100644 --- a/services/com/src/main.rs +++ b/services/com/src/main.rs @@ -350,6 +350,8 @@ fn xmain() -> ! { } Some(Opcode::ShipMode) => { com.txrx(ComState::POWER_SHIPMODE.verb); + xous::return_scalar(msg.sender, 1) + .expect("couldn't ack ship mode"); } Some(Opcode::Wf200Rev) => { com.txrx(ComState::WFX_FW_REV_GET.verb); diff --git a/services/llio/src/main.rs b/services/llio/src/main.rs index 9ec54518a..05cb81935 100644 --- a/services/llio/src/main.rs +++ b/services/llio/src/main.rs @@ -344,6 +344,7 @@ mod implementation { } pub fn self_destruct(&mut self, code: u32) { if self.destruct_armed && code == 0x3141_5926 { + self.ticktimer.sleep_ms(100).unwrap(); // give a moment for any last words (like clearing the screen, powering down, etc.) self.power_csr.rmwf(utra::power::POWER_SELFDESTRUCT, 1); } else if !self.destruct_armed && code == 0x2718_2818 { self.destruct_armed = true; diff --git a/services/shellchat/src/cmds/sleep.rs b/services/shellchat/src/cmds/sleep.rs index eef063aca..3efd80a10 100644 --- a/services/shellchat/src/cmds/sleep.rs +++ b/services/shellchat/src/cmds/sleep.rs @@ -14,20 +14,26 @@ impl Sleep { } } -fn kill_thread() { +fn kill_thread(bounce: usize) { log::info!("Self destruct thread active."); let xns = xous_names::XousNames::new().unwrap(); let llio = llio::Llio::new(&xns).unwrap(); + let com = com::Com::new(&xns).unwrap(); let ticktimer = ticktimer_server::Ticktimer::new().unwrap(); ticktimer.sleep_ms(3000).unwrap(); loop { log::info!("Initiating self destruct sequence..."); + if bounce != 0 { + // slip in a ship mode command. should take long enough to execute that the kill goes through + com.ship_mode().unwrap(); + ticktimer.sleep_ms(100).unwrap(); + } llio.self_destruct(0x2718_2818).unwrap(); - ticktimer.sleep_ms(10).unwrap(); llio.self_destruct(0x3141_5926).unwrap(); - ticktimer.sleep_ms(10).unwrap(); + com.power_off_soc().unwrap(); + ticktimer.sleep_ms(100).unwrap(); log::info!("If you can read this, we failed to destroy ourselves!"); } } @@ -39,7 +45,7 @@ impl<'a> ShellCmdApi<'a> for Sleep { use core::fmt::Write; let mut ret = String::<1024>::new(); - let helpstring = "sleep [now] [current] [ship] [kill] [coldboot]"; + let helpstring = "sleep [now] [current] [ship] [kill] [coldboot] [killbounce]"; let mut tokens = args.as_str().unwrap().split(' '); @@ -129,7 +135,16 @@ impl<'a> ShellCmdApi<'a> for Sleep { } "kill" => { write!(ret, "Killing this device in 3 seconds.\nGoodbye cruel world!").unwrap(); - xous::create_thread_0(kill_thread).unwrap(); + xous::create_thread_1(kill_thread, 0).unwrap(); + } + "killbounce" => { + if ((env.llio.adc_vbus().unwrap() as f64) * 0.005033) > 1.5 { + // if power is plugged in, deny powerdown request + write!(ret, "Unplug charging cable and try again.").unwrap(); + } else { + write!(ret, "Killing this device in 3 seconds, then bouncing into ship mode\n").unwrap(); + xous::create_thread_1(kill_thread, 1).unwrap(); + } } _ => write!(ret, "{}", helpstring).unwrap(), }