2023–05–23: Boot
time power consumption tracing
Power consumption changes rapidly during boot. One microsecond it can be
700 mW and a few microseconds later it can be 3000 mW.
So that I can observe these changes precisely and attribute them to code
being executed in the bootloader (levinboot in this case), I had to create a
test steup that measures the voltage drop on a shunt resistor placed in the VBUS
path and taps into phone's serial console at the same time. Pinephone has
serial console conveniently routed to the audio jack output, so this was easily
doable.
This way I can precisely attribute bootloader actions to power consumption
changes down to 100's of nanoseconds.
(I decided to measure at the battery terminals instead of VBUS/Type-C port
to avoid having to deal with the VBUS input current limit. VBUS current can be
calculated by multiplying the battery current by 4.3 / 5
. So
500 mA from battery equals 430 mA from Type-C port.)
The output from the entire boot looks something like this:
Peak current from the battery during boot is almost 2A @ 4.3V. (8.6 W)
Walkthrough of the powerup
process
Let's walk through the whole powerup process together.
The power button is pressed, and PMIC starts going throug initial regulator
powerup in a sequence defined in the datasheet.
The datasheet says that regulators are powered up in sequence separated by
66 x tCK32k
, which means 66 periods of 32 kHz clock, which equals
to 2.1ms.
This matches with the first activity we see on the scope:
The biggest peak by far is the VCC3V3_SYS
power rail being
enabled, which is not surprising, since a lot of things are powered by it inside
Pinephone Pro.
UART TX signal going high coincides with VDD_LOG
being enabled.
This power rail drives the internal logic in the SoC, thus the name. Apparently
it also powers the UART controller.
After power up sequence is complete, PMIC will wait for voltages to stabilize
and release NRESPWRON
signal after Ton6
(82 ms):
We can see this time interval on the scope as a period of stable current
after the power up sequence finished:
Power consumption is 465 mW, calculated as 4.3 V * 108 mA
. BTW,
1 mV on the yellow trace's scale means 1 mA.
So just about after the predefined set of regulators needed for startup is
enabled, the power consumption is already higher than what can be achieved in
deep sleep. (Even when the SoC is held in reset state and is doing nothing.)
Next period of time is RK3399 boot ROM (BROM) doing some initialization that
ultimately results in it reading a SRAM stage of levinboot from my microSD card.
The moment BROM passes execution to levinboot, is the moment when the first
activity is seen at the UART TX, because levinboot immediately announces itself
by printing its version to serial console.
This period of BROM activity, prior to levinboot saying hello, lasts 365 ms
and can be split into two parts:
Both of these periods of activity are easily identified by their power
consumption profile.
The zoomed in part in detail:
Maybe someone knows what's BROM up to in those post-powerup 257 ms of
activity. I don't. This is the only unaccounted for time of activity
during boot.
In any case, during the whole period of BROM activity before the bootloader
is jumped to (regardless of whether it's levinboot or U-Boot), the phone is
seen consuming maximum of 1.3 W. This is well inside the bounds of the default
450 mA input current limit on VBUS, which in worst case of 4.5 V VBUS
is ~2W.
No problem here.
Next up, the levinboot runs and loads the kernel. DRAM initialization and
training happens in the first 80 ms or so, after which there's a period of
loading data from eMMC and jump to TF-A/kernel.
The power consumption is ~2.1W right before the bootloader starts accessing
eMMC to load the payload (kernel, etc.). This is so so within the input
current limit.
Power consumption in the bootloader unfortunately peaks to 2.8–3W during
the eMMC access time, and this is where the PMIC power cycles when the battery
is fully discharged.
This matches my experience with levinboot failing to boot without battery,
during the eMMC load stage, before I patched it to raise the limit in early
DRAM stage.
The same issue of course happens in U-Boot, for the same reason.
Suspend / resume power
traces for the curious
Deep sleep transitions are interesting, too. It's possible to use them to
discern contributions of various parts of the sleep transition sequence to power
savings.
I'll leave them to you with just one observation, because I haven't looked
very closely at them. A whole 66% of power savings seems to be attributable to
just the one last thing TF-A does during the transition to deep sleep.
Amazing, right?
Wakeup looks quite different. Not at all just the sleep transition reverse,
as one might expect. There's some story in there, too.
Power
consumption tracing and the future optimizations
Power consumption tracing can show us a lot of interesting things and can be
used creatively to identify opportunities to save more power at runtime.
I can envision adding a 100 ms delay and a printk before each
driver's suspend function, and record the suspend to idle power trace. From the
trace it will be possible to see contributions of each device that's being
suspended to the power consumption of the phone, without tediously going through
each device by hand and figuring out ways to disable them manually.
I'll simply go through a trace, and find a printk that results in the biggest
drop in current. :)
Given the large difference between idle and s2idle power consumption, this
can be used to identify devices that consume the most at runtime, and are best
candidates for implementing runtime power management.
Stay tuned for some DRAM power savings on Pinephone Pro in the
next post!