Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/utility/Power_Class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,16 @@ namespace m5
/// switch-over), and enabling without a battery may block for up to 1 s while the protection check
/// waits for the TS reading to settle. The switch-over is serialized with setUsbOutput and the
/// internal speaker enable, so those may wait for it as well.
/// @note Core2 v1.1 (AXP2101; a Tough with the AXP2101 takes the same path): disabling
/// the output while powered from USB with no battery makes the ESP32 brownout and
/// reset (the board's VBUS-to-bus switch closes before the boost stops and the
/// transient pulls VSYS down). The PMIC stays on and the board reboots with the
/// output enabled again, so a sketch that unconditionally disables it at startup
/// will reboot in a loop on such a unit. With a battery, or with 5 V supplied on
/// the bus, the transition itself does not disturb the board. Disabling an enabled
/// output blocks for about 20 ms while the PMIC's DCDC under-voltage power-off is
/// suspended; it is false, without touching the output, when that protection cannot
/// be suspended, and false after the output was disabled when it could not be re-armed.
bool setExtOutput(bool enable, ext_port_mask_t port_mask = (ext_port_mask_t)0xFF);

/// deprecated : Change to "setExtOutput"
Expand Down
41 changes: 40 additions & 1 deletion src/utility/Power_Class.inl
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,10 @@ namespace m5
// , 0x18, 0x0E
};
Axp2101.writeRegister8Array(reg_data_array, sizeof(reg_data_array));
// Re-arm the DCDC1/DCDC3 under-voltage power-off that setExtOutput(false)
// suspends; an ESP32 brownout reset during that call skips the restore.
// Forced like the table above: these bits are the chip default.
Axp2101.bitOn(0x23, 0x05);

// for Core2 v1.1 (AXP2101+INA3221)
if (Ina3221[0].begin())
Expand Down Expand Up @@ -1299,7 +1303,42 @@ namespace m5
}
}
if (!cancel) {
result = Axp2101.setBLDO2(enable * 3300);
if (enable) {
result = Axp2101.setBLDO2(3300);
break;
}
// Core2 v1.1: BLDO2 drives both the boost enable and the /EN of the
// switch that ties USB VBUS to the 5V bus. While BLDO2 falls the switch
// closes before the boost stops, and the boost output feeds back into
// VBUS -> PMIC -> boost. With no battery this sags VSYS and the AXP2101
// powers off on DCDC under-voltage (latched until the power key).
// Suspending that power-off for the transition turns it into an ESP32
// brownout reset instead; begin() re-arms it after such a reset.
// (A Tough with the AXP2101 shares this path; the suspend is harmless there.)
uint8_t r90, r23 = 0;
if (!Axp2101.readRegister(0x90, &r90, 1)) { r90 = 0xFF; } // unreadable: assume a transition
bool transition = (r90 & (1 << 5)) != 0;
bool suspended = false;
if (transition) {
// Fail closed: when the power-off cannot be suspended the output is left as is.
if (!Axp2101.readRegister(0x23, &r23, 1)) {
ESP_LOGW("Power", "setExtOutput(false): protection register unreadable, refused.");
break;
}
suspended = (r23 & 0x05) != 0;
if (suspended && !Axp2101.writeRegister8(0x23, r23 & ~0x05)) {
ESP_LOGW("Power", "setExtOutput(false): could not suspend the DCDC UVP power-off, refused.");
break;
}
}
result = Axp2101.setBLDO2(0);
if (suspended) {
m5gfx::delay(20); // the transition completes within 10 ms (measured)
if (!Axp2101.writeRegister8(0x23, r23)) {
ESP_LOGW("Power", "setExtOutput(false): DCDC UVP power-off not re-armed.");
result = false;
}
}
break;
}
} else {
Expand Down
Loading