mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-08 04:56:43 +00:00
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.
This commit is contained in:
parent
8192c68a63
commit
061284ec5f
9 changed files with 90 additions and 12 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<u8>,
|
||||
/// if this register should be in the suspend/resume set
|
||||
do_sr: bool,
|
||||
}
|
||||
|
||||
/* sketching some structs for suspend/resume */
|
||||
struct TicktimerSusres {
|
||||
csr: utralib::CSR<u32>, // new(csr_base) will allocate this register, from the virtual CSR base given to us by the owning server
|
||||
pub control: Option<u32>,
|
||||
pub time1: Option<u32>,
|
||||
pub time0: Option<u32>,
|
||||
pub resume_time1: Option<u32>,
|
||||
pub resume_time0: Option<u32>,
|
||||
pub status: Option<u32>,
|
||||
pub msleep_target1: Option<u32>,
|
||||
pub msleep_target0: Option<u32>,
|
||||
pub ev_status: Option<u32>,
|
||||
pub ev_pending: Option<u32>,
|
||||
pub ev_enable: Option<u32>,
|
||||
pub ticktimer_irq: Option<bool>, // whether to enable or not after resume
|
||||
pub wait_suspend: Option<fn(timeout: u32) -> 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;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<device schemaVersion="1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" >
|
||||
<vendor>litex</vendor>
|
||||
<name>SOC</name>
|
||||
<description><![CDATA[Litex SoC 2021-04-22 23:47:54]]></description>
|
||||
<description><![CDATA[Litex SoC 2021-04-23 13:47:43]]></description>
|
||||
|
||||
<addressUnitBits>8</addressUnitBits>
|
||||
<width>32</width>
|
||||
|
|
@ -1070,10 +1070,10 @@ register to disable individual events.]]></description>
|
|||
<register>
|
||||
<name>GIT_GITREV</name>
|
||||
<description><![CDATA[First 32-bits of the git revision. This documentation was built from git rev
|
||||
``b9a1ecab``, so this value is 3114396843, which should be enough to check out
|
||||
``4878d3c3``, so this value is 1215878083, which should be enough to check out
|
||||
the exact git version used to build this firmware.]]></description>
|
||||
<addressOffset>0x0014</addressOffset>
|
||||
<resetValue>0xb9a1ecab</resetValue>
|
||||
<resetValue>0x4878d3c3</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
|
|
@ -1090,7 +1090,7 @@ the exact git version used to build this firmware.]]></description>
|
|||
is ``1``, then the repository this was built from has one additional commit
|
||||
beyond the tag indicated in `MAJOR`, `MINOR`, and `REVISION`.]]></description>
|
||||
<addressOffset>0x0018</addressOffset>
|
||||
<resetValue>0x1d</resetValue>
|
||||
<resetValue>0x1f</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
|
|
@ -3086,7 +3086,7 @@ inject too fast.]]></description>
|
|||
<name>SEED1</name>
|
||||
<description><![CDATA[Bits 32-63 of `SEED_SEED`. Seed used for the build]]></description>
|
||||
<addressOffset>0x0000</addressOffset>
|
||||
<resetValue>0x1976d1a8</resetValue>
|
||||
<resetValue>0x5073fcc9</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
|
|
@ -3101,7 +3101,7 @@ inject too fast.]]></description>
|
|||
<name>SEED0</name>
|
||||
<description><![CDATA[Bits 0-31 of `SEED_SEED`.]]></description>
|
||||
<addressOffset>0x0004</addressOffset>
|
||||
<resetValue>0x8576398</resetValue>
|
||||
<resetValue>0x627a019a</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
|
|
|
|||
Loading…
Reference in a new issue