mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
cts: Add real interrupt test
Interrupt test checks whether DUT can be interrupted by an interrupt and an interrupt handler can be invoked as expected. Note the previous interrupt test ported from test/interrupt.c runs in an emulated environment on the host, thus does not test the real interrupt capability of the chip. BUG=chromium:653195 BRANCH=none TEST=Run cts.py -m interrupt Change-Id: I21cecff07594f048633d1c1b699fb3a1876379e0 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/363943 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
241d9e3728
commit
473ecbe2b3
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
20
cts/interrupt/cts.testlist
Normal file
20
cts/interrupt/cts.testlist
Normal file
@@ -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
|
||||
*/
|
||||
@@ -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;
|
||||
|
||||
udelay(3 * PERIOD_US(prng_no_seed()));
|
||||
if (i != main_count || !in_interrupt_context())
|
||||
has_error = 1;
|
||||
interrupt_count++;
|
||||
}
|
||||
|
||||
void interrupt_generator(void)
|
||||
{
|
||||
while (1) {
|
||||
udelay(3 * PERIOD_US(prng_no_seed()));
|
||||
task_trigger_test_interrupt(my_isr);
|
||||
while (counter++ < busy_loop_timeout) {
|
||||
if (got_interrupt)
|
||||
break;
|
||||
watchdog_reload();
|
||||
}
|
||||
if (counter > busy_loop_timeout)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int interrupt_test(void)
|
||||
/*
|
||||
* Interrupt handler.
|
||||
*/
|
||||
void cts_irq(enum gpio_signal signal)
|
||||
{
|
||||
timestamp_t deadline = get_time();
|
||||
/* test some APIs */
|
||||
got_interrupt = in_interrupt_context();
|
||||
|
||||
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;
|
||||
/* Wake up the CTS task */
|
||||
if (wake_me_up)
|
||||
task_wake(TASK_ID_CTS);
|
||||
}
|
||||
|
||||
static int interrupt_disable_test(void)
|
||||
enum cts_rc test_task_wait_event(void)
|
||||
{
|
||||
timestamp_t deadline = get_time();
|
||||
int start_int_cnt, end_int_cnt;
|
||||
uint32_t event;
|
||||
|
||||
deadline.val += SECOND / 2;
|
||||
wake_me_up = 1;
|
||||
|
||||
/* 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 CTS_RC_SUCCESS;
|
||||
}
|
||||
|
||||
enum cts_rc test_task_disable_irq(void)
|
||||
{
|
||||
uint32_t event;
|
||||
|
||||
wake_me_up = 1;
|
||||
|
||||
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);
|
||||
|
||||
return CTS_RC_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();
|
||||
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);
|
||||
|
||||
return EC_SUCCESS;
|
||||
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;
|
||||
|
||||
RUN_TEST(interrupt_test);
|
||||
RUN_TEST(interrupt_disable_test);
|
||||
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();
|
||||
}
|
||||
|
||||
test_print_result();
|
||||
CPRINTS("Interrupt test suite finished");
|
||||
cflush();
|
||||
|
||||
while (1) {
|
||||
watchdog_reload();
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
return EC_SUCCESS;
|
||||
trigger_interrupt();
|
||||
return CTS_RC_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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user