Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests/sys_irq_handler: test for sys/irq_handler
Test application for sys/irq_handler.
- Loading branch information
Showing
2 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
include ../Makefile.tests_common | ||
|
||
BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-nano \ | ||
arduino-uno nucleo-f031k6 | ||
|
||
CFLAGS += -DIRQ_HANDLER_PRIO=THREAD_PRIORITY_MAIN+1 | ||
|
||
USEMODULE += irq_handler | ||
USEMODULE += xtimer | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/* | ||
* Copyright (C) 2019 Gunar Schorcht | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup tests | ||
* @{ | ||
* | ||
* @file | ||
* @brief Interrupt handler test application | ||
* | ||
* @author Gunar Schorcht <gunar@schorcht.net> | ||
* | ||
* This application demonstrates how to use the interrupt handler thread | ||
* module `irq_handler`. For that purpose the main thread simulates interrupts | ||
* from 2 interrupt sources with different priorities with a period | ||
* of a half second. One interrupt source triggeres a second interrupt before | ||
* the interrupts can be handled by the interrupt handler. | ||
* | ||
* To be able to simulate the interrupts by the main thread, the interrupt | ||
* handler thread has to have a lower priority as the main thread for this | ||
* example. Otherwise, the interrupts would be handled immediatly when they | ||
* are generated by the main thread. Therefore the interrupt handler thread | ||
* priority is set to THREAD_PRIORITY_MAIN+1 for this example. | ||
* @} | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <stdio.h> | ||
|
||
#include "irq_handler.h" | ||
#include "mutex.h" | ||
#include "thread.h" | ||
#include "xtimer.h" | ||
|
||
#define TEST_TIME (100 * US_PER_MS) | ||
#define TEST_REPETITIONS (10) | ||
|
||
static void _int1_service (void *arg); | ||
static void _int2_service (void *arg); | ||
|
||
static char some_stack[THREAD_STACKSIZE_MAIN]; | ||
static int i = 0; | ||
static int n_int1_handled = 0; | ||
static int n_int2_handled = 0; | ||
static int n_already_pending = 0; | ||
static mutex_t mutex = MUTEX_INIT; | ||
xtimer_t timer1a = { | ||
.callback = _int1_service, | ||
.arg = &timer1a | ||
}; | ||
xtimer_t timer1b = { | ||
.callback = _int1_service, | ||
.arg = &timer1b | ||
}; | ||
xtimer_t timer2 = { | ||
.callback = _int2_service, | ||
.arg = &timer2 | ||
}; | ||
|
||
/* preallocated and initialized interrupt event objects */ | ||
static irq_event_t _int1_event = IRQ_EVENT_INIT; | ||
static irq_event_t _int2_event = IRQ_EVENT_INIT; | ||
|
||
/* interrupt service routine for a simulated interrupt from source 1 */ | ||
static void _int1_service (void *arg) | ||
{ | ||
(void)arg; | ||
puts("int1 triggered"); | ||
/* registers just the interrupt event and returns */ | ||
if (irq_event_add(&_int1_event) == -EALREADY) { | ||
puts("int1 is already pending"); | ||
n_already_pending++; | ||
} | ||
} | ||
|
||
/* interrupt handler for interrupts from source 1 */ | ||
static void _int1_handler(void *ctx) | ||
{ | ||
xtimer_t *timer = ctx; | ||
xtimer_set(timer, TEST_TIME); | ||
puts("int1 handled"); | ||
mutex_lock(&mutex); | ||
n_int1_handled++; | ||
mutex_unlock(&mutex); | ||
} | ||
|
||
/* interrupt service routine for a simulated interrupt from source 2 */ | ||
static void _int2_service (void *arg) | ||
{ | ||
(void)arg; | ||
puts("int2 triggered"); | ||
/* registers just the interrupt event and returns */ | ||
if (irq_event_add(&_int2_event) == -EALREADY) { | ||
puts("int2 is already pending"); | ||
n_already_pending++; | ||
} | ||
} | ||
|
||
/* interrupt handler for interrupts from source 2 */ | ||
static void _int2_handler(void *ctx) | ||
{ | ||
xtimer_t *timer = ctx; | ||
xtimer_set(timer, TEST_TIME); | ||
puts("int2 handled"); | ||
mutex_lock(&mutex); | ||
n_int2_handled++; | ||
mutex_unlock(&mutex); | ||
} | ||
|
||
static void *some_thread(void *arg) | ||
{ | ||
(void)arg; | ||
|
||
puts("some_thread is starting"); | ||
|
||
while (1) { | ||
mutex_lock(&mutex); | ||
i++; | ||
mutex_unlock(&mutex); | ||
xtimer_usleep(US_PER_MS); | ||
} | ||
return NULL; | ||
} | ||
|
||
int main(void) | ||
{ | ||
_int1_event.isr = _int1_handler; | ||
_int1_event.ctx = &timer1a; | ||
|
||
_int2_event.isr = _int2_handler; | ||
_int2_event.ctx = &timer2; | ||
|
||
puts("START"); | ||
|
||
thread_create(some_stack, sizeof(some_stack), | ||
THREAD_PRIORITY_MAIN + 2, THREAD_CREATE_WOUT_YIELD, | ||
some_thread, NULL, "some_thread"); | ||
puts("some_thread created"); | ||
|
||
/* wait to let some_thread to start */ | ||
xtimer_usleep(US_PER_SEC); | ||
|
||
i = 0; | ||
|
||
xtimer_set(&timer1a, TEST_TIME); | ||
xtimer_set(&timer1b, TEST_TIME); | ||
xtimer_set(&timer2, TEST_TIME); | ||
|
||
xtimer_usleep(TEST_TIME * TEST_REPETITIONS + TEST_TIME/2); | ||
|
||
xtimer_remove(&timer1a); | ||
xtimer_remove(&timer1b); | ||
xtimer_remove(&timer2); | ||
|
||
mutex_lock(&mutex); | ||
if ((i > 0) && | ||
(n_int1_handled == TEST_REPETITIONS) && | ||
(n_int2_handled == TEST_REPETITIONS) && | ||
(n_already_pending == 1)) { | ||
puts("[SUCCESS]"); | ||
} | ||
mutex_unlock(&mutex); | ||
|
||
return 0; | ||
} |