From b2f14a26b9e5b72486e9a7ad0e232fed269704c2 Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Tue, 18 Oct 2016 09:27:34 -0700 Subject: eCTS: Add nested interrupt test (Low->High) Add a nested interrupt test to eCTS. Lower priority IRQ is fired, followed by higher priority IRQ. Handler executions should be nested. P1 *-----* / \ P2 *----* *----* / \ task_cts ----* *---- A B C D BUG=chromium:653195 BRANCH=none TEST=cts.py -m gpio, interrupt, timer; make buildall Change-Id: I34dc7b4e819051b9070a11e69d13d6be704f2e5f Reviewed-on: https://chromium-review.googlesource.com/408797 Commit-Ready: Daisuke Nojiri Tested-by: Daisuke Nojiri Reviewed-by: Randall Spangler --- cts/interrupt/cts.testlist | 12 +++++++++++ cts/interrupt/dut.c | 53 ++++++++++++++++++++++++++++++++++++++++++---- cts/interrupt/th.c | 25 +++++++++++++++++----- 3 files changed, 81 insertions(+), 9 deletions(-) (limited to 'cts/interrupt') diff --git a/cts/interrupt/cts.testlist b/cts/interrupt/cts.testlist index 6153c2b52d..01d6c1b06e 100644 --- a/cts/interrupt/cts.testlist +++ b/cts/interrupt/cts.testlist @@ -13,6 +13,18 @@ CTS_TEST(test_task_wait_event) /* Test task_disable_irq */ CTS_TEST(test_task_disable_irq) +/* Test nested interrupt. Lower priority IRQ is fired, followed by + * higher priority IRQ. Handler executions should be nested. + * + * P1 *-----* + * / \ + * P2 *----* *----* + * / \ + * task_cts ----* *---- + * A B C D + */ +CTS_TEST(test_nested_interrupt_low_high) + /* * Other ideas * diff --git a/cts/interrupt/dut.c b/cts/interrupt/dut.c index 43740147a7..9bf7eabde6 100644 --- a/cts/interrupt/dut.c +++ b/cts/interrupt/dut.c @@ -3,6 +3,7 @@ * found in the LICENSE file. */ +#include #include "common.h" #include "gpio.h" #include "registers.h" @@ -13,6 +14,8 @@ static int got_interrupt; static int wake_me_up; +static int state_index; +static char state[4]; /* * Raw busy loop. Returns 1 if loop finishes before interrupt is triggered. @@ -39,14 +42,35 @@ static int busy_loop(void) /* * Interrupt handler. */ -void cts_irq(enum gpio_signal signal) +void cts_irq1(enum gpio_signal signal) { + state[state_index++] = 'B'; /* test some APIs */ got_interrupt = in_interrupt_context(); /* Wake up the CTS task */ if (wake_me_up) task_wake(TASK_ID_CTS); + state[state_index++] = 'C'; +} + +void cts_irq2(enum gpio_signal signal) +{ + state[state_index++] = 'A'; + busy_loop(); + state[state_index++] = 'D'; +} + +static void clear_state(void) +{ + uint32_t *event; + + got_interrupt = 0; + wake_me_up = 0; + state_index = 0; + memset(state, '_', sizeof(state)); + event = task_get_event_bitmap(TASK_ID_CTS); + *event = 0; } enum cts_rc test_task_wait_event(void) @@ -106,6 +130,27 @@ enum cts_rc test_interrupt_disable(void) return CTS_RC_SUCCESS; } +enum cts_rc test_nested_interrupt_low_high(void) +{ + uint32_t event; + + event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 4); + if (event != TASK_EVENT_TIMER) { + CPRINTS("Woke up by 0x%08x", event); + return CTS_RC_FAILURE; + } + if (!got_interrupt) { + CPRINTS("Interrupt context not detected"); + return CTS_RC_TIMEOUT; + } + if (memcmp(state, "ABCD", sizeof(state))) { + CPRINTS("State transition differs from expectation"); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + #include "cts_testlist.h" void cts_task(void) @@ -113,11 +158,11 @@ void cts_task(void) enum cts_rc rc; int i; - gpio_enable_interrupt(GPIO_CTS_IRQ); + gpio_enable_interrupt(GPIO_CTS_IRQ1); + gpio_enable_interrupt(GPIO_CTS_IRQ2); interrupt_enable(); for (i = 0; i < CTS_TEST_ID_COUNT; i++) { - got_interrupt = 0; - wake_me_up = 0; + clear_state(); sync(); rc = tests[i].run(); interrupt_enable(); diff --git a/cts/interrupt/th.c b/cts/interrupt/th.c index 3bcf2168b6..87582490ed 100644 --- a/cts/interrupt/th.c +++ b/cts/interrupt/th.c @@ -9,34 +9,48 @@ #include "timer.h" #include "watchdog.h" -static void trigger_interrupt(void) +static void trigger_interrupt1(void) { usleep(CTS_INTERRUPT_TRIGGER_DELAY_US); gpio_set_level(GPIO_OUTPUT_TEST, 0); usleep(CTS_INTERRUPT_TRIGGER_DELAY_US); } +static void trigger_interrupt2(void) +{ + usleep(CTS_INTERRUPT_TRIGGER_DELAY_US); + gpio_set_level(GPIO_CTS_IRQ2, 0); + usleep(CTS_INTERRUPT_TRIGGER_DELAY_US); +} + enum cts_rc test_task_wait_event(void) { - trigger_interrupt(); + trigger_interrupt1(); return CTS_RC_SUCCESS; } enum cts_rc test_task_disable_irq(void) { - trigger_interrupt(); + trigger_interrupt1(); return CTS_RC_SUCCESS; } enum cts_rc test_interrupt_enable(void) { - trigger_interrupt(); + trigger_interrupt1(); return CTS_RC_SUCCESS; } enum cts_rc test_interrupt_disable(void) { - trigger_interrupt(); + trigger_interrupt1(); + return CTS_RC_SUCCESS; +} + +enum cts_rc test_nested_interrupt_low_high(void) +{ + trigger_interrupt2(); + trigger_interrupt1(); return CTS_RC_SUCCESS; } @@ -51,6 +65,7 @@ void cts_task(void) for (i = 0; i < CTS_TEST_ID_COUNT; i++) { gpio_set_level(GPIO_OUTPUT_TEST, 1); + gpio_set_level(GPIO_CTS_IRQ2, 1); sync(); rc = tests[i].run(); CPRINTF("\n%s %d\n", tests[i].name, rc); -- cgit v1.2.1