Add thermal engine test

BUG=chrome-os-partner:19236
TEST=Pass the test.
BRANCH=None

Change-Id: I1c96437e1fb3492faa5352383f852dc1d2718ace
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/51248
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
Vic Yang
2013-05-15 11:18:21 +08:00
committed by ChromeBot
parent 3addfe80f9
commit d9cf88b35a
8 changed files with 274 additions and 9 deletions

View File

@@ -6,9 +6,22 @@
#include "board.h"
#include "gpio.h"
#include "temp_sensor.h"
const struct gpio_info gpio_list[GPIO_COUNT] = {
{"EC_INT", 0, 0, 0, 0},
{"LID_OPEN", 0, 0, 0, 0},
{"POWER_BUTTON_L", 0, 0, 0, 0},
};
static int dummy_temp_get_val(int idx, int *temp_ptr)
{
*temp_ptr = 0;
return EC_SUCCESS;
}
const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = {
{"CPU", TEMP_SENSOR_TYPE_CPU, dummy_temp_get_val, 0, 3},
{"Board", TEMP_SENSOR_TYPE_BOARD, dummy_temp_get_val, 0, 3},
{"Case", TEMP_SENSOR_TYPE_CASE, dummy_temp_get_val, 0, 0},
};

View File

@@ -13,6 +13,7 @@
#define CONFIG_KEYBOARD_PROTOCOL_MKBP
#define CONFIG_LID_SWITCH
#define CONFIG_POWER_BUTTON
#define CONFIG_TEMP_SENSOR
enum gpio_signal {
GPIO_EC_INT,
@@ -22,4 +23,12 @@ enum gpio_signal {
GPIO_COUNT
};
enum temp_sensor_id {
TEMP_SENSOR_CPU = 0,
TEMP_SENSOR_BOARD,
TEMP_SENSOR_CASE,
TEMP_SENSOR_COUNT
};
#endif /* __BOARD_H */

View File

@@ -24,7 +24,7 @@
/* Default temperature to report in mapped memory */
#define MAPPED_TEMP_DEFAULT (296 - EC_TEMP_SENSOR_OFFSET)
int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr)
test_mockable int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr)
{
const struct temp_sensor_t *sensor;

View File

@@ -27,7 +27,8 @@
* temp_sensor_type. Threshold values for overheated action first (warning,
* prochot, power-down), followed by fan speed stepping thresholds.
*/
static struct thermal_config_t thermal_config[TEMP_SENSOR_TYPE_COUNT] = {
test_export_static struct thermal_config_t
thermal_config[TEMP_SENSOR_TYPE_COUNT] = {
/* TEMP_SENSOR_TYPE_CPU */
{THERMAL_CONFIG_WARNING_ON_FAIL,
{373, 378, 383, 327, 335, 343, 351, 359} } ,
@@ -38,8 +39,8 @@ static struct thermal_config_t thermal_config[TEMP_SENSOR_TYPE_COUNT] = {
};
/* Fan speed settings. Real max RPM is about 9300. */
static const int fan_speed[THERMAL_FAN_STEPS + 1] = {0, 3000, 4575, 6150,
7725, -1};
test_export_static const int fan_speed[THERMAL_FAN_STEPS + 1] =
{0, 3000, 4575, 6150, 7725, -1};
/* Number of consecutive overheated events for each temperature sensor. */
static int8_t ot_count[TEMP_SENSOR_COUNT][THRESHOLD_COUNT + THERMAL_FAN_STEPS];
@@ -159,7 +160,9 @@ static inline void update_and_check_stat(int temp,
const int16_t threshold = config->thresholds[threshold_id];
const int delay = temp_sensors[sensor_id].action_delay_sec;
if (threshold > 0 && temp >= threshold) {
if (threshold <= 0) {
ot_count[sensor_id][threshold_id] = 0;
} else if (temp >= threshold) {
++ot_count[sensor_id][threshold_id];
if (ot_count[sensor_id][threshold_id] >= delay) {
ot_count[sensor_id][threshold_id] = delay;
@@ -174,8 +177,6 @@ static inline void update_and_check_stat(int temp,
* threshold causing overheated actions to trigger repeatedly.
*/
overheated[threshold_id] = 1;
} else {
ot_count[sensor_id][threshold_id] = 0;
}
}

View File

@@ -77,9 +77,11 @@ enum ec_error_list {
#ifdef TEST_BUILD
#define test_mockable __attribute__((weak))
#define test_mockable_static __attribute__((weak))
#define test_export_static
#else
#define test_mockable
#define test_mockable_static static
#define test_export_static static
#endif
#endif /* __CROS_EC_COMMON_H */

View File

@@ -10,7 +10,7 @@ test-list-y=pingpong timer_calib timer_dos timer_jump mutex utils
#disable: powerdemo
# TODO(victoryang): Fix these tests:
# thermal scancode typematic charging
# scancode typematic charging
test-list-$(BOARD_bds)+=
test-list-$(BOARD_daisy)+=kb_scan flash stress
@@ -26,6 +26,7 @@ test-list-$(BOARD_slippy)=
# Emulator tests
test-list-host=mutex pingpong utils kb_scan kb_mkbp lid_sw power_button hooks
test-list-host+=thermal
flash-y=flash.o
hooks-y=hooks.o
@@ -37,6 +38,8 @@ pingpong-y=pingpong.o
power_button-y=power_button.o
powerdemo-y=powerdemo.o
stress-y=stress.o
thermal-y=thermal.o
thermal-scale=200
timer_calib-y=timer_calib.o
timer_dos-y=timer_dos.o
utils-y=utils.o

236
test/thermal.c Normal file
View File

@@ -0,0 +1,236 @@
/* Copyright (c) 2013 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 thermal engine.
*/
#include "board.h"
#include "common.h"
#include "console.h"
#include "hooks.h"
#include "host_command.h"
#include "temp_sensor.h"
#include "test_util.h"
#include "thermal.h"
#include "timer.h"
#include "util.h"
static int mock_temp[TEMP_SENSOR_COUNT];
static int fan_rpm;
static int cpu_throttled;
static int cpu_down;
extern struct thermal_config_t thermal_config[TEMP_SENSOR_TYPE_COUNT];
extern const int fan_speed[THERMAL_FAN_STEPS + 1];
/*****************************************************************************/
/* Mock functions */
int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr)
{
if (mock_temp[id] >= 0) {
*temp_ptr = mock_temp[id];
return EC_SUCCESS;
} else {
return -mock_temp[id];
}
}
void pwm_set_fan_rpm_mode(int rpm_mode)
{
/* Do nothing */
}
void pwm_set_fan_target_rpm(int rpm)
{
fan_rpm = rpm;
}
void chipset_force_shutdown(void)
{
cpu_down = 1;
}
void chipset_throttle_cpu(int throttled)
{
cpu_throttled = throttled;
}
/*****************************************************************************/
/* Test utilities */
/* Test shorthands */
#define T_CPU TEMP_SENSOR_CPU
#define T_BOARD TEMP_SENSOR_BOARD
#define T_CASE TEMP_SENSOR_CASE
#define THRESHOLD(x, y) (thermal_config[x].thresholds[y])
#define FAN_THRESHOLD(x, y) THRESHOLD(x, THRESHOLD_COUNT + (y))
static void reset_mock_temp(void)
{
int i;
enum temp_sensor_type type;
for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
type = temp_sensors[i].type;
mock_temp[i] = FAN_THRESHOLD(type, 0) - 1;
}
}
static int wait_fan_rpm(int rpm, int timeout_secs)
{
do {
if (fan_rpm == rpm)
return 1;
usleep(SECOND);
} while (timeout_secs--);
return 0;
}
static int wait_value(int *v, int target, int timeout_secs)
{
do {
if (*v == target)
return 1;
usleep(SECOND);
} while (timeout_secs--);
return 0;
}
static int wait_set(int *v, int timeout_secs)
{
return wait_value(v, 1, timeout_secs);
}
static int wait_clear(int *v, int timeout_secs)
{
return wait_value(v, 0, timeout_secs);
}
/*****************************************************************************/
/* Tests */
static int test_init_val(void)
{
/* Initial mock temperature values are all zero. */
TEST_ASSERT(cpu_throttled == 0);
TEST_ASSERT(cpu_down == 0);
TEST_ASSERT(!(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD)));
TEST_ASSERT(!(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN)));
return EC_SUCCESS;
}
static int test_cpu_fan(void)
{
reset_mock_temp();
/*
* Increase CPU temperature to first fan step and check if
* the fan comes up.
*/
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 0);
TEST_ASSERT(wait_fan_rpm(fan_speed[1], 11));
/* Increase CPU temperature to second fan step */
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 1);
TEST_ASSERT(wait_fan_rpm(fan_speed[2], 11));
/* Test threshold hysteresis */
mock_temp[T_CPU]--;
usleep(15 * SECOND);
TEST_ASSERT(fan_rpm == fan_speed[2]);
/* Test action delay */
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 4);
usleep((temp_sensors[T_CPU].action_delay_sec - 1) * SECOND);
TEST_ASSERT(fan_rpm == fan_speed[2]);
mock_temp[T_CPU] = FAN_THRESHOLD(T_CPU, 0);
return EC_SUCCESS;
}
static int test_safety(void)
{
reset_mock_temp();
/* Trigger CPU throttling */
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_WARNING);
TEST_ASSERT(wait_set(&cpu_throttled, 11));
TEST_ASSERT(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD));
/* Lower temperature. CPU not throttled anymore. */
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_WARNING) - 5;
TEST_ASSERT(wait_clear(&cpu_throttled, 2));
/* Thermal shutdown */
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_CPU_DOWN);
TEST_ASSERT(wait_set(&cpu_down, 11));
TEST_ASSERT(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN));
mock_temp[T_CPU] = 0;
usleep(SECOND);
cpu_down = 0;
mock_temp[T_CPU] = THRESHOLD(T_CPU, THRESHOLD_POWER_DOWN);
TEST_ASSERT(wait_set(&cpu_down, 11));
TEST_ASSERT(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN));
return EC_SUCCESS;
}
static int test_sensor_failure(void)
{
reset_mock_temp();
/* Failure due to sensor not powered should be ignored */
mock_temp[T_CPU] = -EC_ERROR_NOT_POWERED;
usleep(2 * SECOND);
TEST_ASSERT(!(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL)));
/* Other failure should be pumped up to host */
mock_temp[T_CPU] = -EC_ERROR_UNKNOWN;
usleep(2 * SECOND);
TEST_ASSERT(host_get_events() &
EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL));
return EC_SUCCESS;
}
static int check_assumption(void)
{
TEST_ASSERT((int)TEMP_SENSOR_CPU == (int)TEMP_SENSOR_TYPE_CPU);
TEST_ASSERT((int)TEMP_SENSOR_BOARD == (int)TEMP_SENSOR_TYPE_BOARD);
TEST_ASSERT((int)TEMP_SENSOR_CASE == (int)TEMP_SENSOR_TYPE_CASE);
TEST_ASSERT(temp_sensors[T_CPU].action_delay_sec != 0);
TEST_ASSERT(thermal_config[T_CPU].config_flags &
THERMAL_CONFIG_WARNING_ON_FAIL);
return EC_SUCCESS;
}
void run_test(void)
{
test_reset();
/* Test assumptions */
RUN_TEST(check_assumption);
RUN_TEST(test_init_val);
RUN_TEST(test_cpu_fan);
/* No tests for board and case temp sensors as they are ignored. */
RUN_TEST(test_safety);
RUN_TEST(test_sensor_failure);
test_print_result();
}

View File

@@ -14,4 +14,5 @@
* '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 */
#define CONFIG_TEST_TASK_LIST \
TASK_TEST(THERMAL, thermal_task, NULL, TASK_STACK_SIZE)