@@ -858,6 +858,10 @@ namespace m5
858858 // , 0x18, 0x0E
859859 };
860860 Axp2101.writeRegister8Array (reg_data_array, sizeof (reg_data_array));
861+ // Re-arm the DCDC1/DCDC3 under-voltage power-off that setExtOutput(false)
862+ // suspends; an ESP32 brownout reset during that call skips the restore.
863+ // Forced like the table above: these bits are the chip default.
864+ Axp2101.bitOn (0x23 , 0x05 );
861865
862866 // for Core2 v1.1 (AXP2101+INA3221)
863867 if (Ina3221[0 ].begin ())
@@ -1189,7 +1193,41 @@ namespace m5
11891193 if (_pmic == pmic_axp2101) {
11901194 cancel = (enable && (Ina3221[0 ].getShuntVoltage (0 ) < 0 .0f || Ina3221[0 ].getShuntVoltage (1 ) < 0 .0f ) && (8 >= Axp2101.getBatteryLevel ()));
11911195 if (!cancel) {
1192- Axp2101.setBLDO2 (enable * 3300 );
1196+ if (enable) {
1197+ Axp2101.setBLDO2 (3300 );
1198+ break ;
1199+ }
1200+ // Core2 v1.1: BLDO2 drives both the boost enable and the /EN of the
1201+ // switch that ties USB VBUS to the 5V bus. While BLDO2 falls the switch
1202+ // closes before the boost stops, and the boost output feeds back into
1203+ // VBUS -> PMIC -> boost. With no battery this sags VSYS and the AXP2101
1204+ // powers off on DCDC under-voltage (latched until the power key).
1205+ // Suspending that power-off for the transition turns it into an ESP32
1206+ // brownout reset instead; begin() re-arms it after such a reset.
1207+ // (A Tough with the AXP2101 shares this path; the suspend is harmless there.)
1208+ uint8_t r90, r23 = 0 ;
1209+ if (!Axp2101.readRegister (0x90 , &r90, 1 )) { r90 = 0xFF ; } // unreadable: assume a transition
1210+ bool transition = (r90 & (1 << 5 )) != 0 ;
1211+ bool suspended = false ;
1212+ if (transition) {
1213+ // Fail closed: when the power-off cannot be suspended the output is left as is.
1214+ if (!Axp2101.readRegister (0x23 , &r23, 1 )) {
1215+ ESP_LOGW (" Power" , " setExtOutput(false): protection register unreadable, refused." );
1216+ break ;
1217+ }
1218+ suspended = (r23 & 0x05 ) != 0 ;
1219+ if (suspended && !Axp2101.writeRegister8 (0x23 , r23 & ~0x05 )) {
1220+ ESP_LOGW (" Power" , " setExtOutput(false): could not suspend the DCDC UVP power-off, refused." );
1221+ break ;
1222+ }
1223+ }
1224+ Axp2101.setBLDO2 (0 );
1225+ if (suspended) {
1226+ m5gfx::delay (20 ); // the transition completes within 10 ms (measured)
1227+ if (!Axp2101.writeRegister8 (0x23 , r23)) {
1228+ ESP_LOGW (" Power" , " setExtOutput(false): DCDC UVP power-off not re-armed." );
1229+ }
1230+ }
11931231 break ;
11941232 }
11951233 } else {
0 commit comments