Files
proxmark3/include
4f4acedbdd pm5: reduce idle power (core clock scaling + WFI idle)
Port the "reduce idle power" feature from the Fantasi firmware
(soeinova/Fantasi @ 9671309, plus its later ACC-SOF fix) to the PM5
(AT32F435) target.

Problem
-------
The PM5 firmware ran the ARM core at 288 MHz with a 1.3 V LDO and a
main loop that busy-polled at full speed even when the device was idle.
The 288 MHz PLL and the 1.3 V LDO dominate idle draw, and the busy loop
adds to it. Nothing scaled back when there was no work.

Change
------
New armsrc/pm5_power.c drives a refcounted clock/voltage governor:
- Idle (nothing pending, boost count 0, boot grace elapsed, FPGA off):
  take SCLK off the PLL onto HICK-48, power the PLL down, drop the LDO
  to 1.1 V, park the FPGA 24 MHz clock (PA8 low), and halt the core in
  WFI until the next IRQ or the 1 ms SysTick wake.
- Any timing-critical work holds a 288 MHz boost: AppMain wraps
  PacketReceived (which on the PM5 also covers a standalone mode, since
  it is only entered through a command there); the BWM low-batt poll
  and the RGB indicator wrap their I2C. Boost is refcounted and
  IRQ-guarded.
- USB (OS image) moves to the crystal-less HICK-48 clock, ACC-trimmed
  against the SOF, so powering the PLL down never touches USB. The
  bootrom keeps the HEXT/PLL USB path (AS_BOOTROM), so DFU flashing is
  unchanged.
- bwm_uart_clock_update() re-inits UART4 through the SDK usart_init()
  on each clock switch (the divider set at 288 MHz is 6x off at 48 MHz).
- FpgaIsOff() (fpga_core.c, PM5 only) tracks the last conf word so the
  governor never downclocks while a reader field / emulation is running.
- Wake preamble on the BWM link: the companion module firmware
  (Proxmark5_BWM_esp32) light-sleeps 2 s after the last byte on the link
  and its UART wakes on RX edges but loses the bytes that carried them.
  bwm_uart_write() therefore leads with four 0x55 bytes and a 10 ms
  settle on its first write and after 1 s without a write of its own
  (RX is not tracked: the ring can be drained long after the bytes
  came in). The module only starts light-sleeping once it has seen a
  preamble, so the one sent while it was still booting is repeated
  after the boot-time link negotiation. A module firmware without light
  sleep drops the preamble as noise.

New `hw powersave on|off` toggles the governor at runtime (default on);
`hw status` reports the idle-clock and WFI-asleep fractions.

Behaviour change
----------------
- PM5 idles at 48 MHz with the PLL off and the CPU halted; it boosts to
  288 MHz for commands and BWM housekeeping. Command timing and
  throughput are unchanged (intra-command work is always boosted).
- PM5 USB now runs off HICK-48 (ACC-trimmed) instead of the HEXT PLL.
- New command id CMD_PM5_POWERSAVE (0x0180).

Testing
-------
Built warning-free (gcc) for PLATFORM=PM5 (with and without
PLATFORM_EXTRAS=BWM), PM3RDV4 and PM3GENERIC, armsrc and bootrom. Client
built via the default Makefile. Not built with clang or on
Windows/macOS; nothing outside PM5/AT32 guards changes.

Flashed to a PM5 and exercised against a MIFARE Classic 4K card:
hw version/status/ping (4000 & 512 B), hw tune, hf search, hf 14a
info/reader (x12 across idle gaps), hf mf info/chk/rdbl, lf search/read,
hw powersave off/on, held-field (raw -sk) correctly blocks the downclock,
hw reset + re-enumerate. All pass; USB stays up across downclocks. Idle
reaches ~80-95% at 48 MHz and ~90%+ WFI-halted after a few seconds idle.
Measured at the USB port: idle draw 283 mA -> 207 mA with the stock
BWM firmware.

Co-authored-by: Soei Nova <soeinova@proton.me>
Co-authored-by: noproto <noproto@zeroday.engineering>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 10:33:46 +02:00
..
2026-07-28 15:53:20 +02:00
2026-08-19 12:04:32 +02:00
2026-09-15 21:58:57 +02:00
2026-08-19 15:32:39 +02:00
2026-08-29 15:00:03 +02:00
2026-08-28 22:35:08 +02:00
2026-09-12 15:10:36 +02:00
2023-01-14 22:22:04 +01:00
2026-02-06 13:43:41 +01:00
2022-01-08 00:40:52 +01:00