mirror of
https://github.com/meshtastic/firmware.git
synced 2026-05-19 14:25:28 -04:00
Detach power interrupts for sleep (#10230)
* Detach power interrupts for sleep * Gate PMU IRQ behind a found PMU
This commit is contained in:
129
src/Power.cpp
129
src/Power.cpp
@@ -746,37 +746,17 @@ bool Power::setup()
|
||||
found = true;
|
||||
#endif
|
||||
}
|
||||
#ifdef EXT_PWR_DETECT
|
||||
attachInterrupt(
|
||||
EXT_PWR_DETECT,
|
||||
[]() {
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
},
|
||||
CHANGE);
|
||||
#endif
|
||||
#ifdef BATTERY_CHARGING_INV
|
||||
attachInterrupt(
|
||||
BATTERY_CHARGING_INV,
|
||||
[]() {
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
},
|
||||
CHANGE);
|
||||
#endif
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
attachInterrupt(
|
||||
EXT_CHRG_DETECT,
|
||||
[]() {
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
BaseType_t higherWake = 0;
|
||||
},
|
||||
CHANGE);
|
||||
#endif
|
||||
attachPowerInterrupts();
|
||||
enabled = found;
|
||||
low_voltage_counter = 0;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Register callbacks for before and after lightsleep
|
||||
// Used to detach and reattach interrupts
|
||||
lsObserver.observe(¬ifyLightSleep);
|
||||
lsEndObserver.observe(¬ifyLightSleepEnd);
|
||||
#endif
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -1055,6 +1035,97 @@ int32_t Power::runOnce()
|
||||
return (statusHandler && statusHandler->isInitialized()) ? (1000 * 20) : RUN_SAME;
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
|
||||
// Detach our class' interrupts before lightsleep
|
||||
// Allows sleep.cpp to configure its own interrupts, which wake the device on user-button press
|
||||
int Power::beforeLightSleep(void *unused)
|
||||
{
|
||||
LOG_WARN("Detaching power interrupts for sleep");
|
||||
detachPowerInterrupts();
|
||||
return 0; // Indicates success
|
||||
}
|
||||
|
||||
// Reconfigure our interrupts
|
||||
// Our class' interrupts were disconnected during sleep, to allow the user button to wake the device from sleep
|
||||
int Power::afterLightSleep(esp_sleep_wakeup_cause_t cause)
|
||||
{
|
||||
attachPowerInterrupts();
|
||||
return 0; // Indicates success
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Attach (or re-attach) hardware interrupts for power management
|
||||
* Public method. Used outside class when waking from MCU sleep
|
||||
*/
|
||||
void Power::attachPowerInterrupts()
|
||||
{
|
||||
#ifdef EXT_PWR_DETECT
|
||||
attachInterrupt(
|
||||
EXT_PWR_DETECT,
|
||||
[]() {
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
},
|
||||
CHANGE);
|
||||
#endif
|
||||
#ifdef BATTERY_CHARGING_INV
|
||||
attachInterrupt(
|
||||
BATTERY_CHARGING_INV,
|
||||
[]() {
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
},
|
||||
CHANGE);
|
||||
#endif
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
attachInterrupt(
|
||||
EXT_CHRG_DETECT,
|
||||
[]() {
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
BaseType_t higherWake = 0;
|
||||
},
|
||||
CHANGE);
|
||||
#endif
|
||||
#ifdef PMU_IRQ
|
||||
if (PMU) {
|
||||
attachInterrupt(
|
||||
PMU_IRQ,
|
||||
[] {
|
||||
pmu_irq = true;
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
},
|
||||
FALLING);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach the "normal" button interrupts.
|
||||
* Public method. Used before attaching a "wake-on-button" interrupt for MCU sleep
|
||||
*/
|
||||
void Power::detachPowerInterrupts()
|
||||
{
|
||||
#ifdef EXT_PWR_DETECT
|
||||
detachInterrupt(EXT_PWR_DETECT);
|
||||
#endif
|
||||
#ifdef BATTERY_CHARGING_INV
|
||||
detachInterrupt(BATTERY_CHARGING_INV);
|
||||
#endif
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
detachInterrupt(EXT_CHRG_DETECT);
|
||||
#endif
|
||||
#ifdef PMU_IRQ
|
||||
if (PMU) {
|
||||
detachInterrupt(PMU_IRQ);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the power manager chip
|
||||
*
|
||||
@@ -1332,8 +1403,6 @@ bool Power::axpChipInit()
|
||||
}
|
||||
|
||||
pinMode(PMU_IRQ, INPUT);
|
||||
attachInterrupt(
|
||||
PMU_IRQ, [] { pmu_irq = true; }, FALLING);
|
||||
|
||||
// we do not look for AXPXXX_CHARGING_FINISHED_IRQ & AXPXXX_CHARGING_IRQ
|
||||
// because it occurs repeatedly while there is no battery also it could cause
|
||||
|
||||
18
src/power.h
18
src/power.h
@@ -86,7 +86,7 @@ extern RAK9154Sensor rak9154Sensor;
|
||||
extern XPowersLibInterface *PMU;
|
||||
#endif
|
||||
|
||||
class Power : private concurrency::OSThread
|
||||
class Power : public concurrency::OSThread
|
||||
{
|
||||
|
||||
public:
|
||||
@@ -101,6 +101,14 @@ class Power : private concurrency::OSThread
|
||||
void setStatusHandler(meshtastic::PowerStatus *handler) { statusHandler = handler; }
|
||||
const uint16_t OCV[11] = {OCV_ARRAY};
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
int beforeLightSleep(void *unused);
|
||||
int afterLightSleep(esp_sleep_wakeup_cause_t cause);
|
||||
#endif
|
||||
|
||||
void attachPowerInterrupts();
|
||||
void detachPowerInterrupts();
|
||||
|
||||
protected:
|
||||
meshtastic::PowerStatus *statusHandler;
|
||||
|
||||
@@ -125,6 +133,14 @@ class Power : private concurrency::OSThread
|
||||
// open circuit voltage lookup table
|
||||
uint8_t low_voltage_counter;
|
||||
uint32_t lastLogTime = 0;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Get notified when lightsleep begins and ends
|
||||
CallbackObserver<Power, void *> lsObserver = CallbackObserver<Power, void *>(this, &Power::beforeLightSleep);
|
||||
CallbackObserver<Power, esp_sleep_wakeup_cause_t> lsEndObserver =
|
||||
CallbackObserver<Power, esp_sleep_wakeup_cause_t>(this, &Power::afterLightSleep);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_HEAP
|
||||
uint32_t lastheap;
|
||||
#endif
|
||||
|
||||
@@ -497,13 +497,12 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
notifyLightSleepEnd.notifyObservers(cause); // Button interrupts are reattached here
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
if (cause == ESP_SLEEP_WAKEUP_GPIO) {
|
||||
LOG_INFO("Exit light sleep gpio: btn=%d",
|
||||
!digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
LOG_INFO("Exit light sleep gpio");
|
||||
// If we woke because of a GPIO, it's possible power needs to run to handle.
|
||||
power->setIntervalFromNow(0);
|
||||
runASAP = true;
|
||||
} else {
|
||||
LOG_INFO("Exit light sleep cause: %d", cause);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user