diff --git a/core/embed/sys/power_manager/inc/sys/power_manager.h b/core/embed/sys/power_manager/inc/sys/power_manager.h index d1a17ad636..9d5bdc7946 100644 --- a/core/embed/sys/power_manager/inc/sys/power_manager.h +++ b/core/embed/sys/power_manager/inc/sys/power_manager.h @@ -91,7 +91,7 @@ typedef struct { } pm_report_t; /* Public API functions */ -pm_status_t pm_init(bool skip_boot_sequence); +pm_status_t pm_init(bool inherit_state); void pm_deinit(void); pm_status_t pm_get_events(pm_event_t* event_flags); pm_status_t pm_get_state(pm_state_t* state); diff --git a/core/embed/sys/power_manager/stm32u5/power_manager.c b/core/embed/sys/power_manager/stm32u5/power_manager.c index d6e02ab4fd..886ef691f5 100644 --- a/core/embed/sys/power_manager/stm32u5/power_manager.c +++ b/core/embed/sys/power_manager/stm32u5/power_manager.c @@ -38,7 +38,7 @@ static void pm_shutdown_timer_handler(void* context); // API Implementation -pm_status_t pm_init(bool skip_bootup_sequence) { +pm_status_t pm_init(bool inherit_state) { pm_driver_t* drv = &g_pm; if (drv->initialized) { @@ -59,38 +59,6 @@ pm_status_t pm_init(bool skip_bootup_sequence) { PM_FUEL_GAUGE_R_AGGRESSIVE, PM_FUEL_GAUGE_Q_AGGRESSIVE, PM_FUEL_GAUGE_P_INIT); - if (skip_bootup_sequence) { - // Skip bootup sequence and try to recover the power manages state left - // by the bootloader in backup ram. - - backup_ram_power_manager_data_t pm_recovery_data; - backup_ram_status_t status = - backup_ram_read_power_manager_data(&pm_recovery_data); - - if (status != BACKUP_RAM_OK && - (pm_recovery_data.bootloader_exit_state != PM_STATE_POWER_SAVE && - pm_recovery_data.bootloader_exit_state != PM_STATE_ACTIVE)) { - drv->state = PM_STATE_POWER_SAVE; - drv->fuel_gauge_request_new_guess = true; - - } else { - // Backup RAM contain valid data - drv->state = pm_recovery_data.bootloader_exit_state; - fuel_gauge_set_soc(&drv->fuel_gauge,pm_recovery_data.soc); - - } - - drv->fuel_gauge_initialized = true; - - } else { - // Start in lowest state and wait for the bootup sequence to - // finish (call of pm_turn_on()) - drv->state = PM_STATE_HIBERNATE; - drv->initialized = false; - } - - // Disable charging by default - drv->charging_enabled = false; // Create monitoring timer drv->monitoring_timer = systimer_create(pm_monitoring_timer_handler, NULL); @@ -102,7 +70,54 @@ pm_status_t pm_init(bool skip_bootup_sequence) { // Initial power source measurement npm1300_measure(pm_pmic_data_ready, NULL); + + // Try to recover SoC from the backup RAM + backup_ram_power_manager_data_t pm_recovery_data; + backup_ram_status_t status = + backup_ram_read_power_manager_data(&pm_recovery_data); + + if (status == BACKUP_RAM_OK) { + fuel_gauge_set_soc(&drv->fuel_gauge, pm_recovery_data.soc); + } else { + // Wait for 1s to sample battery data + systick_delay_ms(1000); + pm_battery_initial_soc_guess(); + } + + if(inherit_state){ + + // Inherit power manager state left in beckup RAM from bootloader. + // in case of error, start with PM_STATE_POWER_SAVE as a lowest state in + // active mode. + if (status != BACKUP_RAM_OK && + (pm_recovery_data.bootloader_exit_state != PM_STATE_POWER_SAVE && + pm_recovery_data.bootloader_exit_state != PM_STATE_ACTIVE)) { + + drv->state = PM_STATE_POWER_SAVE; + + } else { + + // Backup RAM contain valid data + drv->state = pm_recovery_data.bootloader_exit_state; + + } + + }else{ + + // Start in lowest state and wait for the bootup sequence to + // finish (call of pm_turn_on()) + drv->state = PM_STATE_HIBERNATE; + + } + + // Fuel gauge SoC available, set fuel_gauge initialized. + drv->fuel_gauge_initialized = true; + + // Enable charging by default + drv->charging_enabled = true; + drv->initialized = true; + return PM_OK; } @@ -248,24 +263,9 @@ pm_status_t pm_turn_on(void) { return PM_REQUEST_REJECTED; } - // Try to recover SoC from the backup RAM - backup_ram_power_manager_data_t pm_recovery_data; - backup_ram_status_t status = - backup_ram_read_power_manager_data(&pm_recovery_data); - - if (status == BACKUP_RAM_OK && pm_recovery_data.soc != 0.0f) { - fuel_gauge_set_soc(&drv->fuel_gauge, pm_recovery_data.soc); - } else { - // Wait for 1s to sample battery data - systick_delay_ms(1000); - pm_battery_initial_soc_guess(); - } - // Set monitoiring timer with longer period systimer_set_periodic(drv->monitoring_timer, PM_TIMER_PERIOD_MS); - drv->fuel_gauge_initialized = true; - return PM_OK; } 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 6aa09eef01..91274f3085 100644 --- a/core/embed/sys/power_manager/stm32u5/power_manager_internal.h +++ b/core/embed/sys/power_manager/stm32u5/power_manager_internal.h @@ -75,7 +75,6 @@ typedef struct { // Fuel gauge fuel_gauge_state_t fuel_gauge; bool fuel_gauge_initialized; - bool fuel_gauge_request_new_guess; pm_sampling_data_t bat_sampling_buf[PM_BATTERY_SAMPLING_BUF_SIZE]; uint8_t bat_sampling_buf_tail_idx; uint8_t bat_sampling_buf_head_idx; diff --git a/core/embed/sys/power_manager/stm32u5/power_monitoring.c b/core/embed/sys/power_manager/stm32u5/power_monitoring.c index 8b6b0f9011..72c66ab932 100644 --- a/core/embed/sys/power_manager/stm32u5/power_monitoring.c +++ b/core/embed/sys/power_manager/stm32u5/power_monitoring.c @@ -35,39 +35,6 @@ void pm_monitor_power_sources(void) { return; } - // Update fuel gauge state - if (drv->fuel_gauge_initialized) { - if (drv->fuel_gauge_request_new_guess) { - // Request new single SoC guess based on the latest measurements - fuel_gauge_initial_guess(&drv->fuel_gauge, drv->pmic_data.vbat, - drv->pmic_data.ibat, drv->pmic_data.ntc_temp); - - drv->fuel_gauge_request_new_guess = false; - - - } else { - fuel_gauge_update(&drv->fuel_gauge, drv->pmic_sampling_period_ms, - drv->pmic_data.vbat, drv->pmic_data.ibat, - drv->pmic_data.ntc_temp); - - // Ceil the float soc to user friendly integer - uint8_t soc_ceiled_temp = - (int)(drv->fuel_gauge.soc_latched * 100 + 0.999f); - if (soc_ceiled_temp != drv->soc_ceiled) { - drv->soc_ceiled = soc_ceiled_temp; - PM_SET_EVENT(drv->event_flags, PM_EVENT_SOC_UPDATED); - } - } - - } else { - pm_battery_sampling(drv->pmic_data.vbat, drv->pmic_data.ibat, - drv->pmic_data.ntc_temp); - - // Battery sampling period, collect data before initial guess is made. - fuel_gauge_initial_guess(&drv->fuel_gauge, drv->pmic_data.vbat, - drv->pmic_data.ibat, drv->pmic_data.ntc_temp); - } - // Check USB power source status if (drv->pmic_data.usb_status != 0x0) { if (!drv->usb_connected) { @@ -103,6 +70,35 @@ void pm_monitor_power_sources(void) { drv->battery_critical = false; } + // Run battery charging controller + pm_charging_controller(drv); + + // Fuel gauge not initialized yet, battery SoC not available, + // Sample the battery data into the circular buffer, request new PMIC + if(!drv->fuel_gauge_initialized){ + + pm_battery_sampling(drv->pmic_data.vbat, drv->pmic_data.ibat, + drv->pmic_data.ntc_temp); + + // Request fresh measurements + npm1300_measure(pm_pmic_data_ready, NULL); + drv->pmic_measurement_ready = false; + + return; + + } + + fuel_gauge_update(&drv->fuel_gauge, drv->pmic_sampling_period_ms, + drv->pmic_data.vbat, drv->pmic_data.ibat, + drv->pmic_data.ntc_temp); + + // Ceil the float soc to user friendly integer + uint8_t soc_ceiled_temp = (int)(drv->fuel_gauge.soc_latched * 100 + 0.999f); + if (soc_ceiled_temp != drv->soc_ceiled) { + drv->soc_ceiled = soc_ceiled_temp; + PM_SET_EVENT(drv->event_flags, PM_EVENT_SOC_UPDATED); + } + // Check battery voltage for low threshold if (drv->soc_ceiled <= PM_BATTERY_LOW_THRESHOLD_SOC && !drv->battery_low) { drv->battery_low = true; @@ -111,9 +107,6 @@ void pm_monitor_power_sources(void) { drv->battery_low = false; } - // Run battery charging controller - pm_charging_controller(drv); - // Process state machine with updated battery and power source information pm_process_state_machine();