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

feat(core): store fuel gauge covariance into backup ram [no changelog]

This commit is contained in:
kopecdav 2025-05-07 09:50:37 +02:00 committed by kopecdav
parent ac65d1f59d
commit f050136abb
7 changed files with 30 additions and 28 deletions

View File

@ -148,7 +148,7 @@ backup_ram_status_t backup_ram_erase_unused(void) {
} }
backup_ram_status_t backup_ram_store_power_manager_data( backup_ram_status_t backup_ram_store_power_manager_data(
const backup_ram_power_manager_data_t *pm_data) { const backup_ram_power_manager_data_t *pm_data) {
backup_ram_driver_t *drv = &backup_ram_driver; backup_ram_driver_t *drv = &backup_ram_driver;
if (!drv->initialized) { if (!drv->initialized) {

View File

@ -44,7 +44,8 @@ typedef enum {
* after power loss. * after power loss.
*/ */
typedef struct { typedef struct {
float soc; // Captured state of charge <0, 1> float soc; // Captured fuel gauge state of charge <0, 1>
float P; // Captured fuel gauge covariance
bool bat_critical; bool bat_critical;
// Captures RTC time at which SOC was captured // Captures RTC time at which SOC was captured
uint32_t last_capture_timestamp; uint32_t last_capture_timestamp;

View File

@ -27,11 +27,11 @@ void fuel_gauge_init(fuel_gauge_state_t* state, float R, float Q,
state->Q = Q; state->Q = Q;
state->R_aggressive = R_aggressive; state->R_aggressive = R_aggressive;
state->Q_aggressive = Q_aggressive; state->Q_aggressive = Q_aggressive;
state->P = P_init;
// Initialize state // Initialize state
state->soc = 0.0f; state->soc = 0.0f;
state->soc_latched = 0.0f; state->soc_latched = 0.0f;
state->P = P_init; // Initial error covariance
} }
void fuel_gauge_reset(fuel_gauge_state_t* state) { void fuel_gauge_reset(fuel_gauge_state_t* state) {
@ -40,10 +40,11 @@ void fuel_gauge_reset(fuel_gauge_state_t* state) {
state->soc_latched = 0.0f; state->soc_latched = 0.0f;
} }
void fuel_gauge_set_soc(fuel_gauge_state_t* state, float soc) { void fuel_gauge_set_soc(fuel_gauge_state_t* state, float soc, float P) {
// Set SOC directly // Set SOC directly
state->soc = soc; state->soc = soc;
state->soc_latched = soc; state->soc_latched = soc;
state->P = P; // Set error covariance
} }
void fuel_gauge_initial_guess(fuel_gauge_state_t* state, float voltage_V, void fuel_gauge_initial_guess(fuel_gauge_state_t* state, float voltage_V,

View File

@ -59,7 +59,7 @@ void fuel_gauge_reset(fuel_gauge_state_t* state);
* @param state Pointer to EKF state structure * @param state Pointer to EKF state structure
* @param soc State of charge (0.0 to 1.0) * @param soc State of charge (0.0 to 1.0)
*/ */
void fuel_gauge_set_soc(fuel_gauge_state_t* state, float soc); void fuel_gauge_set_soc(fuel_gauge_state_t* state, float soc, float P);
/** /**
* Make initial SOC guess based on OCV * Make initial SOC guess based on OCV

View File

@ -101,7 +101,7 @@ pm_status_t pm_turn_on(void);
pm_status_t pm_get_report(pm_report_t* report); pm_status_t pm_get_report(pm_report_t* report);
pm_status_t pm_charging_enable(void); pm_status_t pm_charging_enable(void);
pm_status_t pm_charging_disable(void); pm_status_t pm_charging_disable(void);
pm_status_t pm_store_data_to_backup_ram(void); pm_status_t pm_store_data_to_backup_ram();
pm_status_t pm_wait_until_active(uint32_t timeout_ms); pm_status_t pm_wait_until_active(uint32_t timeout_ms);
pm_status_t pm_wakeup_flags_set(pm_wakeup_flags_t flags); pm_status_t pm_wakeup_flags_set(pm_wakeup_flags_t flags);
pm_status_t pm_wakeup_flags_reset(void); pm_status_t pm_wakeup_flags_reset(void);

View File

@ -77,7 +77,7 @@ pm_status_t pm_init(bool inherit_state) {
backup_ram_read_power_manager_data(&pm_recovery_data); backup_ram_read_power_manager_data(&pm_recovery_data);
if (status == BACKUP_RAM_OK) { if (status == BACKUP_RAM_OK) {
fuel_gauge_set_soc(&drv->fuel_gauge, pm_recovery_data.soc); fuel_gauge_set_soc(&drv->fuel_gauge, pm_recovery_data.soc, pm_recovery_data.P);
} else { } else {
// Wait for 1s to sample battery data // Wait for 1s to sample battery data
systick_delay_ms(1000); systick_delay_ms(1000);
@ -228,11 +228,11 @@ pm_status_t pm_hibernate(void) {
drv->request_hibernate = true; drv->request_hibernate = true;
pm_process_state_machine(); pm_process_state_machine();
if (drv->state != PM_STATE_HIBERNATE) { systick_delay_ms(50);
return PM_REQUEST_REJECTED;
} // Whenever hibernation request fall through, request was rejected
return PM_REQUEST_REJECTED;
return PM_OK;
} }
pm_status_t pm_turn_on(void) { pm_status_t pm_turn_on(void) {
@ -324,7 +324,7 @@ pm_status_t pm_charging_disable(void) {
return PM_OK; return PM_OK;
} }
pm_status_t pm_store_data_to_backup_ram(void) { pm_status_t pm_store_data_to_backup_ram() {
pm_driver_t* drv = &g_pm; pm_driver_t* drv = &g_pm;
if (!drv->initialized) { if (!drv->initialized) {
@ -333,12 +333,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};
// Fuel gauge state
if (drv->battery_critical) { if (drv->battery_critical) {
pm_data.soc = 0; pm_data.soc = 0;
} else { } else {
pm_data.soc = drv->fuel_gauge.soc; pm_data.soc = drv->fuel_gauge.soc;
} }
pm_data.P = drv->fuel_gauge.P;
// Power manager state
pm_data.bat_critical = drv->battery_critical; pm_data.bat_critical = drv->battery_critical;
pm_data.bootloader_exit_state = drv->state; pm_data.bootloader_exit_state = drv->state;

View File

@ -105,21 +105,16 @@ void pm_enter_active(pm_driver_t* drv) {
} }
pm_internal_state_t pm_handle_state_active(pm_driver_t* drv) { pm_internal_state_t pm_handle_state_active(pm_driver_t* drv) {
// Handle hibernate request // Handle hibernate request
if (drv->request_hibernate) { if (drv->request_hibernate) {
drv->request_hibernate = false; drv->request_hibernate = false;
return PM_STATE_HIBERNATE; return PM_STATE_HIBERNATE;
} }
// Handle suspend request // Handle suspend request
if (drv->request_suspend) { if (drv->request_suspend) {
drv->request_suspend = false; drv->request_suspend = false;
if (drv->usb_connected || drv->wireless_connected) {
return PM_STATE_CHARGING;
}
return PM_STATE_SUSPEND; return PM_STATE_SUSPEND;
} }
@ -138,21 +133,16 @@ void pm_enter_power_save(pm_driver_t* drv) {
} }
pm_internal_state_t pm_handle_state_power_save(pm_driver_t* drv) { pm_internal_state_t pm_handle_state_power_save(pm_driver_t* drv) {
// Handle hibernate request // Handle hibernate request
if (drv->request_hibernate) { if (drv->request_hibernate) {
drv->request_hibernate = false; drv->request_hibernate = false;
return PM_STATE_HIBERNATE; return PM_STATE_HIBERNATE;
} }
// Handle suspend request // Handle suspend request
if (drv->request_suspend) { if (drv->request_suspend) {
drv->request_suspend = false; drv->request_suspend = false;
if (drv->usb_connected || drv->wireless_connected) {
return PM_STATE_CHARGING;
}
return PM_STATE_SUSPEND; return PM_STATE_SUSPEND;
} }
@ -170,6 +160,13 @@ pm_internal_state_t pm_handle_state_power_save(pm_driver_t* drv) {
} }
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) {
// System is shutting down, but user can still hibernate the device early.
if (drv->request_hibernate) {
drv->request_hibernate = false;
return PM_STATE_HIBERNATE;
}
// 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) {
return PM_STATE_POWER_SAVE; return PM_STATE_POWER_SAVE;
@ -253,6 +250,7 @@ pm_internal_state_t pm_handle_state_hibernate(pm_driver_t* drv) {
// State enter/exit actions // State enter/exit actions
void pm_enter_report_low_battery(pm_driver_t* drv) { 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);
@ -273,15 +271,14 @@ void pm_exit_shutting_down(pm_driver_t* drv) {
void pm_enter_suspend(pm_driver_t* drv) { void pm_enter_suspend(pm_driver_t* drv) {
pm_control_suspend(); pm_control_suspend();
// Not implemented yet
} }
void pm_enter_hibernate(pm_driver_t* drv) { void pm_enter_hibernate(pm_driver_t* drv) {
// TODO: Store power manager data with request to hibernate // Store power manager data with request to hibernate, power manager
// after reboot? // will try to hibernate immediately after reboot.
pm_store_data_to_backup_ram(); pm_store_data_to_backup_ram();
reboot_device(); reboot_device();
} }