summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2016-10-03 12:51:52 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-10-05 20:58:20 -0700
commit3afd683d683f482f003405c721800e3ba2ccb637 (patch)
tree0d4a7a23b273d09cbe46f49f5c41eb56ceb3db2b
parent8c22c2dcd7397cddd78e518f808212a0ac86df90 (diff)
downloadchrome-ec-3afd683d683f482f003405c721800e3ba2ccb637.tar.gz
cts: Add I2C tests for read8/16/32 and write8/16/32
This patch adds tests for i2c_read8/16/32 and i2c_write8/16/32. BUG=chromium:653183 BRANCH=none TEST=make buildall. Run cts.py -m i2c for 100kHz with 10k ohms pull-up registers on SCL and SDA. TH=stm32l476g-eval DUT=nucleo-f072rb. Change-Id: I8121b1c5dc7542da45141543e35036ef41364c38 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/393331 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/nucleo-f072rb/board.c10
-rw-r--r--board/nucleo-f072rb/board.h5
-rw-r--r--board/nucleo-f072rb/gpio.inc6
-rw-r--r--board/stm32l476g-eval/board.c8
-rw-r--r--board/stm32l476g-eval/board.h7
-rw-r--r--board/stm32l476g-eval/gpio.inc7
-rw-r--r--chip/stm32/i2c-stm32l4.c8
-rw-r--r--cts/build.mk8
-rw-r--r--cts/i2c/cts.testlist14
-rw-r--r--cts/i2c/cts_i2c.h20
-rw-r--r--cts/i2c/dut.c104
-rw-r--r--cts/i2c/th.c167
12 files changed, 359 insertions, 5 deletions
diff --git a/board/nucleo-f072rb/board.c b/board/nucleo-f072rb/board.c
index 7bbfdfab39..c3489a9617 100644
--- a/board/nucleo-f072rb/board.c
+++ b/board/nucleo-f072rb/board.c
@@ -8,6 +8,8 @@
#include "hooks.h"
#include "registers.h"
#include "task.h"
+#include "i2c.h"
+#include "timer.h"
void button_event(enum gpio_signal signal)
{
@@ -26,6 +28,14 @@ void tick_event(void)
}
DECLARE_HOOK(HOOK_TICK, tick_event, HOOK_PRIO_DEFAULT);
+#ifdef CTS_MODULE_I2C
+const struct i2c_port_t i2c_ports[] = {
+ {"test", STM32_I2C1_PORT, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA},
+};
+
+const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+#endif
+
/******************************************************************************
* Initialize board.
*/
diff --git a/board/nucleo-f072rb/board.h b/board/nucleo-f072rb/board.h
index 6c934f8450..c008deb395 100644
--- a/board/nucleo-f072rb/board.h
+++ b/board/nucleo-f072rb/board.h
@@ -18,6 +18,11 @@
/* Optional features */
#define CONFIG_STM_HWTIMER32
+#ifdef CTS_MODULE_I2C
+#define CONFIG_I2C
+#define CONFIG_I2C_MASTER
+#endif
+
#undef CONFIG_WATCHDOG_HELP
#undef CONFIG_LID_SWITCH
diff --git a/board/nucleo-f072rb/gpio.inc b/board/nucleo-f072rb/gpio.inc
index 7b38555ef8..3515d5ca84 100644
--- a/board/nucleo-f072rb/gpio.inc
+++ b/board/nucleo-f072rb/gpio.inc
@@ -19,6 +19,12 @@ UNIMPLEMENTED(WP_L)
ALTERNATE(PIN_MASK(A, 0x000C), 1, MODULE_UART, 0) /* USART2: PA2/PA3 */
+GPIO(I2C1_SCL, PIN(B, 6), GPIO_ODR_HIGH) /* I2C port 1 SCL */
+GPIO(I2C1_SDA, PIN(B, 7), GPIO_ODR_HIGH) /* I2C port 1 SDA */
+
+/* I2C1: PB6/7*/
+ALTERNATE(PIN_MASK(B, 0x00C0), GPIO_ALT_F1, MODULE_I2C, GPIO_PULL_UP)
+
#ifdef CTS_MODULE
/* CTS Signals */
GPIO(HANDSHAKE_INPUT, PIN(A, 4), GPIO_INPUT | GPIO_PULL_UP)
diff --git a/board/stm32l476g-eval/board.c b/board/stm32l476g-eval/board.c
index 6a5089a874..2ef46e8bc1 100644
--- a/board/stm32l476g-eval/board.c
+++ b/board/stm32l476g-eval/board.c
@@ -7,6 +7,7 @@
#include "gpio.h"
#include "hooks.h"
#include "registers.h"
+#include "i2c.h"
#ifdef CTS_MODULE
/*
@@ -29,3 +30,10 @@ void tick_event(void)
count++;
}
DECLARE_HOOK(HOOK_TICK, tick_event, HOOK_PRIO_DEFAULT);
+
+#ifdef CTS_MODULE_I2C
+const struct i2c_port_t i2c_ports[] = {
+ {"test", STM32_I2C2_PORT, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA},
+};
+const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+#endif
diff --git a/board/stm32l476g-eval/board.h b/board/stm32l476g-eval/board.h
index 5cfc5b0870..12a83fc8fb 100644
--- a/board/stm32l476g-eval/board.h
+++ b/board/stm32l476g-eval/board.h
@@ -29,6 +29,13 @@
/* Optional features */
#define CONFIG_STM_HWTIMER32
+#ifdef CTS_MODULE_I2C
+#define CONFIG_I2C
+#define CONFIG_I2C_SLAVE
+#define CONFIG_HOSTCMD_I2C_SLAVE_ADDR 0x3c
+#define I2C_PORT_EC STM32_I2C2_PORT
+#endif
+
/*
* Allow dangerous commands all the time, since we don't have a write protect
* switch.
diff --git a/board/stm32l476g-eval/gpio.inc b/board/stm32l476g-eval/gpio.inc
index 85447432c0..ff896d8da5 100644
--- a/board/stm32l476g-eval/gpio.inc
+++ b/board/stm32l476g-eval/gpio.inc
@@ -34,4 +34,9 @@ GPIO(OUTPUT_TEST, PIN(C, 11), GPIO_ODR_LOW)
#ifdef CTS_MODULE_GPIO
GPIO(INPUT_TEST, PIN(C, 10), GPIO_INPUT | GPIO_PULL_UP)
#endif
-#endif
+
+GPIO(I2C2_SCL, PIN(B, 10), GPIO_ODR_HIGH) /* I2C port 2 SCL */
+GPIO(I2C2_SDA, PIN(B, 11), GPIO_ODR_HIGH) /* I2C port 2 SDA */
+
+ALTERNATE(PIN_MASK(B, 0x0C00), GPIO_ALT_F4, MODULE_I2C, GPIO_ODR_HIGH) /* I2C2: PB10/11 */
+#endif \ No newline at end of file
diff --git a/chip/stm32/i2c-stm32l4.c b/chip/stm32/i2c-stm32l4.c
index 0e943767b0..bffa6cea39 100644
--- a/chip/stm32/i2c-stm32l4.c
+++ b/chip/stm32/i2c-stm32l4.c
@@ -26,7 +26,7 @@
/* Transmit timeout in microseconds */
#define I2C_TX_TIMEOUT_MASTER (10 * MSEC)
-#ifdef CONFIG_I2C_SLAVE_ADDR
+#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR
#define I2C_SLAVE_ERROR_CODE 0xec
#if (I2C_PORT_EC == STM32_I2C1_PORT)
#define IRQ_SLAVE STM32_IRQ_I2C1
@@ -177,7 +177,7 @@ static void i2c_init_port(const struct i2c_port_t *p)
/*****************************************************************************/
-#ifdef CONFIG_I2C_SLAVE_ADDR
+#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR
static void i2c_event_handler(int port)
{
@@ -451,11 +451,11 @@ static void i2c_init(void)
for (i = 0; i < i2c_ports_used; i++, p++)
i2c_init_port(p);
-#ifdef CONFIG_I2C_SLAVE_ADDR
+#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR
STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE
| STM32_I2C_CR1_ADDRIE | STM32_I2C_CR1_STOPIE
| STM32_I2C_CR1_NACKIE;
- STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 | CONFIG_I2C_SLAVE_ADDR;
+ STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 | CONFIG_HOSTCMD_I2C_SLAVE_ADDR;
task_enable_irq(IRQ_SLAVE);
#endif
}
diff --git a/cts/build.mk b/cts/build.mk
index 8d132e8da2..63b51c6fbf 100644
--- a/cts/build.mk
+++ b/cts/build.mk
@@ -9,6 +9,14 @@ ifeq "$(CTS_MODULE)" "gpio"
CFLAGS_CTS+=-DCTS_MODULE_GPIO
endif
+ifeq "$(CTS_MODULE)" "i2c"
+CFLAGS_CTS+=-DCTS_MODULE_I2C
+CONFIG_I2C=y
+ifneq ($(BOARD),stm32l476g-eval)
+CONFIG_I2C_MASTER=y
+endif
+endif
+
ifeq ($(BOARD),stm32l476g-eval)
cts-y+=$(CTS_MODULE)/th.o
cts-y+=common/th_common.o
diff --git a/cts/i2c/cts.testlist b/cts/i2c/cts.testlist
new file mode 100644
index 0000000000..79732dc65b
--- /dev/null
+++ b/cts/i2c/cts.testlist
@@ -0,0 +1,14 @@
+/* Copyright 2016 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.
+ */
+
+/* Currently tests will execute in the order they are listed here */
+
+/* Test whether sync completes successfully */
+CTS_TEST(write8_test)
+CTS_TEST(write16_test)
+CTS_TEST(write32_test)
+CTS_TEST(read8_test)
+CTS_TEST(read16_test)
+CTS_TEST(read32_test) \ No newline at end of file
diff --git a/cts/i2c/cts_i2c.h b/cts/i2c/cts_i2c.h
new file mode 100644
index 0000000000..9d287580bf
--- /dev/null
+++ b/cts/i2c/cts_i2c.h
@@ -0,0 +1,20 @@
+/* Copyright 2016 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.
+ */
+
+enum cts_i2c_packets {
+ WRITE_8_OFFSET = 0,
+ WRITE_16_OFFSET = 1,
+ WRITE_32_OFFSET = 2,
+ READ_8_OFFSET = 3,
+ READ_16_OFFSET = 4,
+ READ_32_OFFSET = 5,
+};
+
+#define WRITE_8_DATA 0x42
+#define WRITE_16_DATA 0x1234
+#define WRITE_32_DATA 0xDEADBEEF
+#define READ_8_DATA 0x23
+#define READ_16_DATA 0xACED
+#define READ_32_DATA 0x01ABCDEF
diff --git a/cts/i2c/dut.c b/cts/i2c/dut.c
new file mode 100644
index 0000000000..b629475ffa
--- /dev/null
+++ b/cts/i2c/dut.c
@@ -0,0 +1,104 @@
+/* Copyright 2016 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.
+ */
+
+#include "common.h"
+#include "cts_common.h"
+#include "cts_i2c.h"
+#include "dut_common.h"
+#include "i2c.h"
+#include "registers.h"
+#include "timer.h"
+#include "uart.h"
+#include "watchdog.h"
+
+#define TH_ADDR 0x3c
+
+enum cts_rc write8_test(void)
+{
+ int port = i2c_ports[0].port;
+
+ i2c_write8(port, TH_ADDR, WRITE_8_OFFSET, WRITE_8_DATA);
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc write16_test(void)
+{
+ int port = i2c_ports[0].port;
+
+ i2c_write16(port, TH_ADDR, WRITE_16_OFFSET, WRITE_16_DATA);
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc write32_test(void)
+{
+ int port = i2c_ports[0].port;
+
+ i2c_write32(port, TH_ADDR, WRITE_32_OFFSET, WRITE_32_DATA);
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc read8_test(void)
+{
+ int result;
+ int port = i2c_ports[0].port;
+
+ i2c_read8(port, TH_ADDR, READ_8_OFFSET, &result);
+
+ if (result != READ_8_DATA)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc read16_test(void)
+{
+ int result;
+ int port = i2c_ports[0].port;
+
+ i2c_read16(port, TH_ADDR, READ_16_OFFSET, &result);
+
+ if (result != READ_16_DATA)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc read32_test(void)
+{
+ int result;
+ int port = i2c_ports[0].port;
+
+ i2c_read32(port, TH_ADDR, READ_32_OFFSET, &result);
+
+ if (result != READ_32_DATA)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+
+#include "cts_testlist.h"
+
+void cts_task(void)
+{
+ int i;
+
+ cflush();
+ for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
+ sync();
+ CPRINTF("\n%s %d\n", tests[i].name, tests[i].run());
+ uart_flush_output();
+ }
+
+ CPRINTS("I2C test suite finished");
+ uart_flush_output();
+ while (1) {
+ watchdog_reload();
+ sleep(1);
+ }
+}
diff --git a/cts/i2c/th.c b/cts/i2c/th.c
new file mode 100644
index 0000000000..86c3a2c8de
--- /dev/null
+++ b/cts/i2c/th.c
@@ -0,0 +1,167 @@
+/* Copyright 2016 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.
+ */
+
+#include <string.h>
+#include "common.h"
+#include "cts_common.h"
+#include "cts_i2c.h"
+#include "dut_common.h"
+#include "i2c.h"
+#include "registers.h"
+#include "timer.h"
+#include "uart.h"
+#include "watchdog.h"
+
+static uint8_t inbox[I2C_MAX_HOST_PACKET_SIZE + 2];
+static char data_received;
+
+void i2c_data_received(int port, uint8_t *buf, int len)
+{
+ memcpy(inbox, buf, len);
+ data_received = 1;
+}
+
+/* CTS I2C protocol implementation */
+int i2c_set_response(int port, uint8_t *buf, int len)
+{
+ switch (buf[0]) {
+ case READ_8_OFFSET:
+ buf[0] = READ_8_DATA;
+ return 1;
+ case READ_16_OFFSET:
+ buf[0] = READ_16_DATA & 0xFF;
+ buf[1] = (READ_16_DATA >> 8) & 0xFF;
+ return 2;
+ case READ_32_OFFSET:
+ buf[0] = READ_32_DATA & 0xFF;
+ buf[1] = (READ_32_DATA >> 8) & 0xFF;
+ buf[2] = (READ_32_DATA >> 16) & 0xFF;
+ buf[3] = (READ_32_DATA >> 24) & 0xFF;
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+static int wait_for_in_flag(uint32_t timeout_ms)
+{
+ uint64_t start_time, end_time;
+
+ start_time = get_time().val;
+ end_time = start_time + timeout_ms * 1000;
+
+ while (get_time().val < end_time) {
+ if (data_received)
+ return 0;
+ msleep(5);
+ watchdog_reload();
+ }
+ return 1;
+}
+
+static void clear_inbox(void)
+{
+ memset(inbox, 0, sizeof(inbox));
+ data_received = 0;
+}
+
+enum cts_rc write8_test(void)
+{
+ int in;
+
+ if (wait_for_in_flag(100))
+ return CTS_RC_TIMEOUT;
+ if (inbox[0] != WRITE_8_OFFSET)
+ return CTS_RC_FAILURE;
+ in = inbox[1];
+ if (in != WRITE_8_DATA)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc write16_test(void)
+{
+ int in;
+
+ if (wait_for_in_flag(100))
+ return CTS_RC_TIMEOUT;
+ if (inbox[0] != WRITE_16_OFFSET)
+ return CTS_RC_FAILURE;
+ in = inbox[2] << 8 | inbox[1] << 0;
+ if (in != WRITE_16_DATA)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc write32_test(void)
+{
+ int in;
+
+ if (wait_for_in_flag(100))
+ return CTS_RC_TIMEOUT;
+ if (inbox[0] != WRITE_32_OFFSET)
+ return CTS_RC_FAILURE;
+ in = inbox[4] << 24 | inbox[3] << 16 | inbox[2] << 8 | inbox[1];
+ if (in != WRITE_32_DATA)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc read8_test(void)
+{
+ if (wait_for_in_flag(100))
+ return CTS_RC_TIMEOUT;
+ if (inbox[0] != READ_8_OFFSET)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc read16_test(void)
+{
+ if (wait_for_in_flag(100))
+ return CTS_RC_TIMEOUT;
+ if (inbox[0] != READ_16_OFFSET)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc read32_test(void)
+{
+ if (wait_for_in_flag(100))
+ return CTS_RC_TIMEOUT;
+ if (inbox[0] != READ_32_OFFSET)
+ return CTS_RC_FAILURE;
+
+ return CTS_RC_SUCCESS;
+}
+
+#include "cts_testlist.h"
+
+void cts_task(void)
+{
+ enum cts_rc result;
+ int i;
+
+ cflush();
+ for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
+ clear_inbox();
+ sync();
+ result = tests[i].run();
+ CPRINTF("\n%s %d\n", tests[i].name, result);
+ uart_flush_output();
+ }
+
+ CPRINTS("I2C test suite finished");
+ uart_flush_output();
+ while (1) {
+ watchdog_reload();
+ sleep(1);
+ }
+}