From 061284ec5f5eab42b830fc86a79a5a8a33c6a373 Mon Sep 17 00:00:00 2001 From: bunnie Date: Fri, 23 Apr 2021 15:33:14 +0800 Subject: [PATCH] debugging BOOST mode glitch issue Here's an arcane bug for you: When powering down, the Spartan 7 3.3V I/O drivers will output a roughly 800us wide glitch as 3.3V falls below around 1.7V, if the 0.95V core voltage comes down first (which it does because we have an active discharge on 0.95V, but not on 3.3V). In this case, it's just wide and high enough to cause the BOOST mode line to engage, which takes the BOOST output and ties it to VBUS, which is just enough for the system to think you're powering it back on again. Which is not what you want when powering down. The ultimate fix was to put a heftier pull-down on the BOOST line so that it can't trip the BOOST output into the VBUS. Another option could be more active discharge FETs, but that would require a full board spin and we are already at certification, so we'll stick with the stronger pull-down on BOOST. It seems to be a robust fix in the worst corner cases we can find. The downside is that when powering an external USB device, you are burning an extra 30mW of power overcoming the pull-down, but typically, any external USB devices plugged into Precursor will burn far in excess of that, so the delta should be negligible. --- services/com/src/api.rs | 4 +-- services/com/src/lib.rs | 8 +++++ services/com/src/main.rs | 6 ++++ services/llio/src/lib.rs | 12 +++++++ services/llio/src/main.rs | 4 +-- services/rtc/src/main.rs | 2 +- services/shellchat/src/cmds/sleep.rs | 9 +++++- services/ticktimer-server/src/main.rs | 45 +++++++++++++++++++++++++++ svd2utra/examples/soc.svd | 12 +++---- 9 files changed, 90 insertions(+), 12 deletions(-) diff --git a/services/com/src/api.rs b/services/com/src/api.rs index b024a945f..15397a6bd 100644 --- a/services/com/src/api.rs +++ b/services/com/src/api.rs @@ -50,10 +50,10 @@ pub(crate) enum Opcode { //BattFullCapacity, /// Turn Boost Mode On - //BoostOn, + BoostOn, /// Turn Boost Mode Off - //BoostOff, + BoostOff, /// Read the current accelerations off the IMU //ImuAccelRead, diff --git a/services/com/src/lib.rs b/services/com/src/lib.rs index f2ad850ad..663c8e3b6 100644 --- a/services/com/src/lib.rs +++ b/services/com/src/lib.rs @@ -181,6 +181,14 @@ impl Com { Err(xous::Error::InternalError) } } + + pub fn set_boost(&self, on: bool) -> Result<(), xous::Error> { + if on { + send_message(self.conn, Message::new_scalar(Opcode::BoostOn.to_usize().unwrap(), 0, 0, 0, 0,)).map(|_| ()) + } else { + send_message(self.conn, Message::new_scalar(Opcode::BoostOff.to_usize().unwrap(), 0, 0, 0, 0,)).map(|_| ()) + } + } // note to future self: add other event listener registrations (such as network events) here } diff --git a/services/com/src/main.rs b/services/com/src/main.rs index 0f59c61d7..de06de232 100644 --- a/services/com/src/main.rs +++ b/services/com/src/main.rs @@ -328,6 +328,12 @@ fn xmain() -> ! { com.txrx(ComState::POWER_OFF.verb); com.wait_txrx(ComState::LINK_READ.verb, Some(STD_TIMEOUT)); // consume the obligatory return value, even if not used } + Some(Opcode::BoostOff) => { + com.txrx(ComState::CHG_BOOST_OFF.verb); + } + Some(Opcode::BoostOn) => { + com.txrx(ComState::CHG_BOOST_ON.verb); + } Some(Opcode::BattStats) => { info!("batt stats request received"); let stats = com.get_battstats(); diff --git a/services/llio/src/lib.rs b/services/llio/src/lib.rs index b28c10f21..1cfae641e 100644 --- a/services/llio/src/lib.rs +++ b/services/llio/src/lib.rs @@ -293,6 +293,18 @@ impl Llio { Message::new_scalar(Opcode::SelfDestruct.to_usize().unwrap(), code, 0, 0, 0) ).map(|_| ()) } + pub fn boost_on(&self, ena: bool) -> Result<(), xous::Error> { + let arg = if ena { 1 } else { 0 }; + send_message(self.conn, + Message::new_scalar(Opcode::PowerBoostMode.to_usize().unwrap(), arg, 0, 0, 0) + ).map(|_| ()) + } + pub fn audio_on(&self, ena: bool) -> Result<(), xous::Error> { + let arg = if ena { 1 } else { 0 }; + send_message(self.conn, + Message::new_scalar(Opcode::PowerAudio.to_usize().unwrap(), arg, 0, 0, 0) + ).map(|_| ()) + } } diff --git a/services/llio/src/main.rs b/services/llio/src/main.rs index 05cb81935..856d70514 100644 --- a/services/llio/src/main.rs +++ b/services/llio/src/main.rs @@ -320,8 +320,8 @@ mod implementation { self.power_csr.rmwf(utra::power::POWER_SELF, 0); } } - pub fn power_boost_mode(&mut self, power_on: bool) { - if power_on { + pub fn power_boost_mode(&mut self, boost_on: bool) { + if boost_on { self.power_csr.rmwf(utra::power::POWER_BOOSTMODE, 1); } else { self.power_csr.rmwf(utra::power::POWER_BOOSTMODE, 0); diff --git a/services/rtc/src/main.rs b/services/rtc/src/main.rs index a1f18a216..da9154edc 100644 --- a/services/rtc/src/main.rs +++ b/services/rtc/src/main.rs @@ -384,7 +384,7 @@ mod implementation { self.blocking_i2c_write2([ABRTCMC_CONTROL2, control2]); // turn on the timer proper -- the system will wakeup in 5..4..3.... - let mut config = (Config::CLKOUT_DISABLE | Config::TIMER_B_ENABLE | Config::TIMERB_INT_PULSED).bits(); + let mut config = (Config::CLKOUT_DISABLE | Config::TIMER_B_ENABLE).bits(); if self.rtc_alarm_enabled { config |= (Config::TIMER_A_COUNTDWN | Config::TIMERA_SECONDS_INT_PULSED).bits(); } diff --git a/services/shellchat/src/cmds/sleep.rs b/services/shellchat/src/cmds/sleep.rs index 3efd80a10..8d32ff00c 100644 --- a/services/shellchat/src/cmds/sleep.rs +++ b/services/shellchat/src/cmds/sleep.rs @@ -49,6 +49,13 @@ impl<'a> ShellCmdApi<'a> for Sleep { let mut tokens = args.as_str().unwrap().split(' '); + // try powering on the audio block to help to discharge the 3.3VA line + env.llio.audio_on(true).unwrap(); + + // in all cases, we want the boost to be off to ensure a clean shutdown + env.com.set_boost(false).unwrap(); + env.llio.boost_on(false).unwrap(); + if let Some(sub_cmd) = tokens.next() { match sub_cmd { "now" => { @@ -116,7 +123,7 @@ impl<'a> ShellCmdApi<'a> for Sleep { env.ticktimer.sleep_ms(500).unwrap(); // let the screen redraw // set a wakeup alarm a couple seconds from now -- this is the coldboot - self.rtc.set_wakeup_alarm(3).unwrap(); + self.rtc.set_wakeup_alarm(4).unwrap(); // allow EC to snoop, so that it can wake up the system env.llio.allow_ec_snoop(true).unwrap(); diff --git a/services/ticktimer-server/src/main.rs b/services/ticktimer-server/src/main.rs index f0e1cdefe..f60952fb3 100644 --- a/services/ticktimer-server/src/main.rs +++ b/services/ticktimer-server/src/main.rs @@ -52,6 +52,51 @@ impl core::cmp::PartialEq for SleepRequest { } } +/* +// "suspend/resume u32" +struct SrU32 { + /// offset of the register + offset: crate::Register, + /// the saved value of the register + value: u32, + /// the order in which this register should be written. If none, it's written at any convenient time. + resume_order: Option, + /// if this register should be in the suspend/resume set + do_sr: bool, +} + +/* sketching some structs for suspend/resume */ +struct TicktimerSusres { + csr: utralib::CSR, // new(csr_base) will allocate this register, from the virtual CSR base given to us by the owning server + pub control: Option, + pub time1: Option, + pub time0: Option, + pub resume_time1: Option, + pub resume_time0: Option, + pub status: Option, + pub msleep_target1: Option, + pub msleep_target0: Option, + pub ev_status: Option, + pub ev_pending: Option, + pub ev_enable: Option, + pub ticktimer_irq: Option, // whether to enable or not after resume + pub wait_suspend: Option bool>, // function to call to check if a block can suspend +} +pub trait SuspendResume { + pub fn suspend(&mut self) { + /* + go through each item of the structure, and if the item is Some(item), access the corresponding + register and save it into the register + */ + } + pub fn resume(&mut self) { + /* + go through each item of the stucture, and if the item is Some(item), unwrap the value and + poke it into the register + */ + } +} +*/ #[cfg(target_os = "none")] mod implementation { const TICKS_PER_MS: u64 = 1; diff --git a/svd2utra/examples/soc.svd b/svd2utra/examples/soc.svd index 21ed34663..52f10e91c 100644 --- a/svd2utra/examples/soc.svd +++ b/svd2utra/examples/soc.svd @@ -3,7 +3,7 @@ litex SOC - + 8 32 @@ -1070,10 +1070,10 @@ register to disable individual events.]]> GIT_GITREV 0x0014 - 0xb9a1ecab + 0x4878d3c3 32 @@ -1090,7 +1090,7 @@ the exact git version used to build this firmware.]]> is ``1``, then the repository this was built from has one additional commit beyond the tag indicated in `MAJOR`, `MINOR`, and `REVISION`.]]> 0x0018 - 0x1d + 0x1f 32 @@ -3086,7 +3086,7 @@ inject too fast.]]> SEED1 0x0000 - 0x1976d1a8 + 0x5073fcc9 32 @@ -3101,7 +3101,7 @@ inject too fast.]]> SEED0 0x0004 - 0x8576398 + 0x627a019a 32