mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-26 09:52:34 +00:00
feat(core): integrate data recovery from backup ram
[no changelog]
This commit is contained in:
parent
e1503eee53
commit
ae92ae09d5
@ -82,7 +82,7 @@ typedef struct {
|
|||||||
} pm_report_t;
|
} pm_report_t;
|
||||||
|
|
||||||
/* Public API functions */
|
/* Public API functions */
|
||||||
pm_status_t pm_init(bool turned_on);
|
pm_status_t pm_init(bool skip_boot_sequence);
|
||||||
void pm_deinit(void);
|
void pm_deinit(void);
|
||||||
pm_status_t pm_get_events(pm_event_t* event_flags);
|
pm_status_t pm_get_events(pm_event_t* event_flags);
|
||||||
pm_status_t pm_get_state(pm_state_t* state);
|
pm_status_t pm_get_state(pm_state_t* state);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <sys/systick.h>
|
#include <sys/systick.h>
|
||||||
#include <sys/systimer.h>
|
#include <sys/systimer.h>
|
||||||
#include <trezor_rtl.h>
|
#include <trezor_rtl.h>
|
||||||
|
#include <sys/backup_ram.h>
|
||||||
|
|
||||||
#include "../../powerctl/npm1300/npm1300.h"
|
#include "../../powerctl/npm1300/npm1300.h"
|
||||||
#include "../../powerctl/stwlc38/stwlc38.h"
|
#include "../../powerctl/stwlc38/stwlc38.h"
|
||||||
@ -37,7 +38,7 @@ static void pm_shutdown_timer_handler(void* context);
|
|||||||
|
|
||||||
// API Implementation
|
// API Implementation
|
||||||
|
|
||||||
pm_status_t pm_init(bool turned_on) {
|
pm_status_t pm_init(bool skip_bootup_sequence) {
|
||||||
pm_driver_t* drv = &g_pm;
|
pm_driver_t* drv = &g_pm;
|
||||||
|
|
||||||
if (drv->initialized) {
|
if (drv->initialized) {
|
||||||
@ -58,10 +59,41 @@ pm_status_t pm_init(bool turned_on) {
|
|||||||
PM_FUEL_GAUGE_R_AGGRESSIVE, PM_FUEL_GAUGE_Q_AGGRESSIVE,
|
PM_FUEL_GAUGE_R_AGGRESSIVE, PM_FUEL_GAUGE_Q_AGGRESSIVE,
|
||||||
PM_FUEL_GAUGE_P_INIT);
|
PM_FUEL_GAUGE_P_INIT);
|
||||||
|
|
||||||
if (turned_on) {
|
|
||||||
|
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->state = PM_STATE_POWER_SAVE;
|
||||||
} else {
|
drv->fuel_gauge_request_new_guess = true;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
// Backup RAM contain valid data
|
||||||
|
drv->state = pm_recovery_data.bootloader_exit_state;
|
||||||
|
drv->fuel_gauge.soc = pm_recovery_data.soc;
|
||||||
|
drv->fuel_gauge_request_new_guess = false;
|
||||||
|
drv->fuel_gauge_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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->state = PM_STATE_HIBERNATE;
|
||||||
|
drv->initialized = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable charging by default
|
// Disable charging by default
|
||||||
@ -206,12 +238,22 @@ pm_status_t pm_turn_on(void) {
|
|||||||
|
|
||||||
irq_key_t irq_key = irq_lock();
|
irq_key_t irq_key = irq_lock();
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
drv->fuel_gauge.soc = pm_recovery_data.soc;
|
||||||
|
} else {
|
||||||
pm_battery_initial_soc_guess();
|
pm_battery_initial_soc_guess();
|
||||||
|
}
|
||||||
|
|
||||||
// Set monitoiring timer with longer period
|
// Set monitoiring timer with longer period
|
||||||
systimer_set_periodic(drv->monitoring_timer, PM_TIMER_PERIOD_MS);
|
systimer_set_periodic(drv->monitoring_timer, PM_TIMER_PERIOD_MS);
|
||||||
|
|
||||||
drv->fuel_gauge_initialized = true;
|
drv->fuel_gauge_initialized = true;
|
||||||
|
|
||||||
irq_unlock(irq_key);
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
return PM_OK;
|
return PM_OK;
|
||||||
|
@ -84,6 +84,7 @@ typedef struct {
|
|||||||
// Fuel gauge
|
// Fuel gauge
|
||||||
fuel_gauge_state_t fuel_gauge;
|
fuel_gauge_state_t fuel_gauge;
|
||||||
bool fuel_gauge_initialized;
|
bool fuel_gauge_initialized;
|
||||||
|
bool fuel_gauge_request_new_guess;
|
||||||
pm_sampling_data_t bat_sampling_buf[PM_BATTERY_SAMPLING_BUF_SIZE];
|
pm_sampling_data_t bat_sampling_buf[PM_BATTERY_SAMPLING_BUF_SIZE];
|
||||||
uint8_t bat_sampling_buf_tail_idx;
|
uint8_t bat_sampling_buf_tail_idx;
|
||||||
uint8_t bat_sampling_buf_head_idx;
|
uint8_t bat_sampling_buf_head_idx;
|
||||||
@ -134,6 +135,7 @@ void pm_pmic_data_ready(void* context, npm1300_report_t* report);
|
|||||||
void pm_charging_controller(pm_driver_t* drv);
|
void pm_charging_controller(pm_driver_t* drv);
|
||||||
void pm_battery_sampling(float vbat, float ibat, float ntc_temp);
|
void pm_battery_sampling(float vbat, float ibat, float ntc_temp);
|
||||||
void pm_battery_initial_soc_guess(void);
|
void pm_battery_initial_soc_guess(void);
|
||||||
|
void pm_store_power_manager_data(pm_driver_t* drv);
|
||||||
|
|
||||||
// State handlers
|
// State handlers
|
||||||
pm_internal_state_t pm_handle_state_active(pm_driver_t* drv);
|
pm_internal_state_t pm_handle_state_active(pm_driver_t* drv);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <sys/systick.h>
|
#include <sys/systick.h>
|
||||||
#include <trezor_rtl.h>
|
#include <trezor_rtl.h>
|
||||||
|
#include <sys/backup_ram.h>
|
||||||
|
|
||||||
#include "../../powerctl/fuel_gauge/fuel_gauge.h"
|
#include "../../powerctl/fuel_gauge/fuel_gauge.h"
|
||||||
#include "../../powerctl/npm1300/npm1300.h"
|
#include "../../powerctl/npm1300/npm1300.h"
|
||||||
@ -36,6 +37,17 @@ void pm_monitor_power_sources(void) {
|
|||||||
|
|
||||||
// Update fuel gauge state
|
// Update fuel gauge state
|
||||||
if (drv->fuel_gauge_initialized) {
|
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, 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,
|
||||||
drv->pmic_data.ntc_temp);
|
drv->pmic_data.ntc_temp);
|
||||||
@ -47,15 +59,21 @@ void pm_monitor_power_sources(void) {
|
|||||||
PM_SET_EVENT(drv->event_flags, PM_EVENT_SOC_UPDATED);
|
PM_SET_EVENT(drv->event_flags, PM_EVENT_SOC_UPDATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
pm_battery_sampling(drv->pmic_data.vbat, drv->pmic_data.ibat,
|
pm_battery_sampling(drv->pmic_data.vbat, drv->pmic_data.ibat,
|
||||||
drv->pmic_data.ntc_temp);
|
drv->pmic_data.ntc_temp);
|
||||||
|
|
||||||
// Battery sampling period, collect data before initial guess is made.
|
// Battery sampling period, collect data before initial guess is made.
|
||||||
fuel_gauge_initial_guess(&drv->fuel_gauge, drv->pmic_data.vbat,
|
fuel_gauge_initial_guess(&drv->fuel_gauge, drv->pmic_data.vbat,
|
||||||
drv->pmic_data.ibat, drv->pmic_data.ntc_temp);
|
drv->pmic_data.ibat, drv->pmic_data.ntc_temp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Check USB power source status
|
// Check USB power source status
|
||||||
if (drv->pmic_data.usb_status != 0x0) {
|
if (drv->pmic_data.usb_status != 0x0) {
|
||||||
if (!drv->usb_connected) {
|
if (!drv->usb_connected) {
|
||||||
@ -236,3 +254,17 @@ void pm_battery_initial_soc_guess(void) {
|
|||||||
|
|
||||||
fuel_gauge_initial_guess(&drv->fuel_gauge, vbat_g, ibat_g, ntc_temp_g);
|
fuel_gauge_initial_guess(&drv->fuel_gauge, vbat_g, ibat_g, ntc_temp_g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pm_store_power_manager_data(pm_driver_t* drv){
|
||||||
|
|
||||||
|
backup_ram_power_manager_data_t pm_data = {0};
|
||||||
|
|
||||||
|
// Store the current state of the power manager
|
||||||
|
pm_data.soc = drv->fuel_gauge.soc;
|
||||||
|
pm_data.last_capture_timestamp = systick_ms();
|
||||||
|
|
||||||
|
// Store the data in backup RAM
|
||||||
|
backup_ram_store_power_manager_data(&pm_data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -309,6 +309,9 @@ void pm_enter_suspend(pm_driver_t* drv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pm_enter_hibernate(pm_driver_t* drv) {
|
void pm_enter_hibernate(pm_driver_t* drv) {
|
||||||
|
|
||||||
|
pm_store_power_manager_data(drv);
|
||||||
|
|
||||||
reboot_device();
|
reboot_device();
|
||||||
// Put PMIC into ship mode (ultra-low power)
|
// Put PMIC into ship mode (ultra-low power)
|
||||||
// npm1300_enter_shipmode();
|
// npm1300_enter_shipmode();
|
||||||
|
@ -251,7 +251,6 @@ def configure(
|
|||||||
("USE_OEM_KEYS_CHECK", "1"),
|
("USE_OEM_KEYS_CHECK", "1"),
|
||||||
]
|
]
|
||||||
|
|
||||||
if "powerctl" in features_wanted:
|
|
||||||
sources += [
|
sources += [
|
||||||
"embed/sys/powerctl/npm1300/npm1300.c",
|
"embed/sys/powerctl/npm1300/npm1300.c",
|
||||||
"embed/sys/powerctl/fuel_gauge/fuel_gauge.c",
|
"embed/sys/powerctl/fuel_gauge/fuel_gauge.c",
|
||||||
|
Loading…
Reference in New Issue
Block a user