summaryrefslogtreecommitdiff
path: root/cts
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2016-07-27 15:46:42 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-10-07 21:51:54 -0700
commit473ecbe2b36bc44da2552cd5814874a495913fc1 (patch)
tree116b0c658c2fa7916941d114d3ddb6ea33e8a71a /cts
parent241d9e3728c6e2d23d71330be6ddfa5015414f1d (diff)
downloadchrome-ec-473ecbe2b36bc44da2552cd5814874a495913fc1.tar.gz
cts: Add real interrupt test
Interrupt test checks whether DUT can be interrupted by an interrupt and an interrupt handler can be invoked as expected. Note the previous interrupt test ported from test/interrupt.c runs in an emulated environment on the host, thus does not test the real interrupt capability of the chip. BUG=chromium:653195 BRANCH=none TEST=Run cts.py -m interrupt Change-Id: I21cecff07594f048633d1c1b699fb3a1876379e0 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/363943 Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'cts')
-rw-r--r--cts/common/cts_common.h3
-rw-r--r--cts/interrupt/cts.testlist20
-rw-r--r--cts/interrupt/dut.c151
-rw-r--r--cts/interrupt/th.c101
4 files changed, 165 insertions, 110 deletions
diff --git a/cts/common/cts_common.h b/cts/common/cts_common.h
index e3a47d3e1b..607adbc623 100644
--- a/cts/common/cts_common.h
+++ b/cts/common/cts_common.h
@@ -27,7 +27,8 @@
#define CTS_DEBUG_PRINTF(format, args...)
#endif
-#define READ_WAIT_TIME_MS 100
+#define READ_WAIT_TIME_MS 100
+#define CTS_INTERRUPT_TRIGGER_DELAY_US (250 * MSEC)
/* In a single test, only one board can return unknown, the other must
* return a useful result (i.e. success, failure, etc)
diff --git a/cts/interrupt/cts.testlist b/cts/interrupt/cts.testlist
new file mode 100644
index 0000000000..6153c2b52d
--- /dev/null
+++ b/cts/interrupt/cts.testlist
@@ -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.
+ */
+
+/* Test interrupt_enable/disable */
+CTS_TEST(test_interrupt_enable)
+CTS_TEST(test_interrupt_disable)
+
+/* Test task_wait_for_event */
+CTS_TEST(test_task_wait_event)
+
+/* Test task_disable_irq */
+CTS_TEST(test_task_disable_irq)
+
+/*
+ * Other ideas
+ *
+ * Test back-to-back interrupts, NVIC, Priorities
+ */ \ No newline at end of file
diff --git a/cts/interrupt/dut.c b/cts/interrupt/dut.c
index 63a377fb3c..43740147a7 100644
--- a/cts/interrupt/dut.c
+++ b/cts/interrupt/dut.c
@@ -1,84 +1,135 @@
-/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+/* 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.
- *
- * Test interrupt support of EC emulator.
*/
#include "common.h"
-#include "console.h"
+#include "gpio.h"
+#include "registers.h"
#include "task.h"
-#include "test_util.h"
+#include "dut_common.h"
#include "timer.h"
-#include "util.h"
+#include "watchdog.h"
-static int main_count;
-static int has_error;
-static int interrupt_count;
+static int got_interrupt;
+static int wake_me_up;
-/* period between 50us and 3.2ms */
-#define PERIOD_US(num) (((num % 64) + 1) * 50)
-
-void my_isr(void)
+/*
+ * Raw busy loop. Returns 1 if loop finishes before interrupt is triggered.
+ * Loop length is controlled by busy_loop_timeout. It has to be set to the
+ * value which makes the loop last longer than CTS_INTERRUPT_TRIGGER_DELAY_US.
+ */
+static int busy_loop(void)
{
- int i = main_count;
+ /* TODO: Derive a proper value from clock speed */
+ const uint32_t busy_loop_timeout = 0xfffff;
+ uint32_t counter = 0;
+
+ while (counter++ < busy_loop_timeout) {
+ if (got_interrupt)
+ break;
+ watchdog_reload();
+ }
+ if (counter > busy_loop_timeout)
+ return 1;
- udelay(3 * PERIOD_US(prng_no_seed()));
- if (i != main_count || !in_interrupt_context())
- has_error = 1;
- interrupt_count++;
+ return 0;
}
-void interrupt_generator(void)
+/*
+ * Interrupt handler.
+ */
+void cts_irq(enum gpio_signal signal)
{
- while (1) {
- udelay(3 * PERIOD_US(prng_no_seed()));
- task_trigger_test_interrupt(my_isr);
- }
+ /* test some APIs */
+ got_interrupt = in_interrupt_context();
+
+ /* Wake up the CTS task */
+ if (wake_me_up)
+ task_wake(TASK_ID_CTS);
}
-static int interrupt_test(void)
+enum cts_rc test_task_wait_event(void)
{
- timestamp_t deadline = get_time();
+ uint32_t event;
- deadline.val += SECOND / 2;
- while (!timestamp_expired(deadline, NULL))
- ++main_count;
+ wake_me_up = 1;
- ccprintf("Interrupt count: %d\n", interrupt_count);
- ccprintf("Main thread tick: %d\n", main_count);
-
- TEST_ASSERT(!has_error);
- TEST_ASSERT(!in_interrupt_context());
+ /* Sleep and wait for interrupt. This shouldn't time out. */
+ event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 2);
+ if (event != TASK_EVENT_WAKE) {
+ CPRINTS("Woke up by 0x%08x", event);
+ return CTS_RC_FAILURE;
+ }
+ if (!got_interrupt) {
+ CPRINTS("Interrupt context not detected");
+ return CTS_RC_TIMEOUT;
+ }
- return EC_SUCCESS;
+ return CTS_RC_SUCCESS;
}
-static int interrupt_disable_test(void)
+enum cts_rc test_task_disable_irq(void)
{
- timestamp_t deadline = get_time();
- int start_int_cnt, end_int_cnt;
+ uint32_t event;
- deadline.val += SECOND / 2;
+ wake_me_up = 1;
- interrupt_disable();
- start_int_cnt = interrupt_count;
- while (!timestamp_expired(deadline, NULL))
- ;
- end_int_cnt = interrupt_count;
- interrupt_enable();
+ task_disable_irq(CTS_IRQ_NUMBER);
+ /* Sleep and wait for interrupt. This should time out. */
+ event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 2);
+ if (event != TASK_EVENT_TIMER) {
+ CPRINTS("Woke up by 0x%08x", event);
+ return CTS_RC_FAILURE;
+ }
+ task_enable_irq(CTS_IRQ_NUMBER);
- TEST_ASSERT(start_int_cnt == end_int_cnt);
+ return CTS_RC_SUCCESS;
+}
- return EC_SUCCESS;
+enum cts_rc test_interrupt_enable(void)
+{
+ if (busy_loop()) {
+ CPRINTS("Timeout before interrupt");
+ return CTS_RC_TIMEOUT;
+ }
+ return CTS_RC_SUCCESS;
+}
+
+enum cts_rc test_interrupt_disable(void)
+{
+ interrupt_disable();
+ if (!busy_loop()) {
+ CPRINTS("Expected timeout but didn't");
+ return CTS_RC_FAILURE;
+ }
+ return CTS_RC_SUCCESS;
}
+#include "cts_testlist.h"
+
void cts_task(void)
{
- test_reset();
+ enum cts_rc rc;
+ int i;
+
+ gpio_enable_interrupt(GPIO_CTS_IRQ);
+ interrupt_enable();
+ for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
+ got_interrupt = 0;
+ wake_me_up = 0;
+ sync();
+ rc = tests[i].run();
+ interrupt_enable();
+ CPRINTF("\n%s %d\n", tests[i].name, rc);
+ cflush();
+ }
- RUN_TEST(interrupt_test);
- RUN_TEST(interrupt_disable_test);
+ CPRINTS("Interrupt test suite finished");
+ cflush();
- test_print_result();
+ while (1) {
+ watchdog_reload();
+ sleep(1);
+ }
}
diff --git a/cts/interrupt/th.c b/cts/interrupt/th.c
index 63a377fb3c..3bcf2168b6 100644
--- a/cts/interrupt/th.c
+++ b/cts/interrupt/th.c
@@ -1,84 +1,67 @@
-/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+/* 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.
- *
- * Test interrupt support of EC emulator.
*/
#include "common.h"
-#include "console.h"
-#include "task.h"
-#include "test_util.h"
+#include "th_common.h"
+#include "gpio.h"
#include "timer.h"
-#include "util.h"
+#include "watchdog.h"
-static int main_count;
-static int has_error;
-static int interrupt_count;
-
-/* period between 50us and 3.2ms */
-#define PERIOD_US(num) (((num % 64) + 1) * 50)
-
-void my_isr(void)
+static void trigger_interrupt(void)
{
- int i = main_count;
-
- udelay(3 * PERIOD_US(prng_no_seed()));
- if (i != main_count || !in_interrupt_context())
- has_error = 1;
- interrupt_count++;
+ usleep(CTS_INTERRUPT_TRIGGER_DELAY_US);
+ gpio_set_level(GPIO_OUTPUT_TEST, 0);
+ usleep(CTS_INTERRUPT_TRIGGER_DELAY_US);
}
-void interrupt_generator(void)
+enum cts_rc test_task_wait_event(void)
{
- while (1) {
- udelay(3 * PERIOD_US(prng_no_seed()));
- task_trigger_test_interrupt(my_isr);
- }
+ trigger_interrupt();
+ return CTS_RC_SUCCESS;
}
-static int interrupt_test(void)
+enum cts_rc test_task_disable_irq(void)
{
- timestamp_t deadline = get_time();
-
- deadline.val += SECOND / 2;
- while (!timestamp_expired(deadline, NULL))
- ++main_count;
-
- ccprintf("Interrupt count: %d\n", interrupt_count);
- ccprintf("Main thread tick: %d\n", main_count);
-
- TEST_ASSERT(!has_error);
- TEST_ASSERT(!in_interrupt_context());
-
- return EC_SUCCESS;
+ trigger_interrupt();
+ return CTS_RC_SUCCESS;
}
-static int interrupt_disable_test(void)
+enum cts_rc test_interrupt_enable(void)
{
- timestamp_t deadline = get_time();
- int start_int_cnt, end_int_cnt;
-
- deadline.val += SECOND / 2;
-
- interrupt_disable();
- start_int_cnt = interrupt_count;
- while (!timestamp_expired(deadline, NULL))
- ;
- end_int_cnt = interrupt_count;
- interrupt_enable();
-
- TEST_ASSERT(start_int_cnt == end_int_cnt);
+ trigger_interrupt();
+ return CTS_RC_SUCCESS;
+}
- return EC_SUCCESS;
+enum cts_rc test_interrupt_disable(void)
+{
+ trigger_interrupt();
+ return CTS_RC_SUCCESS;
}
+#include "cts_testlist.h"
+
void cts_task(void)
{
- test_reset();
+ enum cts_rc rc;
+ int i;
- RUN_TEST(interrupt_test);
- RUN_TEST(interrupt_disable_test);
+ gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH);
- test_print_result();
+ for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
+ gpio_set_level(GPIO_OUTPUT_TEST, 1);
+ sync();
+ rc = tests[i].run();
+ CPRINTF("\n%s %d\n", tests[i].name, rc);
+ cflush();
+ }
+
+ CPRINTS("Interrupt test suite finished");
+ cflush();
+
+ while (1) {
+ watchdog_reload();
+ sleep(1);
+ }
}