Framework 13 (Ryzen AI 300): intermittent corrupt battery readings from the EC trigger false “battery critical” / critical-action events
Summary
On battery, the ACPI battery status (_BST) intermittently returns corrupt data for one or more consecutive reads: charge fields missing or negative, capacity values like 468376%, discharge current of −65 A. Linux reports these as-is, and UPower turns them into 0% with WarningLevel “action”, the level at which the configured critical power action (hibernate / hybrid sleep / power off) is taken. Most events last 1–2 s, short enough that the action has not fired yet, but one lasted at least 30 s. Eight events have been captured since 2026-09-29, and the rate is rising (four or five on 2026-10-02 alone).
System
| Model | Framework Laptop 13 (AMD Ryzen AI 300 Series), board A9 |
| CPU | AMD Ryzen AI 9 HX 370 |
| BIOS | 03.05 (2025-10-30), the latest stable |
| EC | lilac-3.0.5-9010bdf (RO and RW), built 2025-10-30 |
| Battery | NVT FRANGWA (61 Wh design), 137 cycles, full charge 3.57 Ah (≈91% of design) |
| OS | Pop!_OS 24.04, kernel 7.1.5, UPower via the ACPI battery driver (BAT1, PNP0C0A) |
How it was captured
A logging service records every kernel power_supply uevent for BAT1 (about 1 per second while discharging, otherwise a direct sysfs read every 60 s), every UPower change, and kernel messages from the EC drivers. Values below are exactly what the kernel exposed (µAh, µA, µV); ? means the field was absent from the uevent, i.e. the firmware reported it as unknown.
Captured events (all while discharging, no charger connected)
| Time (local) | Actual charge | Corrupt reading | UPower result |
|---|---|---|---|
| 2026-09-29 13:14:27 | 74% | capacity=-1376499853 charge_now=-170000, voltage absent, level Low |
4.7%, WarningLevel 4 (critical); notification shown |
| 2026-09-29 20:46:53 | 36% | capacity=468376 charge_now=-402654184 current=2000 |
100% for 30 s |
| 2026-10-01 18:26:01 | 38% | capacity and charge_now absent, level Low |
0%, WarningLevel 5 (action) |
| 2026-10-02 11:50:02 | 96% | capacity/charge_now absent, current_now=-65023000, level Low |
0%, action |
| 2026-10-02 11:51:19 | 96% | level Critical with current=1000 voltage=17000000 (suspiciously round) |
— |
| 2026-10-02 12:31:58 | 95% | capacity/charge_now absent, level Low |
0%, action |
| 2026-10-02 12:41:19 | 92% | level Critical, current_now absent |
— |
| 2026-10-02 14:59:02 | 95% | capacity/charge_now absent, current_now=-64663000, level Low |
0%, action |
| 2026-10-02 19:59:11 | 96% | charge_now = charge_full (100%) for one sample |
100% |
Representative raw samples (one-second spacing):
2026-10-02 11:50:01.600 cap=96 lvl=Normal now=3440000 full=3569000 cur=516000 volt=16991000
2026-10-02 11:50:02.860 cap=? lvl=Low now=? full=3569000 cur=-65023000 volt=16975000
2026-10-02 11:50:04 back to cap=96
2026-09-29 20:46:23.382 cap=36 now=1292000 full=3582000 cur=458000 volt=14977000
2026-09-29 20:46:53.492 cap=468376 now=-402654184 full=3582000 cur=2000 volt=14958000
2026-09-29 20:47:23 back to cap=36
Note that charge_full is never affected, and the voltage is usually sane: the corruption appears to hit some fields of the _BST package and not others.
Related EC symptoms on the same machine
cros_ec_lpcs FRMWC004:00: packet too long (65535 bytes, expected 0)andbad packet checksum ff, intermittently since at least 2026-09-18. One occurred at 11:45:11, five minutes before the 11:50 event; most events have no EC error nearby.workqueue: power_supply_changed_work hogged CPU for >13333us N times, climbing within a boot: 131 by 2026-09-27, 259 by 2026-10-02.ucsi_acpi USBC000:00: unknown error 256several times a day.- 2026-10-02:
ACPI: EC: EC stopped / EC startedat 08:17 (around a resume) andACPI: EC: interrupt blocked / unblockedat 19:19. - 2026-09-27: the laptop lost power while the gauge reported 2%. The next boot found the RTC reset to 2025-01-01 and spent 36 s in firmware, against 7–9 s normally. A one-off, but it may be relevant to gauge accuracy near empty.
Outside these events the gauge is accurate. A full awake discharge on 2026-09-30 (100% → 11%) integrated to 48.7 Wh from current × voltage, against 49.3 Wh by the gauge, so the problem is transient corrupt reads, not drift.
Impact
- False “Battery Critical” desktop notifications at 74–96% charge.
- UPower reaching WarningLevel action at 95–96% charge. Its critical action (here HybridSleep) is only avoided because most events end within a second or two. The 30-second event shows they can last long enough to trigger it.
- There is no clean OS-side mitigation: UPower cannot be told to distrust a sample, and disabling the critical action removes real low-battery protection.
Questions
- Is this a known EC issue on lilac / Ryzen AI 300, and is it fixed or being worked on in a newer EC build?
- Is anything in the host’s EC traffic (UCSI / PD polling, the
cros_echost-command channel) known to collide with_BSTreads? - What extra data would help? The logger can capture more around each event, e.g.
ectool batteryoutput, if that’s useful.
Full logs available on request.