diff options
author | Bill Richardson <wfrichar@chromium.org> | 2014-03-26 16:56:38 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-04-01 21:37:32 +0000 |
commit | 9f40d3f90e7373b96256033b3ec7b4b8e5140881 (patch) | |
tree | bb2f4dc8742f869667938f8ee7a2ad4fb9cb38f8 /test | |
parent | 71766a39262b6ed4fec51cba19f10c6bec7e9f19 (diff) | |
download | chrome-ec-9f40d3f90e7373b96256033b3ec7b4b8e5140881.tar.gz |
Add charge_state_v2 algorithm for use by Samus
This is a complete rewrite of the charge_state task used by x86 platforms.
Rather than having a bunch of state-specific functions, each with their own
error handling and special cases, this is organized like so:
Forever:
1. Read everything we can from the battery and charger.
2. Figure out what we'd like to do (including error handling).
3. Allow for customization to override that.
4. Do it.
Things I need to file bugs for are marked with "TODO(wfrichar)". I'll file
the bugs after this CL goes in, so that they'll have something relevant to
refer to.
BUG=chrome-os-partner:20881
BRANCH=ToT
TEST=manual
make buildall -j
Try it on Samus, watch it charge from nearly empty to full, both with and
without fastcharge enabled.
Also undefine CONFIG_BATTERY_PRESENT_CUSTOM, plug and unplug the battery to
be sure the trickle charging logic is correct when it can't tell if the
battery is present.
Change-Id: I3935cd3b87f322eb52178f8a675a886c16b75d58
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/191767
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'test')
-rw-r--r-- | test/battery_get_params_smart.c | 87 | ||||
-rw-r--r-- | test/battery_get_params_smart.tasklist | 17 | ||||
-rw-r--r-- | test/build.mk | 4 | ||||
-rw-r--r-- | test/sbs_charging_v2.c | 221 | ||||
-rw-r--r-- | test/sbs_charging_v2.tasklist | 19 | ||||
-rw-r--r-- | test/test_config.h | 22 |
6 files changed, 369 insertions, 1 deletions
diff --git a/test/battery_get_params_smart.c b/test/battery_get_params_smart.c new file mode 100644 index 0000000000..7c86252b23 --- /dev/null +++ b/test/battery_get_params_smart.c @@ -0,0 +1,87 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Test the logic of battery_get_params() to be sure it sets the correct flags + * when i2c reads fail. + */ + +#include "battery.h" +#include "battery_smart.h" +#include "common.h" +#include "console.h" +#include "i2c.h" +#include "test_util.h" +#include "util.h" + +/* Test state */ +static int fail_on_first, fail_on_last; +static int read_count, write_count; +struct batt_params batt; + +static void reset_and_fail_on(int first, int last) +{ + /* We're not initializing the fake battery, so everything reads zero */ + memset(&batt, 0, sizeof(typeof(batt))); + read_count = write_count = 0; + fail_on_first = first; + fail_on_last = last; +} + +/* Mocked functions */ +int sb_read(int cmd, int *param) +{ + read_count++; + if (read_count >= fail_on_first && read_count <= fail_on_last) + return EC_ERROR_UNKNOWN; + + return i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, cmd, param); +} +int sb_write(int cmd, int param) +{ + write_count++; + return i2c_write16(I2C_PORT_BATTERY, BATTERY_ADDR, cmd, param); +} + + +/* Tests */ +static int test_param_failures(void) +{ + int i, num_reads; + + /* No failures */ + reset_and_fail_on(0, 0); + battery_get_params(&batt); + TEST_ASSERT(batt.flags & BATT_FLAG_RESPONSIVE); + TEST_ASSERT(!(batt.flags & BATT_FLAG_BAD_ANY)); + num_reads = read_count; + + /* Just a single failure */ + for (i = 1; i <= num_reads; i++) { + reset_and_fail_on(i, i); + battery_get_params(&batt); + TEST_ASSERT(batt.flags & BATT_FLAG_BAD_ANY); + TEST_ASSERT(batt.flags & BATT_FLAG_RESPONSIVE); + } + + /* Once it fails, it keeps failing */ + for (i = 1; i <= num_reads; i++) { + reset_and_fail_on(i, num_reads); + battery_get_params(&batt); + TEST_ASSERT(batt.flags & BATT_FLAG_BAD_ANY); + if (i == 1) + /* If every read fails, it's not responsive */ + TEST_ASSERT(!(batt.flags & BATT_FLAG_RESPONSIVE)); + else + TEST_ASSERT(batt.flags & BATT_FLAG_RESPONSIVE); + } + + return EC_SUCCESS; +} + +void run_test(void) +{ + RUN_TEST(test_param_failures); + + test_print_result(); +} diff --git a/test/battery_get_params_smart.tasklist b/test/battery_get_params_smart.tasklist new file mode 100644 index 0000000000..c5d4a2a4b3 --- /dev/null +++ b/test/battery_get_params_smart.tasklist @@ -0,0 +1,17 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * List of enabled tasks in the priority order + * + * The first one has the lowest priority. + * + * For each task, use the macro TASK_TEST(n, r, d, s) where : + * 'n' in the name of the task + * 'r' in the main routine of the task + * 'd' in an opaque parameter passed to the routine at startup + * 's' is the stack size in bytes; must be a multiple of 8 + */ +#define CONFIG_TEST_TASK_LIST /* No test task */ diff --git a/test/build.mk b/test/build.mk index f93b5897aa..d21469ac98 100644 --- a/test/build.mk +++ b/test/build.mk @@ -23,7 +23,7 @@ test-list-host=mutex pingpong utils kb_scan kb_mkbp lid_sw power_button hooks test-list-host+=thermal flash queue kb_8042 extpwr_gpio console_edit system test-list-host+=sbs_charging adapter host_command thermal_falco led_spring test-list-host+=bklight_lid bklight_passthru interrupt timer_dos button -test-list-host+=motion_sense math_util +test-list-host+=motion_sense math_util sbs_charging_v2 battery_get_params_smart adapter-y=adapter.o button-y=button.o @@ -48,6 +48,7 @@ power_button-y=power_button.o powerdemo-y=powerdemo.o queue-y=queue.o sbs_charging-y=sbs_charging.o +sbs_charging_v2-y=sbs_charging_v2.o stress-y=stress.o system-y=system.o thermal-y=thermal.o @@ -55,3 +56,4 @@ thermal_falco-y=thermal_falco.o timer_calib-y=timer_calib.o timer_dos-y=timer_dos.o utils-y=utils.o +battery_get_params_smart-y=battery_get_params_smart.o diff --git a/test/sbs_charging_v2.c b/test/sbs_charging_v2.c new file mode 100644 index 0000000000..feedcb117b --- /dev/null +++ b/test/sbs_charging_v2.c @@ -0,0 +1,221 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Test lid switch. + */ + +#include "battery_smart.h" +#include "charge_state.h" +#include "chipset.h" +#include "common.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "task.h" +#include "test_util.h" +#include "util.h" + +#define WAIT_CHARGER_TASK 500 +#define BATTERY_DETACH_DELAY 35000 + +static int mock_chipset_state = CHIPSET_STATE_ON; +static int is_shutdown; +static int is_force_discharge; +static int is_hibernated; + +void chipset_force_shutdown(void) +{ + is_shutdown = 1; +} + +int chipset_in_state(int state_mask) +{ + return state_mask & mock_chipset_state; +} + +int board_discharge_on_ac(int enabled) +{ + is_force_discharge = enabled; + return EC_SUCCESS; +} + +void system_hibernate(int sec, int usec) +{ + is_hibernated = 1; +} + +/* Setup init condition */ +static void test_setup(void) +{ + const struct battery_info *bat_info = battery_get_info(); + + /* 50% of charge */ + sb_write(SB_RELATIVE_STATE_OF_CHARGE, 50); + sb_write(SB_ABSOLUTE_STATE_OF_CHARGE, 50); + /* 25 degree Celsius */ + sb_write(SB_TEMPERATURE, 250 + 2731); + /* Normal voltage */ + sb_write(SB_VOLTAGE, bat_info->voltage_normal); + sb_write(SB_CHARGING_VOLTAGE, bat_info->voltage_max); + sb_write(SB_CHARGING_CURRENT, 4000); + /* Discharging at 100mAh */ + sb_write(SB_CURRENT, -100); + /* Unplug AC */ + gpio_set_level(GPIO_AC_PRESENT, 0); +} + +static int wait_charging_state(void) +{ + enum charge_state state; + task_wake(TASK_ID_CHARGER); + msleep(WAIT_CHARGER_TASK); + state = charge_get_state(); + ccprintf("[CHARGING TEST] state = %d\n", state); + return state; +} + +static int charge_control(enum ec_charge_control_mode mode) +{ + struct ec_params_charge_control params; + params.mode = mode; + return test_send_host_command(EC_CMD_CHARGE_CONTROL, 1, ¶ms, + sizeof(params), NULL, 0); +} + +static int test_charge_state(void) +{ + enum charge_state state; + + state = wait_charging_state(); + /* Plug AC, charging at 1000mAh */ + ccprintf("[CHARGING TEST] AC on\n"); + gpio_set_level(GPIO_AC_PRESENT, 1); + sb_write(SB_CURRENT, 1000); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_CHARGE); + + /* Detach battery, charging error */ + ccprintf("[CHARGING TEST] Detach battery\n"); + TEST_ASSERT(test_detach_i2c(I2C_PORT_BATTERY, BATTERY_ADDR) == + EC_SUCCESS); + msleep(BATTERY_DETACH_DELAY); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_ERROR); + + /* Attach battery again, charging */ + ccprintf("[CHARGING TEST] Attach battery\n"); + test_attach_i2c(I2C_PORT_BATTERY, BATTERY_ADDR); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_CHARGE); + + /* Unplug AC, discharging at 1000mAh */ + ccprintf("[CHARGING TEST] AC off\n"); + gpio_set_level(GPIO_AC_PRESENT, 0); + sb_write(SB_CURRENT, -1000); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_DISCHARGE); + + /* Discharging overtemp */ + ccprintf("[CHARGING TEST] AC off, batt temp = 90 C\n"); + gpio_set_level(GPIO_AC_PRESENT, 0); + sb_write(SB_CURRENT, -1000); + + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_DISCHARGE); + sb_write(SB_TEMPERATURE, CELSIUS_TO_DECI_KELVIN(90)); + state = wait_charging_state(); + TEST_ASSERT(is_shutdown); + TEST_ASSERT(state == PWR_STATE_DISCHARGE); + sb_write(SB_TEMPERATURE, CELSIUS_TO_DECI_KELVIN(40)); + + /* Force idle */ + ccprintf("[CHARGING TEST] AC on, force idle\n"); + gpio_set_level(GPIO_AC_PRESENT, 1); + sb_write(SB_CURRENT, 1000); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_CHARGE); + charge_control(CHARGE_CONTROL_IDLE); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_IDLE); + charge_control(CHARGE_CONTROL_NORMAL); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_CHARGE); + + /* Force discharge */ + ccprintf("[CHARGING TEST] AC on, force discharge\n"); + gpio_set_level(GPIO_AC_PRESENT, 1); + sb_write(SB_CURRENT, 1000); + charge_control(CHARGE_CONTROL_DISCHARGE); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_IDLE); + TEST_ASSERT(is_force_discharge); + charge_control(CHARGE_CONTROL_NORMAL); + state = wait_charging_state(); + TEST_ASSERT(state == PWR_STATE_CHARGE); + TEST_ASSERT(!is_force_discharge); + + return EC_SUCCESS; +} + +static int test_low_battery(void) +{ + ccprintf("[CHARGING TEST] Low battery with AC\n"); + gpio_set_level(GPIO_AC_PRESENT, 1); + is_hibernated = 0; + sb_write(SB_CURRENT, 1000); + sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2); + wait_charging_state(); + mock_chipset_state = CHIPSET_STATE_SOFT_OFF; + hook_notify(HOOK_CHIPSET_SHUTDOWN); + TEST_ASSERT(!is_hibernated); + + ccprintf("[CHARGING TEST] Low battery shutdown S0->S5\n"); + mock_chipset_state = CHIPSET_STATE_ON; + hook_notify(HOOK_CHIPSET_PRE_INIT); + hook_notify(HOOK_CHIPSET_STARTUP); + gpio_set_level(GPIO_AC_PRESENT, 0); + is_hibernated = 0; + sb_write(SB_CURRENT, -1000); + sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2); + wait_charging_state(); + mock_chipset_state = CHIPSET_STATE_SOFT_OFF; + hook_notify(HOOK_CHIPSET_SHUTDOWN); + wait_charging_state(); + TEST_ASSERT(is_hibernated); + + ccprintf("[CHARGING TEST] Low battery shutdown S5\n"); + is_hibernated = 0; + sb_write(SB_RELATIVE_STATE_OF_CHARGE, 10); + wait_charging_state(); + sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2); + wait_charging_state(); + TEST_ASSERT(is_hibernated); + + ccprintf("[CHARGING TEST] Low battery AP shutdown\n"); + is_shutdown = 0; + mock_chipset_state = CHIPSET_STATE_ON; + sb_write(SB_RELATIVE_STATE_OF_CHARGE, 10); + gpio_set_level(GPIO_AC_PRESENT, 1); + sb_write(SB_CURRENT, 1000); + wait_charging_state(); + gpio_set_level(GPIO_AC_PRESENT, 0); + sb_write(SB_CURRENT, -1000); + sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2); + wait_charging_state(); + usleep(32 * SECOND); + wait_charging_state(); + TEST_ASSERT(is_shutdown); + + return EC_SUCCESS; +} + +void run_test(void) +{ + test_setup(); + + RUN_TEST(test_charge_state); + RUN_TEST(test_low_battery); + + test_print_result(); +} diff --git a/test/sbs_charging_v2.tasklist b/test/sbs_charging_v2.tasklist new file mode 100644 index 0000000000..a87856a123 --- /dev/null +++ b/test/sbs_charging_v2.tasklist @@ -0,0 +1,19 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * List of enabled tasks in the priority order + * + * The first one has the lowest priority. + * + * For each task, use the macro TASK_TEST(n, r, d, s) where : + * 'n' in the name of the task + * 'r' in the main routine of the task + * 'd' in an opaque parameter passed to the routine at startup + * 's' is the stack size in bytes; must be a multiple of 8 + */ +#define CONFIG_TEST_TASK_LIST \ + TASK_TEST(CHARGER, charger_task, NULL, TASK_STACK_SIZE) \ + TASK_TEST(CHIPSET, chipset_task, NULL, TASK_STACK_SIZE) diff --git a/test/test_config.h b/test/test_config.h index 9a005645f8..1ac42ae9d9 100644 --- a/test/test_config.h +++ b/test/test_config.h @@ -63,6 +63,19 @@ int board_discharge_on_ac(int enabled); #define I2C_PORT_CHARGER 1 #endif +#ifdef TEST_SBS_CHARGING_V2 +#define CONFIG_BATTERY_MOCK +#define CONFIG_BATTERY_SMART +#define CONFIG_CHARGER +#define CONFIG_CHARGER_V2 +#define CONFIG_CHARGER_INPUT_CURRENT 4032 +#define CONFIG_CHARGER_DISCHARGE_ON_AC +int board_discharge_on_ac(int enabled); +#define I2C_PORT_MASTER 1 +#define I2C_PORT_BATTERY 1 +#define I2C_PORT_CHARGER 1 +#endif + #ifdef TEST_THERMAL #define CONFIG_CHIPSET_CAN_THROTTLE #define CONFIG_FANS 1 @@ -89,5 +102,14 @@ int board_discharge_on_ac(int enabled); #define CONFIG_KEYBOARD_PROTOCOL_8042 #endif +#ifdef TEST_BATTERY_GET_PARAMS_SMART +#define CONFIG_BATTERY_MOCK +#define CONFIG_BATTERY_SMART +#define CONFIG_CHARGER_INPUT_CURRENT 4032 +#define I2C_PORT_MASTER 1 +#define I2C_PORT_BATTERY 1 +#define I2C_PORT_CHARGER 1 +#endif + #endif /* TEST_BUILD */ #endif /* __CROS_EC_TEST_CONFIG_H */ |