1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-26 09:52:34 +00:00

feat(core): add pm_charging_set_max_current function to API

[no changelog]
This commit is contained in:
kopecdav 2025-05-12 14:31:53 +02:00 committed by kopecdav
parent e1e6d77ba5
commit a530fb2c76
8 changed files with 51 additions and 54 deletions

View File

@ -336,17 +336,16 @@ void prodtest_pm_precharge(cli_t* cli) {
// due to effect of internal resistance of the battery. So battery voltage // due to effect of internal resistance of the battery. So battery voltage
// will drop a bit after the charging is stopped. // will drop a bit after the charging is stopped.
// voltage while charging is being lifted due to charging with quite high charging // voltage while charging is being lifted due to charging with quite high
// current. When the test terminate by reaching the given woltage. The current // charging current. When the test terminate by reaching the given woltage.
// and // The current and
float precharge_voltage_V = 3.45f; float precharge_voltage_V = 3.45f;
pm_charging_enable(); pm_charging_enable();
cli_trace(cli, "Precharging the device..."); cli_trace(cli, "Precharging the device...");
while(true){ while (true) {
pm_report_t report; pm_report_t report;
pm_status_t status = pm_get_report(&report); pm_status_t status = pm_get_report(&report);
@ -365,8 +364,7 @@ void prodtest_pm_precharge(cli_t* cli) {
(int)(report.battery_voltage_v * 1000) % 1000, (int)(report.battery_voltage_v * 1000) % 1000,
(int)precharge_voltage_V, (int)precharge_voltage_V,
(int)(precharge_voltage_V * 1000) % 1000); (int)(precharge_voltage_V * 1000) % 1000);
cli_progress(cli,"%d.%03d %d.%03d", cli_progress(cli, "%d.%03d %d.%03d", (int)report.battery_voltage_v,
(int)report.battery_voltage_v,
(int)(report.battery_voltage_v * 1000) % 1000, (int)(report.battery_voltage_v * 1000) % 1000,
(int)precharge_voltage_V, (int)precharge_voltage_V,
(int)(precharge_voltage_V * 1000) % 1000); (int)(precharge_voltage_V * 1000) % 1000);
@ -377,7 +375,7 @@ void prodtest_pm_precharge(cli_t* cli) {
} }
// Check if the battery voltage is above the precharge voltag // Check if the battery voltage is above the precharge voltag
if(report.battery_voltage_v >= precharge_voltage_V){ if (report.battery_voltage_v >= precharge_voltage_V) {
// Target achieved // Target achieved
cli_trace(cli, "Battery voltage reached the target voltage."); cli_trace(cli, "Battery voltage reached the target voltage.");
break; break;
@ -387,7 +385,6 @@ void prodtest_pm_precharge(cli_t* cli) {
cli_ok(cli, ""); cli_ok(cli, "");
} }
// clang-format off // clang-format off
PRODTEST_CLI_CMD( PRODTEST_CLI_CMD(

View File

@ -107,8 +107,8 @@ 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_charging_set_max_current(uint16_t current_ma);
pm_status_t pm_store_data_to_backup_ram(); pm_status_t pm_store_data_to_backup_ram();
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);
pm_status_t pm_wakeup_flags_get(pm_wakeup_flags_t* flags); pm_status_t pm_wakeup_flags_get(pm_wakeup_flags_t* flags);

View File

@ -106,8 +106,9 @@ pm_status_t pm_init(bool inherit_state) {
// Fuel gauge SoC available, set fuel_gauge initialized. // Fuel gauge SoC available, set fuel_gauge initialized.
drv->fuel_gauge_initialized = true; drv->fuel_gauge_initialized = true;
// Enable charging by default // Enable charging by default to max current
drv->charging_enabled = true; drv->charging_enabled = true;
pm_charging_set_max_current(PM_BATTERY_CHARGING_CURRENT_MAX);
// Poll until fuel_gauge is initialized and first PMIC & WLC measurements // Poll until fuel_gauge is initialized and first PMIC & WLC measurements
// propagates into power_monitor. // propagates into power_monitor.
@ -294,7 +295,9 @@ pm_status_t pm_charging_enable(void) {
} }
drv->charging_enabled = true; drv->charging_enabled = true;
irq_key_t irq_key = irq_lock();
pm_charging_controller(drv); pm_charging_controller(drv);
irq_unlock(irq_key);
return PM_OK; return PM_OK;
} }
@ -307,7 +310,29 @@ pm_status_t pm_charging_disable(void) {
} }
drv->charging_enabled = false; drv->charging_enabled = false;
irq_key_t irq_key = irq_lock();
pm_charging_controller(drv); pm_charging_controller(drv);
irq_unlock(irq_key);
return PM_OK;
}
pm_status_t pm_charging_set_max_current(uint16_t current_ma) {
pm_driver_t* drv = &g_pm;
if (!drv->initialized) {
return PM_NOT_INITIALIZED;
}
if (current_ma > PM_BATTERY_CHARGING_CURRENT_MAX) {
return PM_REQUEST_REJECTED;
}
if (current_ma < PM_BATTERY_CHARGING_CURRENT_MIN) {
return PM_REQUEST_REJECTED;
}
drv->charging_current_max_limit_ma = current_ma;
return PM_OK; return PM_OK;
} }
@ -342,25 +367,6 @@ pm_status_t pm_store_data_to_backup_ram() {
return PM_OK; return PM_OK;
} }
pm_status_t pm_wait_until_active(uint32_t timeout_ms) {
pm_driver_t* drv = &g_pm;
uint32_t expire_time = ticks_timeout(timeout_ms);
while (1) {
if (ticks_expired(expire_time)) {
// Timeout expired
return PM_REQUEST_REJECTED;
}
if ((drv->state == PM_STATE_ACTIVE) ||
(drv->state == PM_STATE_POWER_SAVE)) {
return PM_OK;
}
}
return PM_OK;
}
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_driver_t* drv = &g_pm; pm_driver_t* drv = &g_pm;
if (!drv->initialized) { if (!drv->initialized) {

View File

@ -34,7 +34,8 @@
#define PM_BATTERY_UNDERVOLT_THR_V 3.0f #define PM_BATTERY_UNDERVOLT_THR_V 3.0f
#define PM_BATTERY_UNDERVOLT_RECOVERY_THR_V 3.3f #define PM_BATTERY_UNDERVOLT_RECOVERY_THR_V 3.3f
#define PM_BATTERY_LOW_THRESHOLD_SOC 15 #define PM_BATTERY_LOW_THRESHOLD_SOC 15
#define PM_BATTERY_CHARGING_CURRENT_MAX PMIC_CHARGING_LIMIT_MAX
#define PM_BATTERY_CHARGING_CURRENT_MIN PMIC_CHARGING_LIMIT_MIN
#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
@ -75,6 +76,7 @@ typedef struct {
// Battery charging state // Battery charging state
bool charging_enabled; bool charging_enabled;
uint16_t charging_current_target_ma; uint16_t charging_current_target_ma;
uint16_t charging_current_max_limit_ma;
uint32_t charging_target_timestamp; uint32_t charging_target_timestamp;
// Power source hardware state // Power source hardware state

View File

@ -64,7 +64,6 @@ 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_THR_V) && if ((drv->pmic_data.vbat < PM_BATTERY_UNDERVOLT_THR_V) &&
!drv->battery_critical) { !drv->battery_critical) {
// Force Fuel gauge to 0, keep the covariance // Force Fuel gauge to 0, keep the covariance
fuel_gauge_set_soc(&drv->fuel_gauge, 0.0f, drv->fuel_gauge.P); fuel_gauge_set_soc(&drv->fuel_gauge, 0.0f, drv->fuel_gauge.P);
@ -95,7 +94,7 @@ void pm_monitor_power_sources(void) {
drv->pmic_data.ntc_temp); drv->pmic_data.ntc_temp);
// Charging completed // Charging completed
if(drv->pmic_data.charge_status & 0x1){ if (drv->pmic_data.charge_status & 0x1) {
// Force fuel gauge to 100%, keep the covariance // Force fuel gauge to 100%, keep the covariance
fuel_gauge_set_soc(&drv->fuel_gauge, 1.0f, drv->fuel_gauge.P); fuel_gauge_set_soc(&drv->fuel_gauge, 1.0f, drv->fuel_gauge.P);
} }
@ -162,23 +161,19 @@ void pm_charging_controller(pm_driver_t* drv) {
} }
} else if (drv->usb_connected) { } else if (drv->usb_connected) {
// USB connected, set maximum charging current right away // USB connected, set maximum charging current right away
drv->charging_current_target_ma = PMIC_CHARGING_LIMIT_MAX; drv->charging_current_target_ma = drv->charging_current_max_limit_ma;
} else if (drv->wireless_connected) { } else if (drv->wireless_connected) {
// Gradually increase charging current to the maximum // Gradually increase charging current to the maximum
if (drv->charging_current_target_ma == PMIC_CHARGING_LIMIT_MAX) { if (drv->charging_current_target_ma == drv->charging_current_max_limit_ma) {
// No action required // No action required
} else if (drv->charging_current_target_ma == 0) { } else if (drv->charging_current_target_ma == 0) {
drv->charging_current_target_ma = PMIC_CHARGING_LIMIT_MIN; drv->charging_current_target_ma = drv->charging_current_max_limit_ma;
drv->charging_target_timestamp = systick_ms(); drv->charging_target_timestamp = systick_ms();
} else if (systick_ms() - drv->charging_target_timestamp > } else if (systick_ms() - drv->charging_target_timestamp >
PM_WPC_CHARGE_CURR_STEP_TIMEOUT_MS) { PM_WPC_CHARGE_CURR_STEP_TIMEOUT_MS) {
drv->charging_current_target_ma += PM_WPC_CHARGE_CURR_STEP_MA; drv->charging_current_target_ma += PM_WPC_CHARGE_CURR_STEP_MA;
drv->charging_target_timestamp = systick_ms(); drv->charging_target_timestamp = systick_ms();
if (drv->charging_current_target_ma > PMIC_CHARGING_LIMIT_MAX) {
drv->charging_current_target_ma = PMIC_CHARGING_LIMIT_MAX;
}
} }
} else { } else {
@ -186,6 +181,11 @@ void pm_charging_controller(pm_driver_t* drv) {
drv->charging_current_target_ma = 0; drv->charging_current_target_ma = 0;
} }
// charging current software limit
if (drv->charging_current_target_ma > drv->charging_current_max_limit_ma) {
drv->charging_current_target_ma = drv->charging_current_max_limit_ma;
}
// Set charging target // Set charging target
if (drv->charging_current_target_ma != pmic_get_charging_limit()) { if (drv->charging_current_target_ma != pmic_get_charging_limit()) {
// Set charging current limit // Set charging current limit

View File

@ -236,9 +236,7 @@ def configure(
] ]
if ("pmic" in features_wanted) or ("power_manager" in features_wanted): if ("pmic" in features_wanted) or ("power_manager" in features_wanted):
sources += [ sources += ["embed/sys/power_manager/npm1300/npm1300.c"]
"embed/sys/power_manager/npm1300/npm1300.c"
]
paths += ["embed/sys/power_manager/inc"] paths += ["embed/sys/power_manager/inc"]
defines += ["USE_PMIC"] defines += ["USE_PMIC"]
features_available.append("pmic") features_available.append("pmic")

View File

@ -241,9 +241,7 @@ def configure(
] ]
if ("pmic" in features_wanted) or ("power_manager" in features_wanted): if ("pmic" in features_wanted) or ("power_manager" in features_wanted):
sources += [ sources += ["embed/sys/power_manager/npm1300/npm1300.c"]
"embed/sys/power_manager/npm1300/npm1300.c"
]
paths += ["embed/sys/power_manager/inc"] paths += ["embed/sys/power_manager/inc"]
defines += ["USE_PMIC"] defines += ["USE_PMIC"]
features_available.append("pmic") features_available.append("pmic")
@ -263,7 +261,6 @@ def configure(
defines += [("USE_POWER_MANAGER", "1")] defines += [("USE_POWER_MANAGER", "1")]
features_available.append("power_manager") features_available.append("power_manager")
env.get("ENV")["LINKER_SCRIPT"] = linker_script env.get("ENV")["LINKER_SCRIPT"] = linker_script
return features_available return features_available

View File

@ -241,9 +241,7 @@ def configure(
] ]
if ("pmic" in features_wanted) or ("power_manager" in features_wanted): if ("pmic" in features_wanted) or ("power_manager" in features_wanted):
sources += [ sources += ["embed/sys/power_manager/npm1300/npm1300.c"]
"embed/sys/power_manager/npm1300/npm1300.c"
]
paths += ["embed/sys/power_manager/inc"] paths += ["embed/sys/power_manager/inc"]
defines += ["USE_PMIC"] defines += ["USE_PMIC"]
features_available.append("pmic") features_available.append("pmic")
@ -263,7 +261,6 @@ def configure(
defines += [("USE_POWER_MANAGER", "1")] defines += [("USE_POWER_MANAGER", "1")]
features_available.append("power_manager") features_available.append("power_manager")
env.get("ENV")["LINKER_SCRIPT"] = linker_script env.get("ENV")["LINKER_SCRIPT"] = linker_script
return features_available return features_available