Skip to content

CoreS3 / Core2 v1.1: keep the PMIC on when the 5 V output comes up on a weak USB supply - #381

Merged
lovyan03 merged 2 commits into
m5stack:developfrom
ainyan03:cores3_bus_precharge
Sep 30, 2026
Merged

lovyan03 merged 2 commits into
m5stack:developfrom
ainyan03:cores3_bus_precharge

Conversation

@ainyan03

Copy link
Copy Markdown
Contributor

On a weak USB supply (a port several hubs deep, no battery), a CoreS3 SE powered itself off right after M5.begin(): the backlight flashed once and the board stayed silent. The AXP2101 reported a DCDC under-voltage power-off (REG21 = 0x20). The power key started it, because the charge left on the 5 V bus by the failed attempt remained. The Core2 v1.1 showed the same power-off.

Cause

setExtOutput(true) in begin() connects the empty 5 V bus (BUS_OUT) to the running boost converter through BUS_OUT_EN. The inrush into the bus capacitance pulls a DCDC output below 85 % of its setting, and the AXP2101 latches itself off until the power key is pressed. With cfg.output_power = false the board starts.

Change

  • CoreS3 family: when BUS_OUT_EN goes from 0 to 1, it is first pulsed with a growing on-time (one 100 kHz register write plus i × 16 µs, 1 ms apart, 8 times, about 10 ms). BUS_OUT has a constant discharge path, so short fixed pulses do not accumulate; once it passes about 1.7 V it is pulled up from VBUS even with BUS_OUT_EN = 0, and the final enable is a small step. If a write fails during the ramp, BUS_OUT_EN is rewritten and read back so that the reported result matches the output, and the final enable is read back and retried.
  • CoreS3 family and Core2 v1.1: the DCDC1–5 under-voltage power-off (REG23 bit 4:0) is disabled in begin(). A dip then resets the ESP32 through its brown-out detector instead of latching the PMIC off. The DCDC over-voltage power-off and the VSYS under-voltage power-off (VOFF) stay enabled. On the Core2 v1.1, setExtOutput(false) re-applies the disable before switching instead of suspending and restoring it.

The same precharge is added to M5GFX's board detection for the case where detection itself enables the bus (m5stack/M5GFX#319).

Checks

  • CoreS3 SE, no battery, several hubs deep: before, plugging USB in never started the board (REG21 = 0x20). After, it starts on every plug-in over repeated tries, and a logic analyzer on the 5 V bus shows it rising through the pulses and crossing about 1.7 V within the first few pulses.
  • Four CoreS3-family boards on one hub (two of them charging a battery): with both changes, each battery-less board starts on its own plug-in or power key; before, they did not. Plugging the whole hub in at once can still pull VSYS itself down before the firmware runs (REG21 = 0x08), depending on the hub.
  • Core2 v1.1, no battery: starts on a weak supply. setExtOutput(false) on USB still switches the 5 V bus from the boost converter to USB VBUS (it does not remove 5 V), and on a supply without enough headroom (for example a hub with other loads) the switch-over pulls VSYS down for about 1 ms and the ESP32 browns out and resets; the PMIC no longer latches off, so the board recovers by itself. Input-limit, load and BLDO2-timing changes did not avoid the dip, so the behaviour is documented in the setExtOutput() note instead (use it only with a battery).
  • Builds for all the Arduino and ESP-IDF versions of this repository's CI (also checked on the fork's CI).

On a weak USB supply with no battery, the inrush when the external 5V
output is switched on in begin() pulls a DCDC output below 85% of its
setting, and the AXP2101 powers itself off (REG21 = 0x20) until the power
key is pressed. Seen on the CoreS3 SE and Core2 v1.1 behind several USB
hubs; the backlight flashes once and the board is silent. With
cfg.output_power = false, or with the power-off disabled, they boot.

M5GFX disables this power-off (REG23 bit4:0) when it first powers the
panel, but begin() re-armed DCDC1/DCDC3 on the Core2 v1.1, which undid it
before the external output came on. begin() now disables DCDC1-5 on the
Core2 v1.1 and the CoreS3 family instead. A dip then resets the ESP32
through its brown-out detector rather than latching the PMIC off. The
DCDC over-voltage power-off and the VSYS under-voltage power-off (VOFF)
stay enabled.

setExtOutput(false) on the Core2 v1.1 no longer suspends and restores the
power-off around the 5V bus switch-over: it re-applies the disable first
(in case begin() could not write it) and returns false without touching
the output if that write fails. Checked on a
Core2 v1.1 without battery: switching the output off still ends in a
brown-out reset that recovers, as before.
On a weak USB supply (several hub levels deep, no battery) the CoreS3
family powered itself off right after begin(): connecting the empty
BUS_OUT capacitance through BUS_OUT_EN in setExtOutput(true) pulled the
AXP2101 DCDC under its threshold and the PMIC shut down (REG21 = 0x20).
Plugging USB in never booted the board; the power key did, because the
charge left on BUS_OUT by the failed attempt remained.

When BUS_OUT_EN goes from 0 to 1, pulse it first with a growing on-time:
each pulse is one 100 kHz register write plus i * 16 us, 1 ms apart, 8
times (about 10 ms). BUS_OUT has a constant discharge path, so short
fixed pulses do not accumulate; once it passes about 1.7 V it is pulled
up from VBUS even with BUS_OUT_EN = 0 and the final enable is a small
step. Measured on a CoreS3 SE, the point is crossed at the 3rd pulse.

A write that fails during the ramp is followed by rewriting and reading
back BUS_OUT_EN = 0 (up to three times): confirmed off returns false
(after a failed on-pulse) or continues the ramp, still on goes to the
final enable, unreadable returns false. The final enable is read back
and retried, because a precharged BUS_OUT left with BUS_OUT_EN = 0 is
pulled up from VBUS and then keeps later setExtOutput(true) calls
cancelled by the TS check. The ramp runs only on the 0 -> 1 transition,
inside the existing AW9523 lock.
@lovyan03
lovyan03 merged commit ec073a1 into m5stack:develop Sep 30, 2026
28 checks passed
@ainyan03
ainyan03 deleted the cores3_bus_precharge branch September 30, 2026 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants