diff --git a/core/embed/sys/power_manager/stm32u5/power_manager.c b/core/embed/sys/power_manager/stm32u5/power_manager.c index c9ad5996ba..5ce23889f4 100644 --- a/core/embed/sys/power_manager/stm32u5/power_manager.c +++ b/core/embed/sys/power_manager/stm32u5/power_manager.c @@ -45,15 +45,15 @@ pm_status_t pm_init(bool skip_bootup_sequence) { return PM_OK; } + // Clear driver instance + memset(drv, 0, sizeof(pm_driver_t)); + // Initialize hardware subsystems if (!npm1300_init() || !stwlc38_init()) { pm_deinit(); return PM_ERROR; } - // Clear fuel gauge state - memset(&drv->fuel_gauge, 0, sizeof(fuel_gauge_state_t)); - // Initialize fuel gauge fuel_gauge_init(&(drv->fuel_gauge), PM_FUEL_GAUGE_R, PM_FUEL_GAUGE_Q, 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; } + // 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; 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}; + + 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.soc = drv->fuel_gauge.soc; backup_ram_status_t status = backup_ram_store_power_manager_data(&pm_data); diff --git a/core/embed/sys/power_manager/stm32u5/power_manager_internal.h b/core/embed/sys/power_manager/stm32u5/power_manager_internal.h index 0f88cc7956..d2ece22a29 100644 --- a/core/embed/sys/power_manager/stm32u5/power_manager_internal.h +++ b/core/embed/sys/power_manager/stm32u5/power_manager_internal.h @@ -31,10 +31,10 @@ #define PM_TIMER_PERIOD_MS 300 #define PM_BATTERY_SAMPLING_PERIOD_MS 100 #define PM_SHUTDOWN_TIMEOUT_MS 15000 -#define PM_BATTERY_UNDERVOLT_THRESHOLD_V 3.0f -#define PM_BATTERY_UNDERVOLT_HYSTERESIS_V 0.5f -#define PM_BATTERY_LOW_THRESHOLD_V 3.15f -#define PM_BATTERY_LOW_RECOVERY_V 3.2f +#define PM_BATTERY_UNDERVOLT_THR_V 3.0f +#define PM_BATTERY_UNDERVOLT_RECOVERY_THR_V 3.3f +#define PM_BATTERY_LOW_THRESHOLD_SOC 15 + #define PM_BATTERY_SAMPLING_BUF_SIZE 10 #define PM_WPC_CHARGE_CURR_STEP_MA 50 @@ -50,22 +50,13 @@ #define PM_CLEAR_EVENT(flags, event) ((flags) &= ~(event)) #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 { -#define STATE(name) PM_STATE_##name, - PM_STATE_LIST(STATE) -#undef STATE - PM_STATE_COUNT + PM_STATE_HIBERNATE, + PM_STATE_CHARGING, + PM_STATE_SUSPEND, + PM_STATE_SHUTTING_DOWN, + PM_STATE_POWER_SAVE, + PM_STATE_ACTIVE, } pm_internal_state_t; // Power manager battery sampling data structure) diff --git a/core/embed/sys/power_manager/stm32u5/power_monitoring.c b/core/embed/sys/power_manager/stm32u5/power_monitoring.c index affc153b78..c040b0477d 100644 --- a/core/embed/sys/power_manager/stm32u5/power_monitoring.c +++ b/core/embed/sys/power_manager/stm32u5/power_monitoring.c @@ -44,6 +44,7 @@ void pm_monitor_power_sources(void) { drv->fuel_gauge_request_new_guess = false; + } else { fuel_gauge_update(&drv->fuel_gauge, PM_BATTERY_SAMPLING_PERIOD_MS, 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 - 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 = true; - } else if (drv->pmic_data.vbat > (PM_BATTERY_UNDERVOLT_THRESHOLD_V + - PM_BATTERY_UNDERVOLT_HYSTERESIS_V) && + } else if (drv->pmic_data.vbat > (PM_BATTERY_UNDERVOLT_RECOVERY_THR_V) && drv->battery_critical) { drv->battery_critical = false; } // 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; - } 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 = false; } diff --git a/core/embed/sys/power_manager/stm32u5/power_states.c b/core/embed/sys/power_manager/stm32u5/power_states.c index 1243db9c04..30a1016e04 100644 --- a/core/embed/sys/power_manager/stm32u5/power_states.c +++ b/core/embed/sys/power_manager/stm32u5/power_states.c @@ -21,9 +21,6 @@ #ifdef USE_BUTTON #include #endif -#ifdef USE_RGB_LED -#include -#endif #include #include #include @@ -45,12 +42,6 @@ static const pm_state_handler_t state_handlers[] = { .handle = pm_handle_state_power_save, .exit = NULL, }, - [PM_STATE_ULTRA_POWER_SAVE] = - { - .enter = NULL, - .handle = pm_handle_state_ultra_power_save, - .exit = NULL, - }, [PM_STATE_SHUTTING_DOWN] = { .enter = pm_enter_shutting_down, @@ -63,17 +54,11 @@ static const pm_state_handler_t state_handlers[] = { .handle = pm_handle_state_suspend, .exit = NULL, }, - [PM_STATE_STARTUP_REJECTED] = - { - .enter = NULL, - .handle = pm_handle_state_startup_rejected, - .exit = NULL, - }, [PM_STATE_CHARGING] = { - .enter = pm_enter_charging, + .enter = NULL, .handle = pm_handle_state_charging, - .exit = pm_exit_charging, + .exit = NULL, }, [PM_STATE_HIBERNATE] = { @@ -184,17 +169,6 @@ pm_internal_state_t pm_handle_state_power_save(pm_driver_t* drv) { 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) { // Return to power save if external power or battery recovered 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; } -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) { + if (drv->request_turn_on) { 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. @@ -260,19 +225,12 @@ pm_internal_state_t pm_handle_state_charging(pm_driver_t* drv) { 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) { + if (drv->request_turn_on) { drv->request_turn_on = false; - return PM_STATE_ULTRA_POWER_SAVE; + return PM_STATE_POWER_SAVE; } // External power source, start charging @@ -298,8 +256,6 @@ void pm_enter_report_low_battery(pm_driver_t* drv) { // Set backlight to minimum 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) {