summaryrefslogtreecommitdiff
path: root/cts/interrupt
diff options
context:
space:
mode:
Diffstat (limited to 'cts/interrupt')
-rw-r--r--cts/interrupt/cts.testlist20
-rw-r--r--cts/interrupt/dut.c151
-rw-r--r--cts/interrupt/th.c101
3 files changed, 163 insertions, 109 deletions
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);
+ }
}