blob: a84ee6c4c3ed19df44c12b2776375e59ac5ea029 [file] [log] [blame] [view]
# Chrome OS Power Measurement
This document details how developers can use hardware tools like Servo and
Sweetberry and software tools within [`dev-util/hdctools`][8] and other repos to
measure power on a Chrome OS device (DUT, device under test).
[TOC]
## Hardware to measure power
### Servo
Servo-like devices, including Servo V2, Servo V4, Micro Servo and Suzy-Qable,
can be used to measure power on the DUT with Analog-to-Digital Converters (ADCs)
on the board. For simplicity, this doc refers to them as just "Servo" devices.
See [Servo][5] for more information on Servo.
### Sweetberry
Sweetberry or Servo INA adapter can be used when there are no ADCs on
the DUT. Sweetberry is the preferred method. A hardware rework on the DUT is
often required to place sense resistors on the power rails and to attach 'Medusa
style' header (HIROSE DF13A-40DP-1.25V(55)) to the sense resistors and ground.
See [Sweetberry Configuration][6] for more information on Sweetberry.
## Bridging hardware and software
### Create configuration file
Servo and Sweetberry can measure power on the DUT, but they have no awareness of
what power rails are being measured, or what size the sense resistors are.
Therefore, a configuration file is necessary to provide information about the
hardware setup. This configuration file is usually manually created by an
engineer and is fed into the power measurement software tool later.
File format: `.py`
See [INA Configuration Files][1] for instructions on how to write the
configuration file.
There are some slight differences between configuration files for Servo and that
for Sweetberry. See [this example][2] for configuration for Servo.
There are two ways to write Sweetberry configuration files. See
[`servo_sweetberry_rails_addr.py`][3] and [`servo_sweetberry_rails_pins.py`][4].
## Generate configuration files for software tool
To test changes servod docker need to be build locally. To do that run:
```bash
(HOST) build-servod
```
Then you need run local docker image using -c flag:
```bash
(HOST) start-servod -c local [...]
```
To verify that you have generated configuration files successfully run servo container
in sleep mode and open its bash:
```bash
(HOST) start-servod -c local --sleep -n check
(HOST) docker exec -it check-docker_servod bash
(INSIDE DOCKER) ls ./usr/local/lib/python3.13/dist-packages/servo/data/
```
Note: adjust python version when necessary.
## Software tool to measure power
If introduced custom changes build servod and start-servod with the local build:
```bash
(HOST) $ build-servod
# For setup with on-board INA chip
(HOST) $ start-servod -c local -p $PORT_NUMBER --board $BOARD -- --config $CONFIG_FILE.xml
# For setup with sweetberry only
(HOST) $ start-servod -c local -p $PORT_NUMBER -- --config $CONFIG_FILE.xml
```
Note that `$CONFIG_FILE.xml` is generated in the previous step. Both `dut-power`
and `dut-control` are servod clients that talk to servod and fetch power data
from the Servo or Sweetberry.
You have to explicitly set $PORT_NUMBER to run servod-based tast test, such as
meta.PowerServodWrapper, which by defaults uses 9999.
### Unlock CCD
If the current-sensor data is to be read out from USB-C interface (CCD), the
GSC must be configured to forward the I2C current sensor bus to the SBU (USB)
interface. You can check whether this is already the case by running `ccd` in
GSC console:
```bash
>> ccd
State: Locked
Password: none
Flags: 0x000000
Capabilities: 0000000000000000
UartGscRxAPTx Y 0=Default (Always)
UartGscTxAPRx Y 0=Default (Always)
UartGscRxECTx Y 0=Default (Always)
UartGscTxECRx - 0=Default (IfOpened)
FlashAP - 0=Default (IfOpened)
FlashEC - 0=Default (IfOpened)
OverrideWP - 0=Default (IfOpened)
RebootECAP - 0=Default (IfOpened)
GscFullConsole - 0=Default (IfOpened)
UnlockNoReboot Y 0=Default (Always)
UnlockNoShortPP Y 0=Default (Always)
OpenNoTPMWipe - 0=Default (IfOpened)
OpenNoLongPP - 0=Default (IfOpened)
BatteryBypassPP Y 0=Default (Always)
Unused Y 0=Default (Always)
I2C - 0=Default (IfOpened)
FlashRead Y 0=Default (Always)
OpenNoDevMode Y 0=Default (Always)
OpenFromUSB Y 0=Default (Always)
OverrideBatt - 0=Default (IfOpened)
APROCheckVC - 0=Default (IfOpened)
```
`I2C` flag will be set to `(Always)` if this bus can be accessed via CCD.
`(IfOpened)` means the bus is inaccessible by default.
To unlock the I2C bus, run `ccd open` and follow the instructions printed on
the console. `ccd reset factory` will save these flags into GSC's non-volatile
memory, so that the unlocked state will be retained. You can revert back to
locked mode with `ccd reset` (usually required before device leaves the
factory).
### dut-power
Recommended, for users who only want measurements in power.
```bash
(HOST) $ dut-power -- [arguments]
# Example arguments for setup with sweetberry only
(HOST) $ dut-power -- --vbat-rate 0 -t 5
```
`dut-power` queries the selected servod to read power measurements from the
Servo or Sweetberry. See `dut-power -h` for setting arguments. `dut-power` works
with both Servo and Sweetberry. It packs configuring the ADCs, reading data,
calculating statistics, and saving to file into one command.
dut-power organizes results into a directory 'power_measurements' in a temp
directory (without TMPDIR in the env, this just defaults to '/tmp'). In there,
each board receives its own directory, and each measurement its own directory
within those. Measurements are labeled by their powerstate and timestamp.
The board name and powerstate are queried from the DUT's EC, though this might
fail, either due to EC communication issues, or because the user is using a
servo device that is not a dut controller e.g. sweetberry. In those cases, they
default to 'unknown' for board, and 'S?' for the powerstate.
Alternatively, they can be provided as command line arguments. If provided
through the command line, they overwrite the EC values (we do not attempt to
even read them)
```
dut-power --powerstate S0ix --board volteer -t 30 -w 10 -p 9998
```
This would read power wait for 10s before reading power for 30s through servod
running at port `9998` and store the result at
`/tmp/power_measurements/volteer/S0ix_20210210-162609/`
Lastly, the board name can also be provided through the environment variable
`BOARD`. To summarize the priorities of how the boardname is determined
(descending priorities)
1. command-line argument
2. querying `ec_board` through servod
3. using `BOARD` environment variable
4. using `'unknown'`
e.g.
```
/tmp/power_measurements/volteer/S0_20201116-162609/
/tmp/power_measurements/unknown/S?_20201116-163909/
```
### dut-control
For power users, provides more info than power.
`dut-control` can collect power measurements from both EC and on-board ADCs.
#### EC
`dut-control` can query battery power via ECs connection (I2C) to the battery,
namely `ppvar_vbat`. On newer devices, same data averaged over 1 minute can be
queried by `avg_ppvar_vbat`.
#### On-board ADCs
`dut-control` can query power rails specified in the configuration file.
#### Types of information
`dut-control` can query power, bus voltage and current for all rails above, and
additionally shunt voltage for on-board ADCs.
#### Configure the ADCs
The on-board ADCs can be configured to more accurately measure power depending
on the size of the sense resistors and shunt voltage across the sense resistors.
Choose from the follow quick configs:
Config | Context
------------------------- | ---------------------------------------
`regular_power` | S0 measurements
`regular_power_no_hw_avg` | S0 measurements w/out avg (for debug)
`low_power` | < S0 measurements
`low_power_no_hw_avg` | < S0 measurements w/out avg (for debug)
#### Examples
1. Create helper variable, without `ppvar_vbat`.
```bash
(HOST) $ mv=$(dut-control -- bus_voltage_rails | cut -f 2 -d: | tr -d ',')
(HOST) $ ma=$(dut-control -- current_rails | cut -f 2 -d: | tr -d ',')
(HOST) $ mw=$(dut-control -- power_rails | cut -f 2 -d: | tr -d ',')
(HOST) $ cfg_reg=$(echo $mv | sed 's/_mv/_cfg_reg/g')
```
2. Configure on-board ADCs (everytime after running `servod`).
```bash
(HOST) $ for cfg in $cfg_reg ; do dut-control -- $cfg:regular_power $cfg; done
```
Or
```bash
(HOST) $ for cfg in $cfg_reg ; do dut-control -- $cfg:low_power $cfg; done
```
3. Measure each power rail once.
```bash
(HOST) $ dut-control -- $mv
(HOST) $ dut-control -- $ma
(HOST) $ dut-control -- $mw
```
And
```bash
(HOST) $ dut-control -- avg_ppvar_vbat_mw
(HOST) $ dut-control -- avg_ppvar_vbat_ma
(HOST) $ dut-control -- avg_ppvar_vbat_mw
```
Or
```bash
(HOST) $ dut-control -- ppvar_vbat_mv
(HOST) $ dut-control -- ppvar_vbat_ma
(HOST) $ dut-control -- ppvar_vbat_mw
```
4. Measure power for 1 second 30 times.
```bash
(HOST) $ dut-control -- -t 30 -z 1000 $mw | grep @@ | cut -b 6-
```
### powerlog
See [Sweetberry USB power monitoring][7].
[1]: ./ina.md
[2]: ../servo/data/nami_rev1_inas.py
[3]: ../servo/data/servo_sweetberry_rails_addr.py
[4]: ../servo/data/servo_sweetberry_rails_pins.py
[5]: ./servo.md
[6]: ./sweetberry.md
[7]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/extra/usb_power/powerlog.README.md
[8]: https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/HEAD