summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2016-10-18 09:27:34 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-11-09 23:26:30 -0800
commitb2f14a26b9e5b72486e9a7ad0e232fed269704c2 (patch)
tree0bad437caabacc37e80b4756c11c105da9992ebc
parentd57ca415774be9bf136d9350b9ca52bb29c0ebfb (diff)
downloadchrome-ec-b2f14a26b9e5b72486e9a7ad0e232fed269704c2.tar.gz
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 <dnojiri@chromium.org> Tested-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/nucleo-f072rb/board.c5
-rw-r--r--board/nucleo-f072rb/board.h4
-rw-r--r--board/nucleo-f072rb/gpio.inc3
-rw-r--r--board/stm32l476g-eval/gpio.inc5
-rw-r--r--cts/interrupt/cts.testlist12
-rw-r--r--cts/interrupt/dut.c53
-rw-r--r--cts/interrupt/th.c25
7 files changed, 92 insertions, 15 deletions
diff --git a/board/nucleo-f072rb/board.c b/board/nucleo-f072rb/board.c
index 1d60231ebe..48a51c7b02 100644
--- a/board/nucleo-f072rb/board.c
+++ b/board/nucleo-f072rb/board.c
@@ -21,9 +21,8 @@ void button_event(enum gpio_signal signal)
* Dummy interrupt handler. It's supposed to be overwritten by each suite
* if needed.
*/
-__attribute__((weak)) void cts_irq(enum gpio_signal signal)
-{
-}
+__attribute__((weak)) void cts_irq1(enum gpio_signal signal) {}
+__attribute__((weak)) void cts_irq2(enum gpio_signal signal) {}
#endif
#include "gpio_list.h"
diff --git a/board/nucleo-f072rb/board.h b/board/nucleo-f072rb/board.h
index c008deb395..9cc2fc2d0b 100644
--- a/board/nucleo-f072rb/board.h
+++ b/board/nucleo-f072rb/board.h
@@ -18,10 +18,14 @@
/* Optional features */
#define CONFIG_STM_HWTIMER32
+#ifdef CTS_MODULE
+#undef STM32_IRQ_EXT2_3_PRIORITY
+#define STM32_IRQ_EXT2_3_PRIORITY 2
#ifdef CTS_MODULE_I2C
#define CONFIG_I2C
#define CONFIG_I2C_MASTER
#endif
+#endif
#undef CONFIG_WATCHDOG_HELP
#undef CONFIG_LID_SWITCH
diff --git a/board/nucleo-f072rb/gpio.inc b/board/nucleo-f072rb/gpio.inc
index 31149bf633..6f3b592845 100644
--- a/board/nucleo-f072rb/gpio.inc
+++ b/board/nucleo-f072rb/gpio.inc
@@ -13,11 +13,12 @@ GPIO_INT(USER_BUTTON, PIN(C, 13), GPIO_INT_FALLING, button_event)
#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)
+GPIO_INT(CTS_IRQ1, PIN(C, 1), GPIO_INT_FALLING | GPIO_PULL_UP , cts_irq1)
/* 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
+GPIO_INT(CTS_IRQ2, PIN(C, 2), GPIO_INT_FALLING | GPIO_PULL_UP , cts_irq2)
#endif
/* Outputs */
diff --git a/board/stm32l476g-eval/gpio.inc b/board/stm32l476g-eval/gpio.inc
index ff896d8da5..9cf5bc0aa4 100644
--- a/board/stm32l476g-eval/gpio.inc
+++ b/board/stm32l476g-eval/gpio.inc
@@ -28,9 +28,10 @@ ALTERNATE(PIN_MASK(G, 0x0180), GPIO_ALT_F8, MODULE_UART, 0) /* LPUART: PG7/8 */
#ifdef CTS_MODULE
/* CTS Signals */
-GPIO(HANDSHAKE_OUTPUT, PIN(D, 2), GPIO_ODR_LOW)
-GPIO(HANDSHAKE_INPUT, PIN(C, 12), GPIO_INPUT | GPIO_PULL_UP)
+GPIO(HANDSHAKE_OUTPUT, PIN(A, 9), GPIO_ODR_LOW)
+GPIO(HANDSHAKE_INPUT, PIN(A, 8), GPIO_INPUT | GPIO_PULL_UP)
GPIO(OUTPUT_TEST, PIN(C, 11), GPIO_ODR_LOW)
+GPIO(CTS_IRQ2, PIN(C, 12), GPIO_ODR_LOW)
#ifdef CTS_MODULE_GPIO
GPIO(INPUT_TEST, PIN(C, 10), GPIO_INPUT | GPIO_PULL_UP)
#endif
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 <string.h>
#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);