summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-10-01 13:46:18 +0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-04 21:08:48 +0000
commitf0dc012cf75a02110f3ac98a4dbd1a395a70e794 (patch)
tree7b3e93ec612d16d8acd54b674c02a5c1507fdd66 /test
parent15eced037401c1749b634786754df17d8c58285f (diff)
downloadchrome-ec-f0dc012cf75a02110f3ac98a4dbd1a395a70e794.tar.gz
Add back unit test for usb_pd"
This is mostly the same as previous commits, but with increased delay. Previously, we have short delays (e.g. 3ms) which is too short and may cause instability. Now that we have slowed down the time when running unit tests and increased the delay, this shouldn't cause problems anymore. BUG=chrome-os-partner:31200 TEST=Repeatedly run multiple unit tests in parallel. BRANCH=Samus Change-Id: Ib55e3adc5fd27a8e233996b4799dab3cefd62318 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/220734 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'test')
-rw-r--r--test/build.mk6
-rw-r--r--test/test_config.h7
-rw-r--r--test/usb_pd.c212
-rw-r--r--test/usb_pd.tasklist19
-rw-r--r--test/usb_pd_test_util.h31
5 files changed, 273 insertions, 2 deletions
diff --git a/test/build.mk b/test/build.mk
index f503188410..8995c41fb9 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -31,12 +31,13 @@ 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 sbs_charging_v2 battery_get_params_smart
-test-list-host+=lightbar inductive_charging
+test-list-host+=lightbar inductive_charging usb_pd
adapter-y=adapter.o
-button-y=button.o
+battery_get_params_smart-y=battery_get_params_smart.o
bklight_lid-y=bklight_lid.o
bklight_passthru-y=bklight_passthru.o
+button-y=button.o
console_edit-y=console_edit.o
extpwr_gpio-y=extpwr_gpio.o
flash-y=flash.o
@@ -65,6 +66,7 @@ thermal-y=thermal.o
thermal_falco-y=thermal_falco.o
timer_calib-y=timer_calib.o
timer_dos-y=timer_dos.o
+usb_pd-y=usb_pd.o
utils-y=utils.o
battery_get_params_smart-y=battery_get_params_smart.o
lightbar-y=lightbar.o
diff --git a/test/test_config.h b/test/test_config.h
index 299e3e7930..24ccb19024 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -116,5 +116,12 @@ int board_discharge_on_ac(int enabled);
#define I2C_PORT_LIGHTBAR 1
#endif
+#ifdef TEST_USB_PD
+#define CONFIG_USB_POWER_DELIVERY
+#define CONFIG_USB_PD_CUSTOM_VDM
+#define CONFIG_USB_PD_DUAL_ROLE
+#define CONFIG_SW_CRC
+#endif
+
#endif /* TEST_BUILD */
#endif /* __CROS_EC_TEST_CONFIG_H */
diff --git a/test/usb_pd.c b/test/usb_pd.c
new file mode 100644
index 0000000000..208836fe5b
--- /dev/null
+++ b/test/usb_pd.c
@@ -0,0 +1,212 @@
+/* Copyright 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 USB PD module.
+ */
+
+#include "common.h"
+#include "crc.h"
+#include "task.h"
+#include "test_util.h"
+#include "timer.h"
+#include "usb_pd.h"
+#include "usb_pd_config.h"
+#include "usb_pd_test_util.h"
+#include "util.h"
+
+struct pd_port_t {
+ int host_mode;
+ int cc_volt[2]; /* -1 for Hi-Z */
+ int has_vbus;
+ int msg_tx_id;
+ int msg_rx_id;
+ int polarity;
+} pd_port[PD_PORT_COUNT];
+
+/* Mock functions */
+
+int pd_adc_read(int port, int cc)
+{
+ int val = pd_port[port].cc_volt[cc];
+ if (val == -1)
+ return pd_port[port].host_mode ? 3000 : 0;
+ return val;
+}
+
+int pd_snk_is_vbus_provided(int port)
+{
+ return pd_port[port].has_vbus;
+}
+
+void pd_set_host_mode(int port, int enable)
+{
+ pd_port[port].host_mode = enable;
+}
+
+void pd_select_polarity(int port, int polarity)
+{
+ pd_port[port].polarity = polarity;
+}
+
+/* Tests */
+
+void inc_tx_id(int port)
+{
+ pd_port[port].msg_tx_id = (pd_port[port].msg_tx_id + 1) % 7;
+}
+
+void inc_rx_id(int port)
+{
+ pd_port[port].msg_rx_id = (pd_port[port].msg_rx_id + 1) % 7;
+}
+
+static void init_ports(void)
+{
+ int i;
+
+ for (i = 0; i < PD_PORT_COUNT; ++i) {
+ pd_port[i].host_mode = 0;
+ pd_port[i].cc_volt[0] = pd_port[i].cc_volt[1] = -1;
+ pd_port[i].has_vbus = 0;
+ }
+}
+
+static void simulate_rx_msg(int port, uint16_t header, int cnt,
+ const uint32_t *data)
+{
+ int i;
+
+ pd_test_rx_set_preamble(port, 1);
+ pd_test_rx_msg_append_sop(port);
+ pd_test_rx_msg_append_short(port, header);
+
+ crc32_init();
+ crc32_hash16(header);
+ for (i = 0; i < cnt; ++i) {
+ pd_test_rx_msg_append_word(port, data[i]);
+ crc32_hash32(data[i]);
+ }
+ pd_test_rx_msg_append_word(port, crc32_result());
+
+ pd_test_rx_msg_append_eop(port);
+
+ pd_simulate_rx(port);
+}
+
+static void simulate_source_cap(int port)
+{
+ uint16_t header = PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
+ pd_port[port].msg_rx_id, pd_src_pdo_cnt);
+ simulate_rx_msg(port, header, pd_src_pdo_cnt, pd_src_pdo);
+}
+
+static void simulate_goodcrc(int port, int role, int id)
+{
+ simulate_rx_msg(port, PD_HEADER(PD_CTRL_GOOD_CRC, role, id, 0),
+ 0, NULL);
+}
+
+static int verify_goodcrc(int port, int role, int id)
+{
+ return pd_test_tx_msg_verify_sop(0) &&
+ pd_test_tx_msg_verify_short(0, PD_HEADER(PD_CTRL_GOOD_CRC,
+ role, id, 0)) &&
+ pd_test_tx_msg_verify_crc(0) &&
+ pd_test_tx_msg_verify_eop(0);
+}
+
+static void plug_in_source(int port, int polarity)
+{
+ pd_port[port].has_vbus = 1;
+ pd_port[port].cc_volt[polarity] = 3000;
+}
+
+static void plug_in_sink(int port, int polarity)
+{
+ pd_port[port].has_vbus = 0;
+ pd_port[port].cc_volt[polarity] = 400; /* V_rd */
+}
+
+static void unplug(int port)
+{
+ pd_port[port].has_vbus = 0;
+ pd_port[port].cc_volt[0] = -1;
+ pd_port[port].cc_volt[1] = -1;
+ task_wake(PORT_TO_TASK_ID(port));
+ usleep(30 * MSEC);
+}
+
+static int test_request(void)
+{
+ plug_in_source(0, 0);
+ task_wake(PORT_TO_TASK_ID(0));
+ task_wait_event(100 * MSEC);
+ TEST_ASSERT(pd_port[0].polarity == 0);
+
+ /* We're in SNK_DISCOVERY now. Let's send the source cap. */
+ simulate_source_cap(0);
+ task_wait_event(30 * MSEC);
+ TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[0].msg_rx_id));
+
+ /* Wait for the power request */
+ task_wake(PORT_TO_TASK_ID(0));
+ task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */
+ inc_rx_id(0);
+
+ /* Process the request */
+ TEST_ASSERT(pd_test_tx_msg_verify_sop(0));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(0,
+ PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK,
+ pd_port[0].msg_tx_id, 1)));
+ TEST_ASSERT(pd_test_tx_msg_verify_word(0, RDO_FIXED(2, 450, 900, 0)));
+ TEST_ASSERT(pd_test_tx_msg_verify_crc(0));
+ TEST_ASSERT(pd_test_tx_msg_verify_eop(0));
+ inc_tx_id(0);
+
+ /* We're done */
+ unplug(0);
+ return EC_SUCCESS;
+}
+
+static int test_sink(void)
+{
+ int i;
+
+ plug_in_sink(1, 1);
+ task_wake(PORT_TO_TASK_ID(1));
+ task_wait_event(250 * MSEC); /* tTypeCSinkWaitCap: 210~250 ms */
+ TEST_ASSERT(pd_port[1].polarity == 1);
+
+ /* The source cap should be sent */
+ TEST_ASSERT(pd_test_tx_msg_verify_sop(1));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(1,
+ PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
+ pd_port[1].msg_tx_id, pd_src_pdo_cnt)));
+ for (i = 0; i < pd_src_pdo_cnt; ++i)
+ TEST_ASSERT(pd_test_tx_msg_verify_word(1, pd_src_pdo[i]));
+ TEST_ASSERT(pd_test_tx_msg_verify_crc(1));
+ TEST_ASSERT(pd_test_tx_msg_verify_eop(1));
+
+ /* Looks good. Ack the source cap. */
+ simulate_goodcrc(1, PD_ROLE_SINK, pd_port[1].msg_tx_id);
+ task_wake(PORT_TO_TASK_ID(1));
+ usleep(30 * MSEC);
+ inc_tx_id(1);
+
+ /* We're done */
+ unplug(1);
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ test_reset();
+ init_ports();
+ pd_set_dual_role(PD_DRP_TOGGLE_ON);
+
+ RUN_TEST(test_request);
+ RUN_TEST(test_sink);
+
+ test_print_result();
+}
diff --git a/test/usb_pd.tasklist b/test/usb_pd.tasklist
new file mode 100644
index 0000000000..4d95d0b156
--- /dev/null
+++ b/test/usb_pd.tasklist
@@ -0,0 +1,19 @@
+/* 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.
+ */
+
+/**
+ * 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(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_TEST(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE)
diff --git a/test/usb_pd_test_util.h b/test/usb_pd_test_util.h
new file mode 100644
index 0000000000..5be8e0984a
--- /dev/null
+++ b/test/usb_pd_test_util.h
@@ -0,0 +1,31 @@
+/* Copyright 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 utilities for USB PD unit test.
+ */
+
+#ifndef __USB_PD_TEST_UTIL_H
+#define __USB_PD_TEST_UTIL_H
+
+/* Simulate Rx message */
+void pd_test_rx_set_preamble(int port, int has_preamble);
+void pd_test_rx_msg_append_bits(int port, uint32_t bits, int nb);
+void pd_test_rx_msg_append_kcode(int port, uint8_t kcode);
+void pd_test_rx_msg_append_sop(int port);
+void pd_test_rx_msg_append_eop(int port);
+void pd_test_rx_msg_append_4b(int port, uint8_t val);
+void pd_test_rx_msg_append_short(int port, uint16_t val);
+void pd_test_rx_msg_append_word(int port, uint32_t val);
+void pd_simulate_rx(int port);
+
+/* Verify Tx message */
+int pd_test_tx_msg_verify_kcode(int port, uint8_t kcode);
+int pd_test_tx_msg_verify_sop(int port);
+int pd_test_tx_msg_verify_eop(int port);
+int pd_test_tx_msg_verify_4b5b(int port, uint8_t b4);
+int pd_test_tx_msg_verify_short(int port, uint16_t val);
+int pd_test_tx_msg_verify_word(int port, uint32_t val);
+int pd_test_tx_msg_verify_crc(int port);
+
+#endif /* __USB_PD_TEST_UTIL_H */