mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-29 11:22:34 +00:00
chore(core): unify prodtests under power_manager
[no changelog]
This commit is contained in:
parent
3795ba9fc4
commit
8e7d5a2a01
@ -137,7 +137,6 @@ SOURCE_PRODTEST = [
|
||||
'embed/projects/prodtest/cmd/prodtest_bootloader.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_button.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_display.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_fuel_gauge.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_prodtest.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_backup_ram.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_get_cpuid.c',
|
||||
@ -150,7 +149,6 @@ SOURCE_PRODTEST = [
|
||||
'embed/projects/prodtest/cmd/prodtest_otp_batch.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_otp_variant.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_ping.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_pmic.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_power_manager.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_reboot.c',
|
||||
'embed/projects/prodtest/cmd/prodtest_rgbled.c',
|
||||
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_POWERCTL
|
||||
|
||||
#include <rust_ui_prodtest.h>
|
||||
#include <stdlib.h>
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <rtl/cli.h>
|
||||
#include <rtl/mini_printf.h>
|
||||
#include <sys/systick.h>
|
||||
|
||||
#include "../../../sys/powerctl/fuel_gauge/fuel_gauge.h"
|
||||
#include "../../../sys/powerctl/npm1300/npm1300.h"
|
||||
|
||||
static void prodtest_fuel_gauge(cli_t *cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
char display_text[100];
|
||||
|
||||
fuel_gauge_state_t fg;
|
||||
|
||||
// Fuel gauge noise covariance parameters.
|
||||
// These parameters are used in the Kalman filter to adjust the weight
|
||||
// given to the measurements versus the model predictions.
|
||||
// Parameters are fine-tuned on battery model simulation.
|
||||
float Q = 0.001f;
|
||||
float R = 3000.0f;
|
||||
float R_aggressive = 3000.0f;
|
||||
float Q_aggressive = 0.001f;
|
||||
float P_init = 0.1;
|
||||
|
||||
cli_trace(cli, "Initialize Fuel gauge.");
|
||||
|
||||
fuel_gauge_init(&fg, R, Q, R_aggressive, Q_aggressive, P_init);
|
||||
|
||||
npm1300_report_t report;
|
||||
if (!npm1300_measure_sync(&report)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to get measurement data from PMIC.");
|
||||
return;
|
||||
}
|
||||
|
||||
fuel_gauge_initial_guess(&fg, report.vbat, report.ibat, report.ntc_temp);
|
||||
uint32_t tick = systick_ms();
|
||||
|
||||
systick_delay_ms(1000);
|
||||
|
||||
while (true) {
|
||||
if (cli_aborted(cli)) {
|
||||
cli_trace(cli, "Abort fuel gauge test.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!npm1300_measure_sync(&report)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to get measurement data from PMIC.");
|
||||
break;
|
||||
}
|
||||
|
||||
fuel_gauge_update(&fg, systick_ms() - tick, report.vbat, report.ibat,
|
||||
report.ntc_temp);
|
||||
tick = systick_ms();
|
||||
|
||||
// Calculate the integer and fractional parts correctly
|
||||
int vbat_int = (int)report.vbat;
|
||||
int vbat_frac =
|
||||
abs((int)((report.vbat - vbat_int) * 1000)); // Only 3 decimal places
|
||||
|
||||
int ibat_int = (int)report.ibat;
|
||||
int ibat_frac =
|
||||
abs((int)((report.ibat - ibat_int) * 1000)); // Only 3 decimal places
|
||||
|
||||
int soc_int = (int)fg.soc;
|
||||
int soc_frac =
|
||||
abs((int)((fg.soc - soc_int) * 1000)); // Only 3 decimal places
|
||||
|
||||
const char *charge_state_str;
|
||||
if (report.ibat > 0) {
|
||||
charge_state_str = "DISCHARGING";
|
||||
} else if (report.ibat < 0) {
|
||||
charge_state_str = "CHARGING";
|
||||
} else {
|
||||
charge_state_str = "IDLE";
|
||||
}
|
||||
|
||||
cli_progress(cli, "%d.%03d %d.%03d %d.%03d %s", vbat_int, vbat_frac,
|
||||
ibat_int, ibat_frac, soc_int, soc_frac, charge_state_str);
|
||||
|
||||
mini_snprintf(display_text, 100, "V: %d.%03d I: %d.%03d SOC: %d.%03d",
|
||||
vbat_int, vbat_frac, ibat_int, ibat_frac, soc_int, soc_frac);
|
||||
|
||||
screen_prodtest_show_text(display_text, strlen(display_text));
|
||||
|
||||
// Wait a second
|
||||
systick_delay_ms(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "fuel-gauge",
|
||||
.func = prodtest_fuel_gauge,
|
||||
.info = "Test fuel gauge",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
#endif // USE_POWERCTL
|
@ -1,318 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_POWERCTL
|
||||
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <rtl/cli.h>
|
||||
#include <rtl/unit_test.h>
|
||||
#include <sys/systick.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "../../../sys/powerctl/npm1300/npm1300.h"
|
||||
|
||||
static void prodtest_pmic_init(cli_t* cli) {
|
||||
cli_trace(cli, "Initializing the NPM1300 driver...");
|
||||
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
npm1300_deinit();
|
||||
|
||||
if (!npm1300_init()) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to initialize NPM1300 driver.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_pmic_charge_enable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Enabling battery charging @ %dmA...",
|
||||
npm1300_get_charging_limit());
|
||||
|
||||
if (!npm1300_set_charging(true)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to enable battery charging.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_pmic_charge_disable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Disabling battery charging...");
|
||||
|
||||
if (!npm1300_set_charging(false)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to disable battery charging.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_pmic_charge_set_limit(cli_t* cli) {
|
||||
uint32_t i_charge = 0;
|
||||
|
||||
if (!cli_arg_uint32(cli, "limit", &i_charge) ||
|
||||
i_charge < NPM1300_CHARGING_LIMIT_MIN ||
|
||||
i_charge > NPM1300_CHARGING_LIMIT_MAX) {
|
||||
cli_error_arg(cli, "Expecting charging limit in range %d-%d mA.",
|
||||
NPM1300_CHARGING_LIMIT_MIN, NPM1300_CHARGING_LIMIT_MAX);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_arg_count(cli) > 1) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Setting battery charging limit to %d mA...", i_charge);
|
||||
|
||||
if (!npm1300_set_charging_limit(i_charge)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to set battery charging limit.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_pmic_buck_set_mode(cli_t* cli) {
|
||||
npm1300_buck_mode_t buck_mode = NPM1300_BUCK_MODE_AUTO;
|
||||
|
||||
const char* mode = cli_arg(cli, "mode");
|
||||
if (strcmp(mode, "pwm") == 0) {
|
||||
buck_mode = NPM1300_BUCK_MODE_PWM;
|
||||
} else if (strcmp(mode, "pfm") == 0) {
|
||||
buck_mode = NPM1300_BUCK_MODE_PFM;
|
||||
} else if (strcmp(mode, "auto") == 0) {
|
||||
buck_mode = NPM1300_BUCK_MODE_AUTO;
|
||||
} else {
|
||||
cli_error_arg(cli, "Buck converter mode expected (pwm, pfm or auto).");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_arg_count(cli) > 1) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Setting the buck converter mode...");
|
||||
|
||||
if (!npm1300_set_buck_mode(buck_mode)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to set buck converter mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_pmic_report(cli_t* cli) {
|
||||
uint32_t count = 1;
|
||||
uint32_t period = 1000;
|
||||
|
||||
if (cli_has_arg(cli, "count") && !cli_arg_uint32(cli, "count", &count)) {
|
||||
cli_error_arg(cli, "Expecting count of measurements.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_has_arg(cli, "period") && !cli_arg_uint32(cli, "period", &period)) {
|
||||
cli_error_arg(cli, "Expecting period in milliseconds.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_arg_count(cli) > 2) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli,
|
||||
" time vbat ibat ntc vsys die bat buck mode");
|
||||
|
||||
uint32_t ticks = hal_ticks_ms();
|
||||
|
||||
while (count-- > 0) {
|
||||
npm1300_report_t report;
|
||||
|
||||
if (!npm1300_measure_sync(&report)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to get NPM1300 report.");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* state = "IDLE";
|
||||
|
||||
bool ibat_discharging = ((report.ibat_meas_status >> 2) & 0x03) == 1;
|
||||
bool ibat_charging = ((report.ibat_meas_status >> 2) & 0x03) == 3;
|
||||
|
||||
if (ibat_discharging) {
|
||||
state = "DISCHARGING";
|
||||
} else if (ibat_charging) {
|
||||
state = "CHARGING";
|
||||
}
|
||||
|
||||
cli_progress(
|
||||
cli, "%09d %d.%03d %d.%03d %d.%03d %d.%03d %d.%03d 0x%02X 0x%02X %s",
|
||||
ticks, (int)report.vbat, (int)(report.vbat * 1000) % 1000,
|
||||
(int)report.ibat, (int)abs(report.ibat * 1000) % 1000,
|
||||
(int)report.ntc_temp, (int)abs(report.ntc_temp * 1000) % 1000,
|
||||
(int)report.vsys, (int)(report.vsys * 1000) % 1000,
|
||||
(int)report.die_temp, (int)abs(report.die_temp * 1000) % 1000,
|
||||
report.ibat_meas_status, report.buck_status, state);
|
||||
|
||||
if (count > 0) {
|
||||
do {
|
||||
if (cli_aborted(cli)) {
|
||||
return;
|
||||
}
|
||||
} while (!ticks_expired(ticks + period));
|
||||
ticks += period;
|
||||
}
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
// ut-pmic-init-deinit
|
||||
// This unit test verifies the PMIC driver initialization and deinitialization
|
||||
// routine could be called repeatably witout failure. It should verify that all
|
||||
// driver components are properly cleaned by deinit function.
|
||||
static ut_status_t ut_pmic_init_deinit() {
|
||||
ut_status_t ut_result = UT_PASSED;
|
||||
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
// deinitilize the pmic driver
|
||||
npm1300_deinit();
|
||||
if (npm1300_init() == false) {
|
||||
ut_result = UT_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
npm1300_deinit();
|
||||
|
||||
return ut_result;
|
||||
}
|
||||
|
||||
// ut-pmic-battery
|
||||
// This unit test verifies the battery connection to NPM1300 PMIC.
|
||||
// Firstly it initilize the PMIC driver and request the measurement
|
||||
// report. From the measurement report it checks, if the battery voltage and
|
||||
// NTC temperature are within the expeted range. At last, it checks if NTC
|
||||
// temperature measurement is not too far away from the die temperarture.
|
||||
static ut_status_t ut_pmic_battery() {
|
||||
ut_status_t ut_result = UT_PASSED;
|
||||
npm1300_report_t report;
|
||||
|
||||
if (npm1300_init() == false) {
|
||||
ut_result = UT_FAILED;
|
||||
} else {
|
||||
// Request mesaurement report from PMIC
|
||||
if (npm1300_measure_sync(&report) == false) {
|
||||
ut_result = UT_FAILED;
|
||||
} else {
|
||||
// Battery voltage outside given range
|
||||
if (report.vbat < 3.0 || report.vbat > 3.8) {
|
||||
ut_result = UT_FAILED;
|
||||
}
|
||||
|
||||
// Battery NTC outside given range
|
||||
if (report.ntc_temp < -40.0 || report.ntc_temp > 50.0) {
|
||||
ut_result = UT_FAILED;
|
||||
}
|
||||
|
||||
// Battery NTC too far from die temp
|
||||
if (abs(report.ntc_temp - report.die_temp) > 10.0) {
|
||||
ut_result = UT_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
npm1300_deinit();
|
||||
return ut_result;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pmic-init",
|
||||
.func = prodtest_pmic_init,
|
||||
.info = "Initialize the PMIC driver",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pmic-charge-enable",
|
||||
.func = prodtest_pmic_charge_enable,
|
||||
.info = "Enable battery charging",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pmic-charge-disable",
|
||||
.func = prodtest_pmic_charge_disable,
|
||||
.info = "Disable battery charging",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pmic-charge-set-limit",
|
||||
.func = prodtest_pmic_charge_set_limit,
|
||||
.info = "Set the battery charging limit",
|
||||
.args = "<limit>"
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pmic-buck-set-mode",
|
||||
.func = prodtest_pmic_buck_set_mode,
|
||||
.info = "Set the buck converter mode",
|
||||
.args = "<mode>"
|
||||
)
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pmic-report",
|
||||
.func = prodtest_pmic_report,
|
||||
.info = "Retrieve PMIC report",
|
||||
.args = "[<count>] [<period>]"
|
||||
);
|
||||
|
||||
REGISTER_UNIT_TEST(
|
||||
.name = "ut-pmic-init-deinit",
|
||||
.func = ut_pmic_init_deinit,
|
||||
.info = "Test PMIC driver initialization and deinitialization",
|
||||
)
|
||||
|
||||
REGISTER_UNIT_TEST(
|
||||
.name = "ut-pmic-battery",
|
||||
.func = ut_pmic_battery,
|
||||
.info = "Test PMIC battery connection",
|
||||
)
|
||||
|
||||
#endif // USE_POWERCTL
|
@ -65,7 +65,41 @@ void prodtest_pm_suspend(cli_t* cli) {
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
void prodtest_pm_watch(cli_t* cli) {
|
||||
void prodtest_pm_charge_disable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Enabling battery charging");
|
||||
|
||||
pm_status_t status = pm_charging_disable();
|
||||
if (status != PM_OK) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to enable battery charging");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
void prodtest_pm_charge_enable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Enabling battery charging");
|
||||
|
||||
pm_status_t status = pm_charging_enable();
|
||||
if (status != PM_OK) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to enable battery charging");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
void prodtest_pm_fuel_gauge_monitor(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
@ -157,7 +191,7 @@ void prodtest_pm_report(cli_t* cli) {
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
void prodtest_pm_monitor(cli_t* cli) {
|
||||
void prodtest_pm_event_monitor(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
@ -225,38 +259,52 @@ void prodtest_pm_monitor(cli_t* cli) {
|
||||
// clang-format off
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "power-manager-monitor",
|
||||
.func = prodtest_pm_monitor,
|
||||
.info = "Run power manager monitor",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "power-manager-watch",
|
||||
.func = prodtest_pm_watch,
|
||||
.info = "Watch power manager reports",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "power-manager-report",
|
||||
.func = prodtest_pm_report,
|
||||
.info = "Get power manager report",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "power-manager-suspend",
|
||||
.name = "pm-suspend",
|
||||
.func = prodtest_pm_suspend,
|
||||
.info = "Suspend the device to low-power mode",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "power-manager-hibernate",
|
||||
.name = "pm-hibernate",
|
||||
.func = prodtest_pm_hibernate,
|
||||
.info = "Hibernate the device into a near power-off state",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pm-charge-enable",
|
||||
.func = prodtest_pm_charge_enable,
|
||||
.info = "Enable battery charging",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pm-charge-disable",
|
||||
.func = prodtest_pm_charge_disable,
|
||||
.info = "Disable battery charging",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pm-event-monitor",
|
||||
.func = prodtest_pm_event_monitor,
|
||||
.info = "Run power manager event monitor",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pm-fuel-gauge-monitor",
|
||||
.func = prodtest_pm_fuel_gauge_monitor,
|
||||
.info = "Watch fuel gauge ",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "pm-report",
|
||||
.func = prodtest_pm_report,
|
||||
.info = "Get power manager report",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
#endif /* USE POWER_MANAGER */
|
||||
|
@ -17,165 +17,37 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_POWERCTL
|
||||
#ifdef USE_POWER_MANAGER
|
||||
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <rtl/cli.h>
|
||||
#include <sys/systick.h>
|
||||
#include <sys/power_manager.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "../../../sys/powerctl/stwlc38/stwlc38.h"
|
||||
|
||||
static void prodtest_wpc_init(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Initializing the WPC driver...");
|
||||
|
||||
stwlc38_deinit();
|
||||
|
||||
if (!stwlc38_init()) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to initialize STWLC38.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_wpc_enable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Enabling STWLC38...");
|
||||
|
||||
if (!stwlc38_enable(true)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to enable STWLC38.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_wpc_disable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Disabling STWLC38...");
|
||||
|
||||
if (!stwlc38_enable(false)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to disable STWLC38.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_wpc_vout_enable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Enabling STWLC38 output...");
|
||||
|
||||
if (!stwlc38_enable_vout(true)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to enable STWLC38 output.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_wpc_vout_disable(cli_t* cli) {
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(cli, "Disabling STWLC38 output...");
|
||||
|
||||
if (!stwlc38_enable_vout(false)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to disable STWLC38 output.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
|
||||
static void prodtest_wpc_report(cli_t* cli) {
|
||||
uint32_t count = 1;
|
||||
uint32_t period = 1000;
|
||||
|
||||
if (cli_has_arg(cli, "count") && !cli_arg_uint32(cli, "count", &count)) {
|
||||
cli_error_arg(cli, "Expecting count of measurements.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_has_arg(cli, "timeout") && !cli_arg_uint32(cli, "timeout", &period)) {
|
||||
cli_error_arg(cli, "Expecting period in milliseconds.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cli_arg_count(cli) > 2) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_trace(
|
||||
cli,
|
||||
" time ready vout_ready vrect vout icur tmeas opfreq ntc");
|
||||
|
||||
uint32_t ticks = hal_ticks_ms();
|
||||
|
||||
while (count-- > 0) {
|
||||
stwlc38_report_t report;
|
||||
|
||||
if (!stwlc38_get_report(&report)) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to get STWLC38 report.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_progress(cli, "%09d %d %d %d.%03d %d.%03d %d.%03d %d.%03d %d %d.%03d",
|
||||
ticks, report.ready ? 1 : 0, report.vout_ready ? 1 : 0,
|
||||
(int)report.vrect, (int)abs(report.vrect * 1000) % 1000,
|
||||
(int)report.vout, (int)(report.vout * 1000) % 1000,
|
||||
(int)report.icur, (int)abs(report.icur * 1000) % 1000,
|
||||
(int)report.tmeas, (int)abs(report.tmeas * 1000) % 1000,
|
||||
report.opfreq, (int)report.ntc,
|
||||
(int)abs(report.ntc * 1000) % 1000);
|
||||
|
||||
if (count > 0) {
|
||||
do {
|
||||
if (cli_aborted(cli)) {
|
||||
return;
|
||||
}
|
||||
} while (!ticks_expired(ticks + period));
|
||||
ticks += period;
|
||||
}
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
}
|
||||
#include "../stwlc38/stwlc38.h"
|
||||
|
||||
static void prodtest_wpc_info(cli_t* cli) {
|
||||
|
||||
if (cli_arg_count(cli) > 0) {
|
||||
cli_error_arg_count(cli);
|
||||
return;
|
||||
}
|
||||
|
||||
stwlc38_chip_info_t chip_info;
|
||||
pm_status_t status_pm;
|
||||
|
||||
// Deinit power manager to not interfere with STWLC38
|
||||
pm_deinit();
|
||||
|
||||
|
||||
stwlc38_init();
|
||||
|
||||
cli_trace(cli, "Reading STWLC38 info...");
|
||||
if (!stwlc38_read_chip_info(&chip_info)) {
|
||||
cli_error(cli, CLI_ERROR, "Cannot read STWLC38 info.");
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
char device_id[sizeof(chip_info.device_id) * 2 + 1];
|
||||
@ -183,7 +55,7 @@ static void prodtest_wpc_info(cli_t* cli) {
|
||||
if (!cstr_encode_hex(device_id, sizeof(device_id), chip_info.device_id,
|
||||
sizeof(chip_info.device_id))) {
|
||||
cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cli_trace(cli, "chip_id 0x%d ", chip_info.chip_id);
|
||||
@ -205,7 +77,27 @@ static void prodtest_wpc_info(cli_t* cli) {
|
||||
cli_trace(cli, " nvm_patch_err: 0x%X ", chip_info.nvm_patch_err);
|
||||
cli_trace(cli, " nvm_prod_info_err: 0x%X ", chip_info.nvm_prod_info_err);
|
||||
|
||||
|
||||
stwlc38_deinit();
|
||||
|
||||
// initlize power manager again
|
||||
status_pm = pm_init(true);
|
||||
if (status_pm != PM_OK) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to reinitialize power manager.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
|
||||
cleanup:
|
||||
|
||||
// initlize power manager again
|
||||
status_pm = pm_init(true);
|
||||
if (status_pm != PM_OK) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to reinitialize power manager.");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void prodtest_wpc_update(cli_t* cli) {
|
||||
@ -214,12 +106,19 @@ static void prodtest_wpc_update(cli_t* cli) {
|
||||
return;
|
||||
}
|
||||
|
||||
pm_status_t status_pm;
|
||||
|
||||
// Deinit power manager to not interfere with STWLC38
|
||||
pm_deinit();
|
||||
|
||||
stwlc38_init();
|
||||
|
||||
cli_trace(cli, "Updating STWLC38...");
|
||||
|
||||
stwlc38_chip_info_t chip_info;
|
||||
if (!stwlc38_read_chip_info(&chip_info)) {
|
||||
cli_error(cli, CLI_ERROR, "Cannot read STWLC38 info.");
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (chip_info.chip_rev == STWLC38_CUT_1_2) {
|
||||
@ -228,7 +127,7 @@ static void prodtest_wpc_update(cli_t* cli) {
|
||||
cli_trace(cli, "STWLC38 chip revision 1.3");
|
||||
} else {
|
||||
cli_error(cli, CLI_ERROR, "Unknown chip revision, update aborted.");
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Update STWLC38 firmware and configuration
|
||||
@ -238,57 +137,34 @@ static void prodtest_wpc_update(cli_t* cli) {
|
||||
|
||||
if (status == false) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to update STWLC38.");
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cli_trace(cli, "WPC update completed {%d ms}", update_time);
|
||||
|
||||
stwlc38_deinit();
|
||||
|
||||
// initlize power manager again
|
||||
status_pm = pm_init(true);
|
||||
if (status_pm != PM_OK) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to reinitialize power manager.");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_ok(cli, "");
|
||||
|
||||
cleanup:
|
||||
|
||||
// initlize power manager again
|
||||
status_pm = pm_init(true);
|
||||
if (status_pm != PM_OK) {
|
||||
cli_error(cli, CLI_ERROR, "Failed to reinitialize power manager.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "wpc-init",
|
||||
.func = prodtest_wpc_init,
|
||||
.info = "Initialize the WPC driver",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "wpc-enable",
|
||||
.func = prodtest_wpc_enable,
|
||||
.info = "Enable the WPC chip",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "wpc-disable",
|
||||
.func = prodtest_wpc_disable,
|
||||
.info = "Disable the WPC chip",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "wpc-out-enable",
|
||||
.func = prodtest_wpc_vout_enable,
|
||||
.info = "Enable WPC output",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "wpc-out-disable",
|
||||
.func = prodtest_wpc_vout_disable,
|
||||
.info = "Disable WPC output",
|
||||
.args = ""
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "wpc-report",
|
||||
.func = prodtest_wpc_report,
|
||||
.info = "Retrieve WPC report",
|
||||
.args = "[<count>] [<timeout>]"
|
||||
);
|
||||
|
||||
PRODTEST_CLI_CMD(
|
||||
.name = "wpc-info",
|
||||
.func = prodtest_wpc_info,
|
||||
@ -303,4 +179,4 @@ PRODTEST_CLI_CMD(
|
||||
.args = ""
|
||||
);
|
||||
|
||||
#endif // USE_POWERCTL
|
||||
#endif // USE_POWER_MANAGER
|
||||
|
@ -109,6 +109,10 @@ pm_status_t pm_init(bool skip_bootup_sequence) {
|
||||
void pm_deinit(void) {
|
||||
pm_driver_t* drv = &g_pm;
|
||||
|
||||
if(drv->fuel_gauge_initialized){
|
||||
pm_store_data_to_backup_ram();
|
||||
}
|
||||
|
||||
if (drv->monitoring_timer) {
|
||||
systimer_delete(drv->monitoring_timer);
|
||||
drv->monitoring_timer = NULL;
|
||||
@ -121,6 +125,9 @@ void pm_deinit(void) {
|
||||
|
||||
npm1300_deinit();
|
||||
stwlc38_deinit();
|
||||
|
||||
drv->initialized = false;
|
||||
|
||||
}
|
||||
|
||||
pm_status_t pm_get_events(pm_event_t* event_flags) {
|
||||
@ -373,4 +380,5 @@ pm_status_t pm_wakeup_flags_get(pm_wakeup_flags_t *flags) {
|
||||
*flags = drv->wakeup_flags;
|
||||
irq_unlock(irq_key);
|
||||
return PM_OK;
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user