diff options
Diffstat (limited to 'cts/interrupt')
-rw-r--r-- | cts/interrupt/cts.testlist | 20 | ||||
-rw-r--r-- | cts/interrupt/dut.c | 151 | ||||
-rw-r--r-- | cts/interrupt/th.c | 101 |
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); + } } |