mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
very basic battery monitoring via COM
This commit is contained in:
parent
471befa970
commit
d583e20b18
8 changed files with 220 additions and 150 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -142,6 +142,8 @@ dependencies = [
|
|||
"heapless",
|
||||
"log",
|
||||
"log-server",
|
||||
"ticktimer-server",
|
||||
"typenum",
|
||||
"utralib",
|
||||
"xous",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -12,68 +12,9 @@
|
|||
<resetMask>0xFFFFFFFF</resetMask>
|
||||
|
||||
<peripherals>
|
||||
<peripheral>
|
||||
<name>CTRL</name>
|
||||
<baseAddress>0xF0000000</baseAddress>
|
||||
<groupName>CTRL</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
<name>RESET</name>
|
||||
<description><![CDATA[Write a ``1`` to this register to reset the SoC.]]></description>
|
||||
<addressOffset>0x0000</addressOffset>
|
||||
<resetValue>0x00</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
<name>reset</name>
|
||||
<msb>0</msb>
|
||||
<bitRange>[0:0]</bitRange>
|
||||
<lsb>0</lsb>
|
||||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
<register>
|
||||
<name>SCRATCH</name>
|
||||
<description><![CDATA[Use this register as a scratch space to verify that software read/write accesses
|
||||
to the Wishbone/CSR bus are working correctly. The initial reset value of
|
||||
0x1234578 can be used to verify endianness.]]></description>
|
||||
<addressOffset>0x0004</addressOffset>
|
||||
<resetValue>0x12345678</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
<name>scratch</name>
|
||||
<msb>31</msb>
|
||||
<bitRange>[31:0]</bitRange>
|
||||
<lsb>0</lsb>
|
||||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
<register>
|
||||
<name>BUS_ERRORS</name>
|
||||
<description><![CDATA[Total number of Wishbone bus errors (timeouts) since start.]]></description>
|
||||
<addressOffset>0x0008</addressOffset>
|
||||
<resetValue>0x00</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
<name>bus_errors</name>
|
||||
<msb>31</msb>
|
||||
<bitRange>[31:0]</bitRange>
|
||||
<lsb>0</lsb>
|
||||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
</registers>
|
||||
<addressBlock>
|
||||
<offset>0</offset>
|
||||
<size>0xc</size>
|
||||
<usage>registers</usage>
|
||||
</addressBlock>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>IDENTIFIER_MEM</name>
|
||||
<baseAddress>0xF0002000</baseAddress>
|
||||
<baseAddress>0xF0001000</baseAddress>
|
||||
<groupName>IDENTIFIER_MEM</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -100,7 +41,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>TIMER0</name>
|
||||
<baseAddress>0xF0003000</baseAddress>
|
||||
<baseAddress>0xF0002000</baseAddress>
|
||||
<groupName>TIMER0</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -246,17 +187,19 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>REBOOT</name>
|
||||
<baseAddress>0xF0004000</baseAddress>
|
||||
<baseAddress>0xF0003000</baseAddress>
|
||||
<groupName>REBOOT</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
<name>CTRL</name>
|
||||
<name>SOC_RESET</name>
|
||||
<description><![CDATA[Writing 0xAC to this register will do a full SoC reset, including CRGs and
|
||||
peripherals]]></description>
|
||||
<addressOffset>0x0000</addressOffset>
|
||||
<resetValue>0x00</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
<name>ctrl</name>
|
||||
<name>soc_reset</name>
|
||||
<msb>7</msb>
|
||||
<bitRange>[7:0]</bitRange>
|
||||
<lsb>0</lsb>
|
||||
|
|
@ -265,6 +208,7 @@ register to disable individual events.]]></description>
|
|||
</register>
|
||||
<register>
|
||||
<name>ADDR</name>
|
||||
<description><![CDATA[The address written here will be used as the next reset vector]]></description>
|
||||
<addressOffset>0x0004</addressOffset>
|
||||
<resetValue>0x00</resetValue>
|
||||
<size>32</size>
|
||||
|
|
@ -277,16 +221,32 @@ register to disable individual events.]]></description>
|
|||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
<register>
|
||||
<name>CPU_RESET</name>
|
||||
<description><![CDATA[Writing anything to this register resets the CPU, and the CPU only; does not
|
||||
affect CRG or peripherals]]></description>
|
||||
<addressOffset>0x0008</addressOffset>
|
||||
<resetValue>0x00</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
<name>cpu_reset</name>
|
||||
<msb>0</msb>
|
||||
<bitRange>[0:0]</bitRange>
|
||||
<lsb>0</lsb>
|
||||
</field>
|
||||
</fields>
|
||||
</register>
|
||||
</registers>
|
||||
<addressBlock>
|
||||
<offset>0</offset>
|
||||
<size>0x8</size>
|
||||
<size>0xc</size>
|
||||
<usage>registers</usage>
|
||||
</addressBlock>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>CRG</name>
|
||||
<baseAddress>0xF0005000</baseAddress>
|
||||
<baseAddress>0xF0004000</baseAddress>
|
||||
<groupName>CRG</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -410,7 +370,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>GPIO</name>
|
||||
<baseAddress>0xF0006000</baseAddress>
|
||||
<baseAddress>0xF0005000</baseAddress>
|
||||
<groupName>GPIO</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -724,7 +684,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>UART_PHY</name>
|
||||
<baseAddress>0xF0007000</baseAddress>
|
||||
<baseAddress>0xF0006000</baseAddress>
|
||||
<groupName>UART_PHY</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -750,7 +710,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>UART</name>
|
||||
<baseAddress>0xF0008000</baseAddress>
|
||||
<baseAddress>0xF0007000</baseAddress>
|
||||
<groupName>UART</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -908,7 +868,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>CONSOLE_PHY</name>
|
||||
<baseAddress>0xF0009000</baseAddress>
|
||||
<baseAddress>0xF0008000</baseAddress>
|
||||
<groupName>CONSOLE_PHY</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -934,7 +894,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>CONSOLE</name>
|
||||
<baseAddress>0xF000A000</baseAddress>
|
||||
<baseAddress>0xF0009000</baseAddress>
|
||||
<groupName>CONSOLE</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -1092,7 +1052,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SERVER0_PHY</name>
|
||||
<baseAddress>0xF000B000</baseAddress>
|
||||
<baseAddress>0xF000A000</baseAddress>
|
||||
<groupName>SERVER0_PHY</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -1118,7 +1078,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SERVER0</name>
|
||||
<baseAddress>0xF000C000</baseAddress>
|
||||
<baseAddress>0xF000B000</baseAddress>
|
||||
<groupName>SERVER0</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -1276,7 +1236,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SERVER1_PHY</name>
|
||||
<baseAddress>0xF000D000</baseAddress>
|
||||
<baseAddress>0xF000C000</baseAddress>
|
||||
<groupName>SERVER1_PHY</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -1302,7 +1262,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SERVER1</name>
|
||||
<baseAddress>0xF000E000</baseAddress>
|
||||
<baseAddress>0xF000D000</baseAddress>
|
||||
<groupName>SERVER1</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -1460,7 +1420,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>INFO</name>
|
||||
<baseAddress>0xF000F000</baseAddress>
|
||||
<baseAddress>0xF000E000</baseAddress>
|
||||
<groupName>INFO</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -1856,7 +1816,7 @@ VCCBRAM (V) = ``Value`` x 3 / 4096.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SRAM_EXT</name>
|
||||
<baseAddress>0xF0010000</baseAddress>
|
||||
<baseAddress>0xF000F000</baseAddress>
|
||||
<groupName>SRAM_EXT</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -1898,7 +1858,7 @@ VCCBRAM (V) = ``Value`` x 3 / 4096.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>MEMLCD</name>
|
||||
<baseAddress>0xF0011000</baseAddress>
|
||||
<baseAddress>0xF0010000</baseAddress>
|
||||
<groupName>MEMLCD</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2014,7 +1974,7 @@ register to disable individual events.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>COM</name>
|
||||
<baseAddress>0xF0012000</baseAddress>
|
||||
<baseAddress>0xF0011000</baseAddress>
|
||||
<groupName>COM</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2171,10 +2131,14 @@ register to disable individual events.]]></description>
|
|||
<size>0x1c</size>
|
||||
<usage>registers</usage>
|
||||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>com</name>
|
||||
<value>6</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>I2C</name>
|
||||
<baseAddress>0xF0013000</baseAddress>
|
||||
<baseAddress>0xF0012000</baseAddress>
|
||||
<groupName>I2C</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2422,12 +2386,12 @@ register to disable individual events.]]></description>
|
|||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>i2c</name>
|
||||
<value>6</value>
|
||||
<value>7</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>BTEVENTS</name>
|
||||
<baseAddress>0xF0014000</baseAddress>
|
||||
<baseAddress>0xF0013000</baseAddress>
|
||||
<groupName>BTEVENTS</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2511,12 +2475,12 @@ register to disable individual events.]]></description>
|
|||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>btevents</name>
|
||||
<value>7</value>
|
||||
<value>8</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>MESSIBLE</name>
|
||||
<baseAddress>0xF0015000</baseAddress>
|
||||
<baseAddress>0xF0014000</baseAddress>
|
||||
<groupName>MESSIBLE</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2582,7 +2546,7 @@ register advances the read pointer automatically.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>MESSIBLE2</name>
|
||||
<baseAddress>0xF0016000</baseAddress>
|
||||
<baseAddress>0xF0015000</baseAddress>
|
||||
<groupName>MESSIBLE2</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2648,7 +2612,7 @@ register advances the read pointer automatically.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>TICKTIMER</name>
|
||||
<baseAddress>0xF0017000</baseAddress>
|
||||
<baseAddress>0xF0016000</baseAddress>
|
||||
<groupName>TICKTIMER</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2793,12 +2757,12 @@ register to disable individual events.]]></description>
|
|||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>ticktimer</name>
|
||||
<value>8</value>
|
||||
<value>9</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>POWER</name>
|
||||
<baseAddress>0xF0018000</baseAddress>
|
||||
<baseAddress>0xF0017000</baseAddress>
|
||||
<groupName>POWER</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -2958,7 +2922,7 @@ reset fashion]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SPINOR</name>
|
||||
<baseAddress>0xF0019000</baseAddress>
|
||||
<baseAddress>0xF0018000</baseAddress>
|
||||
<groupName>SPINOR</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -3239,7 +3203,7 @@ checked]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>KEYBOARD</name>
|
||||
<baseAddress>0xF001A000</baseAddress>
|
||||
<baseAddress>0xF0019000</baseAddress>
|
||||
<groupName>KEYBOARD</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -3449,19 +3413,19 @@ again until the interrupt is serviced.]]></description>
|
|||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>keyboard</name>
|
||||
<value>9</value>
|
||||
<value>10</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SEED</name>
|
||||
<baseAddress>0xF001B000</baseAddress>
|
||||
<baseAddress>0xF001A000</baseAddress>
|
||||
<groupName>SEED</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
<name>SEED1</name>
|
||||
<description><![CDATA[Bits 32-63 of `SEED_SEED`. Seed used for the build]]></description>
|
||||
<addressOffset>0x0000</addressOffset>
|
||||
<resetValue>0x20483d3b</resetValue>
|
||||
<resetValue>0x2c552c3f</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
|
|
@ -3476,7 +3440,7 @@ again until the interrupt is serviced.]]></description>
|
|||
<name>SEED0</name>
|
||||
<description><![CDATA[Bits 0-31 of `SEED_SEED`.]]></description>
|
||||
<addressOffset>0x0004</addressOffset>
|
||||
<resetValue>0x1febda0d</resetValue>
|
||||
<resetValue>0x3e20093a</resetValue>
|
||||
<size>32</size>
|
||||
<fields>
|
||||
<field>
|
||||
|
|
@ -3496,7 +3460,7 @@ again until the interrupt is serviced.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>ROMTEST</name>
|
||||
<baseAddress>0xF001C000</baseAddress>
|
||||
<baseAddress>0xF001B000</baseAddress>
|
||||
<groupName>ROMTEST</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -3538,7 +3502,7 @@ again until the interrupt is serviced.]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>AUDIO</name>
|
||||
<baseAddress>0xF001D000</baseAddress>
|
||||
<baseAddress>0xF001C000</baseAddress>
|
||||
<groupName>AUDIO</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -3905,12 +3869,12 @@ I2S_FORMAT.I2S_STANDARD is I2S standard]]></description>
|
|||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>audio</name>
|
||||
<value>10</value>
|
||||
<value>11</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>TRNG_OSC</name>
|
||||
<baseAddress>0xF001E000</baseAddress>
|
||||
<baseAddress>0xF001D000</baseAddress>
|
||||
<groupName>TRNG_OSC</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -3996,7 +3960,7 @@ reading the `rand` register]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>AES</name>
|
||||
<baseAddress>0xF001F000</baseAddress>
|
||||
<baseAddress>0xF001E000</baseAddress>
|
||||
<groupName>AES</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -4459,7 +4423,7 @@ automatically on data and IV ready]]></description>
|
|||
</peripheral>
|
||||
<peripheral>
|
||||
<name>SHA512</name>
|
||||
<baseAddress>0xF0020000</baseAddress>
|
||||
<baseAddress>0xF001F000</baseAddress>
|
||||
<groupName>SHA512</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -4949,12 +4913,12 @@ in bits]]></description>
|
|||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>sha512</name>
|
||||
<value>11</value>
|
||||
<value>12</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>ENGINE</name>
|
||||
<baseAddress>0xF0021000</baseAddress>
|
||||
<baseAddress>0xF0020000</baseAddress>
|
||||
<groupName>ENGINE</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
@ -5178,12 +5142,12 @@ exactly reflects the binary layout of an Engine instruction.]]></description>
|
|||
</addressBlock>
|
||||
<interrupt>
|
||||
<name>engine</name>
|
||||
<value>12</value>
|
||||
<value>13</value>
|
||||
</interrupt>
|
||||
</peripheral>
|
||||
<peripheral>
|
||||
<name>JTAG</name>
|
||||
<baseAddress>0xF0022000</baseAddress>
|
||||
<baseAddress>0xF0021000</baseAddress>
|
||||
<groupName>JTAG</groupName>
|
||||
<registers>
|
||||
<register>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,12 @@ description = "COM interface to the EC"
|
|||
xous = { path = "../../xous-rs" }
|
||||
heapless = "0.5"
|
||||
log-server = { path = "../log-server" }
|
||||
ticktimer-server = { path = "../ticktimer-server" }
|
||||
log = "0.4"
|
||||
com_rs = { path = "com_rs" }
|
||||
#[target.'cfg(not(any(windows,unix)))'.dependencies]
|
||||
typenum = "1.12"
|
||||
|
||||
[target.'cfg(not(any(windows,unix)))'.dependencies]
|
||||
utralib = { path = "../../utralib"}
|
||||
|
||||
[target.'cfg(any(windows,unix))'.dependencies]
|
||||
|
|
|
|||
|
|
@ -4,12 +4,44 @@ use xous::{Message, ScalarMessage};
|
|||
// It's just a convenient abuse of already-defined constants. However, it's intended that
|
||||
// the COM server on the SoC side abstracts much of the EC bus complexity away.
|
||||
use com_rs::*;
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BattStats {
|
||||
/// instantaneous voltage in mV
|
||||
pub voltage: u16,
|
||||
/// state of charge in %, as inferred by impedance tracking
|
||||
pub soc: u8,
|
||||
/// instantaneous current draw in mA
|
||||
pub current: i16,
|
||||
/// remaining capacity in mA, as measured by coulomb counting
|
||||
pub remaining_capacity: u16,
|
||||
}
|
||||
|
||||
impl From<[usize; 2]> for BattStats {
|
||||
fn from(a: [usize; 2]) -> BattStats {
|
||||
BattStats {
|
||||
voltage: (a[0] & 0xFFFF) as u16,
|
||||
soc: ((a[0] >> 16) & 0xFF) as u8,
|
||||
current: ((a[1] >> 16) & 0xFFFF) as i16,
|
||||
remaining_capacity: (a[1] & 0xFFFF) as u16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[usize; 2]> for BattStats {
|
||||
fn into(self) -> [usize; 2] {
|
||||
[ (self.voltage as usize & 0xffff) | ((self.soc as usize) << 16) & 0xFF_0000,
|
||||
(self.remaining_capacity as usize & 0xffff) | ((self.current as usize) << 16) & 0xffff_0000 ]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Opcode {
|
||||
/// Battery stats
|
||||
BattStats,
|
||||
|
||||
/// Query Full charge capacity of the battery
|
||||
BattFullCapacity,
|
||||
|
||||
/// Turn Boost Mode On
|
||||
BoostOn,
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,27 @@
|
|||
#![cfg_attr(target_os = "none", no_std)]
|
||||
|
||||
/// This is the API that other servers use to call the COM. Read this code as if you
|
||||
/// are calling these functions inside a different process.
|
||||
|
||||
pub mod api;
|
||||
|
||||
use api::BattStats;
|
||||
use xous::{send_message, Error, CID};
|
||||
|
||||
pub fn power_off_soc(cid: CID) -> Result<(), xous::Error> {
|
||||
send_message(cid, api::Opcode::PowerOffSoc.into()).map(|_| ())
|
||||
}
|
||||
|
||||
pub fn get_batt_stats(cid: CID) -> Result<BattStats, xous::Error> {
|
||||
let response = send_message(cid, api::Opcode::BattStats.into())?;
|
||||
if let xous::Result::Scalar2(upper, lower) = response {
|
||||
let raw_stats: [usize; 2] = [lower, upper];
|
||||
Ok(raw_stats.into())
|
||||
} else {
|
||||
panic!("unexpected return value: {:#?}", response);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn elapsed_ms(cid: CID) -> Result<u64, Error> {
|
||||
let response = send_message(cid, api::Opcode::ElapsedMs.into())?;
|
||||
|
|
|
|||
|
|
@ -10,28 +10,39 @@ use api::Opcode;
|
|||
|
||||
use core::convert::TryFrom;
|
||||
|
||||
/*
|
||||
use heapless::binary_heap::{BinaryHeap, Min};
|
||||
use heapless::Vec;
|
||||
use heapless::consts::*;
|
||||
type U1280 = UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B1>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>;
|
||||
*/
|
||||
|
||||
use log::{error, info};
|
||||
|
||||
use com_rs::*;
|
||||
|
||||
//#[cfg(target_os = "none")]
|
||||
#[cfg(target_os = "none")]
|
||||
mod implementation {
|
||||
use crate::api::BattStats;
|
||||
use ticktimer_server::*;
|
||||
use com_rs::*;
|
||||
use utralib::generated::*;
|
||||
use xous::CID;
|
||||
|
||||
/*
|
||||
#[macro_use]
|
||||
use heapless::Vec;
|
||||
|
||||
use typenum::{UInt, UTerm};
|
||||
use typenum::bit::{B0, B1};
|
||||
type U1280 = UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B1>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>;
|
||||
*/
|
||||
|
||||
const STD_TIMEOUT: u32 = 100;
|
||||
|
||||
pub struct XousCom {
|
||||
csr: utralib::CSR<u32>,
|
||||
ticktimer: CID,
|
||||
}
|
||||
|
||||
fn handle_irq(_irq_no: usize, arg: *mut usize) {
|
||||
let _xc = unsafe { &mut *(arg as *mut XousCom) };
|
||||
let xc = unsafe { &mut *(arg as *mut XousCom) };
|
||||
println!("COM IRQ");
|
||||
// just clear the pending request, as this is used as a "wait" until request function
|
||||
xc.csr.wo(utra::com::EV_PENDING, xc.csr.r(utra::com::EV_PENDING));
|
||||
}
|
||||
|
||||
impl XousCom {
|
||||
|
|
@ -44,8 +55,15 @@ mod implementation {
|
|||
)
|
||||
.expect("couldn't map COM CSR range");
|
||||
|
||||
let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
|
||||
let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap();
|
||||
|
||||
let mut xc = XousCom {
|
||||
csr: CSR::new(csr.as_mut_ptr() as *mut u32),
|
||||
ticktimer: ticktimer_conn,
|
||||
//tx_queue: Vec::new(),
|
||||
//rx_queue: Vec::new(),
|
||||
//in_progress: false,
|
||||
};
|
||||
|
||||
xous::claim_interrupt(
|
||||
|
|
@ -68,12 +86,53 @@ mod implementation {
|
|||
// grab the RX value and return it
|
||||
self.csr.rf(utra::com::RX_RX) as u16
|
||||
}
|
||||
|
||||
pub fn wait_txrx(&mut self, tx: u16, timeout: Option<u32>) -> u16 {
|
||||
self.csr.wfo(utra::com::EV_ENABLE_SPI_HOLD, 1);
|
||||
if timeout.is_some() {
|
||||
let curtime = ticktimer_server::elapsed_ms(self.ticktimer).expect("couldn't connect to ticktimer");
|
||||
let mut timed_out = false;
|
||||
let to = timeout.unwrap() as u64;
|
||||
// timeout after 0.25 second to avoid hangs in case of a bug in the protocol
|
||||
while self.csr.rf(utra::com::STATUS_HOLD) == 1 && !timed_out {
|
||||
if (ticktimer_server::elapsed_ms(self.ticktimer).expect("couldn't connect to ticktimer") - curtime) > to {
|
||||
timed_out = true;
|
||||
}
|
||||
xous::wait_event();
|
||||
}
|
||||
} else {
|
||||
while self.csr.rf(utra::com::STATUS_HOLD) == 1 {
|
||||
xous::wait_event();
|
||||
}
|
||||
}
|
||||
self.csr.wfo(utra::com::EV_ENABLE_SPI_HOLD, 0);
|
||||
|
||||
self.txrx(tx)
|
||||
}
|
||||
|
||||
pub fn get_battstats(&mut self) -> BattStats {
|
||||
let mut stats = BattStats::default();
|
||||
|
||||
self.txrx(ComState::GAS_GAUGE.verb);
|
||||
stats.current = self.wait_txrx(ComState::LINK_READ.verb, Some(STD_TIMEOUT)) as i16;
|
||||
self.wait_txrx(ComState::LINK_READ.verb, Some(100)); // stby_current, not used here
|
||||
stats.voltage = self.wait_txrx(ComState::LINK_READ.verb, Some(STD_TIMEOUT));
|
||||
self.wait_txrx(ComState::LINK_READ.verb, Some(100)); // power register value, not used
|
||||
|
||||
self.txrx(ComState::GG_SOC.verb);
|
||||
stats.soc = self.wait_txrx(ComState::LINK_READ.verb, Some(STD_TIMEOUT)) as u8;
|
||||
self.txrx(ComState::GG_REMAINING.verb);
|
||||
stats.remaining_capacity = self.wait_txrx(ComState::LINK_READ.verb, Some(STD_TIMEOUT));
|
||||
|
||||
stats
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a stub to try to avoid breaking hosted mode for as long as possible.
|
||||
#[cfg(not(target_os = "none"))]
|
||||
mod implementation {
|
||||
use crate::api::BattStats;
|
||||
pub struct XousCom {
|
||||
}
|
||||
|
||||
|
|
@ -83,9 +142,18 @@ mod implementation {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn txrx(tx: u16) -> u16 {
|
||||
pub fn txrx(&mut self, _tx: u16) -> u16 {
|
||||
0xDEAD as u16
|
||||
}
|
||||
|
||||
pub fn get_battstats(&mut self) -> BattStats {
|
||||
BattStats {
|
||||
voltage: 3700,
|
||||
current: -150,
|
||||
soc: 50,
|
||||
remaining_capacity: 750,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,6 +181,17 @@ fn xmain() -> ! {
|
|||
info!("COM: power off called");
|
||||
com.txrx(ComState::POWER_OFF.verb);
|
||||
}
|
||||
Opcode::BattStats => {
|
||||
info!("COM: batt stats request received");
|
||||
let stats = com.get_battstats();
|
||||
let raw_stats: [usize; 2] = stats.into();
|
||||
xous::return_scalar2(
|
||||
envelope.sender,
|
||||
raw_stats[1],
|
||||
raw_stats[0]
|
||||
).expect("COM: couldn't return batt stats request");
|
||||
info!("COM: done returning batt stats request");
|
||||
}
|
||||
_ => error!("unknown opcode"),
|
||||
}
|
||||
} else {
|
||||
|
|
@ -120,5 +199,3 @@ fn xmain() -> ! {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// xous::wait_event()
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@ utralib = { path = "../../utralib"}
|
|||
|
||||
[features]
|
||||
debugprint = []
|
||||
default = []
|
||||
#default = ["debugprint"]
|
||||
#default = []
|
||||
default = ["debugprint"]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use log::{error, info};
|
|||
use xous::String;
|
||||
use graphics_server::Point;
|
||||
use graphics_server::GlyphSet;
|
||||
use com::api::BattStats;
|
||||
use com::*;
|
||||
|
||||
// fn print_and_yield(index: *mut usize) -> ! {
|
||||
// let num = index as usize;
|
||||
|
|
@ -148,8 +150,6 @@ fn shell_main() -> ! {
|
|||
|
||||
let screensize = graphics_server::screen_size(graphics_conn).expect("Couldn't get screen size");
|
||||
|
||||
// let mut counter: usize = 0;
|
||||
let mut ls = logstr::LogStr::new();
|
||||
let dark = graphics_server::Color::from(0);
|
||||
let light = graphics_server::Color::from(!0);
|
||||
let mut bouncyball = Bounce::new(14,
|
||||
|
|
@ -157,8 +157,10 @@ fn shell_main() -> ! {
|
|||
Point::new(screensize.x as _, screensize.y as i16 - 1)));
|
||||
bouncyball.update();
|
||||
|
||||
let mut batt_stats: BattStats = BattStats::default();
|
||||
|
||||
#[cfg(baremetal)]
|
||||
{
|
||||
{ // use this to select which UART to monitor in the main loop
|
||||
use utralib::generated::*;
|
||||
let gpio_base = xous::syscall::map_memory(
|
||||
xous::MemoryAddress::new(utra::gpio::HW_GPIO_BASE),
|
||||
|
|
@ -183,40 +185,19 @@ fn shell_main() -> ! {
|
|||
ticktimer_server::reset(ticktimer_conn).unwrap();
|
||||
let mut string_buffer = String::new(4096);
|
||||
loop {
|
||||
// a message passing demo -- checking time
|
||||
// update battery status periodically
|
||||
if let Ok(elapsed_time) = ticktimer_server::elapsed_ms(ticktimer_conn) {
|
||||
info!("SHELL: {}ms", elapsed_time);
|
||||
if elapsed_time - last_time > 40 {
|
||||
if elapsed_time - last_time > 500 {
|
||||
last_time = elapsed_time;
|
||||
/*
|
||||
xous::try_send_message(log_conn,
|
||||
xous::Message::Scalar(xous::ScalarMessage{id:256, arg1: elapsed_time as usize, arg2: 257, arg3: 258, arg4: 259}));
|
||||
*/
|
||||
info!("Preparing a mutable borrow message");
|
||||
|
||||
ls.clear();
|
||||
write!(
|
||||
ls,
|
||||
"Hello, Server! This memory is borrowed from another process. Elapsed: {}",
|
||||
elapsed_time as usize
|
||||
)
|
||||
.expect("couldn't send hello message");
|
||||
|
||||
let mm = ls
|
||||
.as_memory_message(0)
|
||||
.expect("couldn't form memory message");
|
||||
|
||||
info!("Sending a mutable borrow message");
|
||||
|
||||
xous::syscall::send_message(log_conn, xous::Message::MutableBorrow(mm))
|
||||
.expect("couldn't send memory message");
|
||||
batt_stats = get_batt_stats(com_conn).expect("Can't get battery stats from COM");
|
||||
}
|
||||
} else {
|
||||
error!("error requesting ticktimer!")
|
||||
}
|
||||
|
||||
string_buffer.clear();
|
||||
write!(&mut string_buffer, "Uptime: {:.2}s", last_time as f32 / 1000f32).expect("Can't write");
|
||||
write!(&mut string_buffer, "{}mV Uptime: {:.2}s", batt_stats.voltage, last_time as f32 / 1000f32).expect("Can't write");
|
||||
graphics_server::set_glyph(graphics_conn, GlyphSet::Small).expect("unable to set glyph");
|
||||
let (_, h) = graphics_server::query_glyph(graphics_conn).expect("unable to query glyph");
|
||||
graphics_server::clear_region(graphics_conn, 0, 0, screensize.x as usize - 1, h)
|
||||
|
|
@ -225,9 +206,6 @@ fn shell_main() -> ! {
|
|||
graphics_server::draw_string(graphics_conn, &string_buffer).expect("unable to draw string");
|
||||
|
||||
// ticktimer_server::sleep_ms(ticktimer_conn, 500).expect("couldn't sleep");
|
||||
if last_time > 10_000 { // after 10 seconds issue a shutdown command
|
||||
com::power_off_soc(com_conn).expect("Couldn't issue powerdown command to COM");
|
||||
}
|
||||
|
||||
// draw the ball
|
||||
bouncyball.update();
|
||||
|
|
|
|||
Loading…
Reference in a new issue