1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-26 18:02:35 +00:00

fix(core): remove ULTRA_POWER_SAVE and STARTUP_REJECTED states, improve battery low state detection [no changelog]

This commit is contained in:
kopecdav 2025-05-05 13:20:02 +02:00 committed by kopecdav
parent 19948372c7
commit 3beebe5956
4 changed files with 41 additions and 78 deletions

View File

@ -45,15 +45,15 @@ pm_status_t pm_init(bool skip_bootup_sequence) {
return PM_OK; return PM_OK;
} }
// Clear driver instance
memset(drv, 0, sizeof(pm_driver_t));
// Initialize hardware subsystems // Initialize hardware subsystems
if (!npm1300_init() || !stwlc38_init()) { if (!npm1300_init() || !stwlc38_init()) {
pm_deinit(); pm_deinit();
return PM_ERROR; return PM_ERROR;
} }
// Clear fuel gauge state
memset(&drv->fuel_gauge, 0, sizeof(fuel_gauge_state_t));
// Initialize fuel gauge // Initialize fuel gauge
fuel_gauge_init(&(drv->fuel_gauge), PM_FUEL_GAUGE_R, PM_FUEL_GAUGE_Q, fuel_gauge_init(&(drv->fuel_gauge), PM_FUEL_GAUGE_R, PM_FUEL_GAUGE_Q,
PM_FUEL_GAUGE_R_AGGRESSIVE, PM_FUEL_GAUGE_Q_AGGRESSIVE, PM_FUEL_GAUGE_R_AGGRESSIVE, PM_FUEL_GAUGE_Q_AGGRESSIVE,
@ -227,6 +227,15 @@ pm_status_t pm_turn_on(void) {
return PM_NOT_INITIALIZED; return PM_NOT_INITIALIZED;
} }
// Poll until at least single PMIC measurement is done
while(drv->pmic_last_update_ms == 0){
}
if(drv->pmic_data.usb_status == 0x0 &&
drv->pmic_data.vbat < PM_BATTERY_UNDERVOLT_RECOVERY_THR_V){
return PM_REQUEST_REJECTED;
}
drv->request_turn_on = true; drv->request_turn_on = true;
pm_process_state_machine(); pm_process_state_machine();
@ -320,8 +329,15 @@ pm_status_t pm_store_data_to_backup_ram(void) {
} }
backup_ram_power_manager_data_t pm_data = {0}; backup_ram_power_manager_data_t pm_data = {0};
if (drv->battery_critical) {
pm_data.soc = 0;
} else {
pm_data.soc = drv->fuel_gauge.soc;
}
pm_data.bat_critical = drv->battery_critical;
pm_data.bootloader_exit_state = drv->state; pm_data.bootloader_exit_state = drv->state;
pm_data.soc = drv->fuel_gauge.soc;
backup_ram_status_t status = backup_ram_store_power_manager_data(&pm_data); backup_ram_status_t status = backup_ram_store_power_manager_data(&pm_data);

View File

@ -31,10 +31,10 @@
#define PM_TIMER_PERIOD_MS 300 #define PM_TIMER_PERIOD_MS 300
#define PM_BATTERY_SAMPLING_PERIOD_MS 100 #define PM_BATTERY_SAMPLING_PERIOD_MS 100
#define PM_SHUTDOWN_TIMEOUT_MS 15000 #define PM_SHUTDOWN_TIMEOUT_MS 15000
#define PM_BATTERY_UNDERVOLT_THRESHOLD_V 3.0f #define PM_BATTERY_UNDERVOLT_THR_V 3.0f
#define PM_BATTERY_UNDERVOLT_HYSTERESIS_V 0.5f #define PM_BATTERY_UNDERVOLT_RECOVERY_THR_V 3.3f
#define PM_BATTERY_LOW_THRESHOLD_V 3.15f #define PM_BATTERY_LOW_THRESHOLD_SOC 15
#define PM_BATTERY_LOW_RECOVERY_V 3.2f
#define PM_BATTERY_SAMPLING_BUF_SIZE 10 #define PM_BATTERY_SAMPLING_BUF_SIZE 10
#define PM_WPC_CHARGE_CURR_STEP_MA 50 #define PM_WPC_CHARGE_CURR_STEP_MA 50
@ -50,22 +50,13 @@
#define PM_CLEAR_EVENT(flags, event) ((flags) &= ~(event)) #define PM_CLEAR_EVENT(flags, event) ((flags) &= ~(event))
#define PM_CLEAR_ALL_EVENTS(flags) ((flags) = 0) #define PM_CLEAR_ALL_EVENTS(flags) ((flags) = 0)
/* Power manager states */
#define PM_STATE_LIST(STATE) \
STATE(HIBERNATE) \
STATE(CHARGING) \
STATE(STARTUP_REJECTED) \
STATE(SUSPEND) \
STATE(ULTRA_POWER_SAVE) \
STATE(SHUTTING_DOWN) \
STATE(POWER_SAVE) \
STATE(ACTIVE)
typedef enum { typedef enum {
#define STATE(name) PM_STATE_##name, PM_STATE_HIBERNATE,
PM_STATE_LIST(STATE) PM_STATE_CHARGING,
#undef STATE PM_STATE_SUSPEND,
PM_STATE_COUNT PM_STATE_SHUTTING_DOWN,
PM_STATE_POWER_SAVE,
PM_STATE_ACTIVE,
} pm_internal_state_t; } pm_internal_state_t;
// Power manager battery sampling data structure) // Power manager battery sampling data structure)

View File

@ -44,6 +44,7 @@ void pm_monitor_power_sources(void) {
drv->fuel_gauge_request_new_guess = false; drv->fuel_gauge_request_new_guess = false;
} else { } else {
fuel_gauge_update(&drv->fuel_gauge, PM_BATTERY_SAMPLING_PERIOD_MS, fuel_gauge_update(&drv->fuel_gauge, PM_BATTERY_SAMPLING_PERIOD_MS,
drv->pmic_data.vbat, drv->pmic_data.ibat, drv->pmic_data.vbat, drv->pmic_data.ibat,
@ -94,19 +95,18 @@ void pm_monitor_power_sources(void) {
} }
// Check battery voltage for critical (undervoltage) threshold // Check battery voltage for critical (undervoltage) threshold
if ((drv->pmic_data.vbat < PM_BATTERY_UNDERVOLT_THRESHOLD_V) && if ((drv->pmic_data.vbat < PM_BATTERY_UNDERVOLT_THR_V) &&
!drv->battery_critical) { !drv->battery_critical) {
drv->battery_critical = true; drv->battery_critical = true;
} else if (drv->pmic_data.vbat > (PM_BATTERY_UNDERVOLT_THRESHOLD_V + } else if (drv->pmic_data.vbat > (PM_BATTERY_UNDERVOLT_RECOVERY_THR_V) &&
PM_BATTERY_UNDERVOLT_HYSTERESIS_V) &&
drv->battery_critical) { drv->battery_critical) {
drv->battery_critical = false; drv->battery_critical = false;
} }
// Check battery voltage for low threshold // Check battery voltage for low threshold
if (drv->pmic_data.vbat < PM_BATTERY_LOW_THRESHOLD_V && !drv->battery_low) { if (drv->soc_ceiled <= PM_BATTERY_LOW_THRESHOLD_SOC && !drv->battery_low) {
drv->battery_low = true; drv->battery_low = true;
} else if (drv->pmic_data.vbat > PM_BATTERY_LOW_RECOVERY_V && } else if (drv->soc_ceiled > PM_BATTERY_LOW_THRESHOLD_SOC &&
drv->battery_low) { drv->battery_low) {
drv->battery_low = false; drv->battery_low = false;
} }

View File

@ -21,9 +21,6 @@
#ifdef USE_BUTTON #ifdef USE_BUTTON
#include <io/button.h> #include <io/button.h>
#endif #endif
#ifdef USE_RGB_LED
#include <io/rgb_led.h>
#endif
#include <sys/bootutils.h> #include <sys/bootutils.h>
#include <sys/systick.h> #include <sys/systick.h>
#include <sys/systimer.h> #include <sys/systimer.h>
@ -45,12 +42,6 @@ static const pm_state_handler_t state_handlers[] = {
.handle = pm_handle_state_power_save, .handle = pm_handle_state_power_save,
.exit = NULL, .exit = NULL,
}, },
[PM_STATE_ULTRA_POWER_SAVE] =
{
.enter = NULL,
.handle = pm_handle_state_ultra_power_save,
.exit = NULL,
},
[PM_STATE_SHUTTING_DOWN] = [PM_STATE_SHUTTING_DOWN] =
{ {
.enter = pm_enter_shutting_down, .enter = pm_enter_shutting_down,
@ -63,17 +54,11 @@ static const pm_state_handler_t state_handlers[] = {
.handle = pm_handle_state_suspend, .handle = pm_handle_state_suspend,
.exit = NULL, .exit = NULL,
}, },
[PM_STATE_STARTUP_REJECTED] =
{
.enter = NULL,
.handle = pm_handle_state_startup_rejected,
.exit = NULL,
},
[PM_STATE_CHARGING] = [PM_STATE_CHARGING] =
{ {
.enter = pm_enter_charging, .enter = NULL,
.handle = pm_handle_state_charging, .handle = pm_handle_state_charging,
.exit = pm_exit_charging, .exit = NULL,
}, },
[PM_STATE_HIBERNATE] = [PM_STATE_HIBERNATE] =
{ {
@ -184,17 +169,6 @@ pm_internal_state_t pm_handle_state_power_save(pm_driver_t* drv) {
return drv->state; return drv->state;
} }
pm_internal_state_t pm_handle_state_ultra_power_save(pm_driver_t* drv) {
// Go to power save if external power or battery above critical
if (drv->usb_connected || !drv->battery_critical) {
return PM_STATE_POWER_SAVE;
} else {
return PM_STATE_STARTUP_REJECTED;
}
return drv->state;
}
pm_internal_state_t pm_handle_state_shutting_down(pm_driver_t* drv) { pm_internal_state_t pm_handle_state_shutting_down(pm_driver_t* drv) {
// Return to power save if external power or battery recovered // Return to power save if external power or battery recovered
if (drv->usb_connected || !drv->battery_critical) { if (drv->usb_connected || !drv->battery_critical) {
@ -227,20 +201,11 @@ pm_internal_state_t pm_handle_state_startup_rejected(pm_driver_t* drv) {
return drv->state; return drv->state;
} }
void pm_enter_charging(pm_driver_t* drv) {
#ifdef USE_RGB_LED
// Initialize RGB
rgb_led_init();
rgb_led_set_color(0x0000FF);
#endif
}
pm_internal_state_t pm_handle_state_charging(pm_driver_t* drv) { pm_internal_state_t pm_handle_state_charging(pm_driver_t* drv) {
if (drv->request_turn_on) { if (drv->request_turn_on) {
drv->request_turn_on = false; drv->request_turn_on = false;
return PM_STATE_ULTRA_POWER_SAVE; return PM_STATE_POWER_SAVE;
} }
// Go back to hibernate if external power was removed. // Go back to hibernate if external power was removed.
@ -260,19 +225,12 @@ pm_internal_state_t pm_handle_state_charging(pm_driver_t* drv) {
return drv->state; return drv->state;
} }
void pm_exit_charging(pm_driver_t* drv) {
#ifdef USE_RGB_LED
// Turn off RGB LED
rgb_led_set_color(0x0);
#endif
}
pm_internal_state_t pm_handle_state_hibernate(pm_driver_t* drv) { pm_internal_state_t pm_handle_state_hibernate(pm_driver_t* drv) {
if (drv->request_turn_on) { if (drv->request_turn_on) {
drv->request_turn_on = false; drv->request_turn_on = false;
return PM_STATE_ULTRA_POWER_SAVE; return PM_STATE_POWER_SAVE;
} }
// External power source, start charging // External power source, start charging
@ -298,8 +256,6 @@ void pm_enter_report_low_battery(pm_driver_t* drv) {
// Set backlight to minimum // Set backlight to minimum
backlight_set_max_level(0); backlight_set_max_level(0);
// Set RGB LED to red
// rgb_led_set_color(RGB_LED_COLOR_RED);
} }
void pm_enter_shutting_down(pm_driver_t* drv) { void pm_enter_shutting_down(pm_driver_t* drv) {