enable high-efficiency low power regulator

This commit is contained in:
Joey Castillo 2022-02-13 14:15:00 -05:00
parent 203850104d
commit b91f025542
3 changed files with 26 additions and 6 deletions

View File

@ -27,7 +27,13 @@
// receives interrupts from MCLK, OSC32KCTRL, OSCCTRL, PAC, PM, SUPC and TAL, whatever that is.
void SYSTEM_Handler(void) {
if (SUPC->INTFLAG.bit.BOD33DET) {
// Our system voltage has dipped below 2.6V!
// Set the voltage regulator to work at low system voltage before we hit 2.5 V
// This voltage regulator can carry us down to 1.62 volts as the battery drains.
SUPC->VREG.bit.LPEFF = 0;
// clear the interrupt condition
SUPC->INTENCLR.bit.BOD33DET = 1;
// and disable the brownout detector (TODO: add a second, "power critical" brownout condition?)
SUPC->INTFLAG.reg &= ~SUPC_INTFLAG_BOD33DET;
}
}

View File

@ -155,8 +155,10 @@ void watch_enter_sleep_mode(void) {
// disable tick interrupt
watch_rtc_disable_all_periodic_callbacks();
// disable brownout detector interrupt, which could inadvertently wake us up.
SUPC->INTENCLR.bit.BOD33DET = 1;
// set brownout detector to check voltage once an hour (64 minutes).
// in sleep, we're not worried about the LED causing a voltage drop and a brownout.
// changes to voltage will take place slowly over months, not quickly over seconds.
SUPC->BOD33.bit.PSEL = 0xF;
// disable all pins
_watch_disable_all_pins_except_rtc();
@ -164,8 +166,8 @@ void watch_enter_sleep_mode(void) {
// enter standby (4); we basically hang out here until an interrupt wakes us.
sleep(4);
// and we awake! re-enable the brownout detector
SUPC->INTENSET.bit.BOD33DET = 1;
// and we awake! speed the brownout detector back up to 1 check per second.
SUPC->BOD33.bit.PSEL = 0x9;
// call app_setup so the app can re-enable everything we disabled.
app_setup();

View File

@ -37,6 +37,18 @@ void _watch_init(void) {
SUPC->VREG.bit.SEL = 1;
while(!SUPC->STATUS.bit.VREGRDY);
// check the battery voltage...
watch_enable_adc();
uint16_t battery_voltage = watch_get_vcc_voltage();
watch_disable_adc();
// ...because we can enable the more efficient low power regulator if the system voltage is > 2.5V
// still, enable LPEFF only if the battery voltage is comfortably above this threshold.
if (battery_voltage >= 2700) {
SUPC->VREG.bit.LPEFF = 1;
} else {
SUPC->VREG.bit.LPEFF = 0;
}
// set up the brownout detector (low battery warning)
NVIC_DisableIRQ(SYSTEM_IRQn);
NVIC_ClearPendingIRQ(SYSTEM_IRQn);
@ -47,8 +59,8 @@ void _watch_init(void) {
SUPC->BOD33.bit.RUNSTDBY = 1; // Enable sampling mode in standby
SUPC->BOD33.bit.STDBYCFG = 1; // Run in standby
SUPC->BOD33.bit.RUNBKUP = 0; // Don't run in backup mode
SUPC->BOD33.bit.PSEL = 0xB; // Check battery level every 4 seconds
SUPC->BOD33.bit.LEVEL = 31; // Detect brownout at 2.5V (1.445V + level * 34mV)
SUPC->BOD33.bit.PSEL = 0x9; // Check battery level every second (we'll change this before entering sleep)
SUPC->BOD33.bit.LEVEL = 34; // Detect brownout at 2.6V (1.445V + level * 34mV)
SUPC->BOD33.bit.ACTION = 0x2; // Generate an interrupt when BOD33 is triggered
SUPC->BOD33.bit.HYST = 0; // Disable hysteresis
while(!SUPC->STATUS.bit.B33SRDY);