summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/nucleo-f072rb/board.c10
-rw-r--r--board/nucleo-f072rb/gpio.inc12
-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
6 files changed, 187 insertions, 110 deletions
diff --git a/board/nucleo-f072rb/board.c b/board/nucleo-f072rb/board.c
index c3489a9617..1d60231ebe 100644
--- a/board/nucleo-f072rb/board.c
+++ b/board/nucleo-f072rb/board.c
@@ -16,6 +16,16 @@ void button_event(enum gpio_signal signal)
gpio_set_level(GPIO_LED_U, 1);
}
+#ifdef CTS_MODULE
+/*
+ * Dummy interrupt handler. It's supposed to be overwritten by each suite
+ * if needed.
+ */
+__attribute__((weak)) void cts_irq(enum gpio_signal signal)
+{
+}
+#endif
+
#include "gpio_list.h"
void tick_event(void)
diff --git a/board/nucleo-f072rb/gpio.inc b/board/nucleo-f072rb/gpio.inc
index 3515d5ca84..31149bf633 100644
--- a/board/nucleo-f072rb/gpio.inc
+++ b/board/nucleo-f072rb/gpio.inc
@@ -9,6 +9,16 @@
* Note: Those with interrupt handlers must be declared first. */
GPIO_INT(USER_BUTTON, PIN(C, 13), GPIO_INT_FALLING, button_event)
+#ifdef CTS_MODULE
+#ifndef CTS_MODULE_GPIO
+/* Overload C1 for interrupt. Enabled only for non-GPIO suites as
+ * GPIO tests don't require a separate notification line. */
+GPIO_INT(CTS_IRQ, PIN(C, 1), GPIO_INT_FALLING | GPIO_PULL_UP , cts_irq)
+/* Used to disable interrupt. This IRQ# has to match the number used for the
+ * pin set above */
+#define CTS_IRQ_NUMBER STM32_IRQ_EXTI0_1
+#endif
+#endif
/* Outputs */
GPIO(LED_U, PIN(A, 5), GPIO_OUT_LOW)
@@ -29,6 +39,8 @@ ALTERNATE(PIN_MASK(B, 0x00C0), GPIO_ALT_F1, MODULE_I2C, GPIO_PULL_UP)
/* CTS Signals */
GPIO(HANDSHAKE_INPUT, PIN(A, 4), GPIO_INPUT | GPIO_PULL_UP)
GPIO(HANDSHAKE_OUTPUT, PIN(B, 0), GPIO_ODR_LOW)
+#ifdef CTS_MODULE_GPIO
GPIO(INPUT_TEST, PIN(C, 1), GPIO_INPUT | GPIO_PULL_UP)
+#endif
GPIO(OUTPUT_TEST, PIN(C, 0), GPIO_ODR_LOW)
#endif
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);
+ }
}