* include/irq-config.h: Removed file.
	* include/irq.h: New file (renamed from 'include/irq-config.h').
	* include/irq-generic.h, src/irq-info.c: Include <bsp/irq.h> instead
	of <bsp/irq-config.h>.
	* src/irq-server.c: Use events instead of semaphore.  Added error
	counter for multiple chain appends.  Added error counter to detect
	erroneous interrupt events.
This commit is contained in:
Sebastian Huber
2010-04-30 11:27:01 +00:00
parent 2984b7c19f
commit 11d6263b83
5 changed files with 87 additions and 92 deletions

View File

@@ -1,3 +1,13 @@
2010-04-30 Sebastian Huber <sebastian.huber@embedded-brains.de>
* include/irq-config.h: Removed file.
* include/irq.h: New file (renamed from 'include/irq-config.h').
* include/irq-generic.h, src/irq-info.c: Include <bsp/irq.h> instead
of <bsp/irq-config.h>.
* src/irq-server.c: Use events instead of semaphore. Added error
counter for multiple chain appends. Added error counter to detect
erroneous interrupt events.
2010-04-30 Sebastian Huber <sebastian.huber@embedded-brains.de> 2010-04-30 Sebastian Huber <sebastian.huber@embedded-brains.de>
* include/bootcard.h: Documentation. * include/bootcard.h: Documentation.

View File

@@ -9,7 +9,7 @@
/* /*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette. * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
* *
* Copyright (c) 2008, 2009 * Copyright (c) 2008, 2009, 2010
* embedded brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
@@ -28,7 +28,7 @@
#include <rtems/irq-extension.h> #include <rtems/irq-extension.h>
#include <bsp/irq-config.h> #include <bsp/irq.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -86,30 +86,30 @@ static inline rtems_vector_number bsp_interrupt_handler_index(
* *
* The BSP interrupt support manages a sequence of interrupt vector numbers * The BSP interrupt support manages a sequence of interrupt vector numbers
* ranging from @ref BSP_INTERRUPT_VECTOR_MIN to @ref BSP_INTERRUPT_VECTOR_MAX * ranging from @ref BSP_INTERRUPT_VECTOR_MIN to @ref BSP_INTERRUPT_VECTOR_MAX
* including the end points. It provides methods to @ref * including the end points. It provides methods to
* bsp_interrupt_handler_install() "install", @ref * @ref bsp_interrupt_handler_install() "install",
* bsp_interrupt_handler_remove() "remove" and @ref * @ref bsp_interrupt_handler_remove() "remove" and
* bsp_interrupt_handler_dispatch() "dispatch" interrupt handlers for each * @ref bsp_interrupt_handler_dispatch() "dispatch" interrupt handlers for each
* vector number. It implements parts of the RTEMS interrupt manager. * vector number. It implements parts of the RTEMS interrupt manager.
* *
* The entry points to a list of interrupt handlers are stored in a table * The entry points to a list of interrupt handlers are stored in a table
* (= handler table). * (= handler table).
* *
* You have to configure the BSP interrupt support in the bsp/irq-config.h file * You have to configure the BSP interrupt support in the <bsp/irq.h> file
* for each BSP. For a minimum configuration you have to provide @ref * for each BSP. For a minimum configuration you have to provide
* BSP_INTERRUPT_VECTOR_MIN and @ref BSP_INTERRUPT_VECTOR_MAX. * @ref BSP_INTERRUPT_VECTOR_MIN and @ref BSP_INTERRUPT_VECTOR_MAX.
* *
* For boards with small memory requirements you can define @ref * For boards with small memory requirements you can define
* BSP_INTERRUPT_USE_INDEX_TABLE. With an enabled index table the handler * @ref BSP_INTERRUPT_USE_INDEX_TABLE. With an enabled index table the handler
* table will be accessed via a small index table. You can define the size of * table will be accessed via a small index table. You can define the size of
* the handler table with @ref BSP_INTERRUPT_HANDLER_TABLE_SIZE. You must * the handler table with @ref BSP_INTERRUPT_HANDLER_TABLE_SIZE. You must
* provide a data type for the index table (@ref * provide a data type for the index table
* bsp_interrupt_handler_index_type). It must be an integer type big enough to * (@ref bsp_interrupt_handler_index_type). It must be an integer type big
* index the complete handler table. * enough to index the complete handler table.
* *
* Normally new list entries are allocated from the heap. You may define @ref * Normally new list entries are allocated from the heap. You may define
* BSP_INTERRUPT_NO_HEAP_USAGE, if you do not want to use the heap. For this * @ref BSP_INTERRUPT_NO_HEAP_USAGE, if you do not want to use the heap. For
* option you have to define @ref BSP_INTERRUPT_USE_INDEX_TABLE as well. * this option you have to define @ref BSP_INTERRUPT_USE_INDEX_TABLE as well.
* *
* You have to provide some special routines in your BSP (follow the links for * You have to provide some special routines in your BSP (follow the links for
* the details): * the details):
@@ -182,9 +182,9 @@ rtems_status_code bsp_interrupt_facility_initialize(void);
* *
* This function shall enable the vector at the corresponding facility (in most * This function shall enable the vector at the corresponding facility (in most
* cases the interrupt controller). It will be called then the first handler * cases the interrupt controller). It will be called then the first handler
* is installed for the vector in bsp_interrupt_handler_install(). For a * is installed for the vector in bsp_interrupt_handler_install(). It is
* vector out of range this function shall do nothing except returning * guaranteed that the vector number is within the BSP_INTERRUPT_VECTOR_MIN and
* RTEMS_SUCCESSFUL. * BSP_INTERRUPT_VECTOR_MAX range.
* *
* @note You must not install or remove an interrupt handler in this function. * @note You must not install or remove an interrupt handler in this function.
* This may result in a deadlock. * This may result in a deadlock.
@@ -198,9 +198,9 @@ rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector);
* *
* This function shall disable the vector at the corresponding facility (in * This function shall disable the vector at the corresponding facility (in
* most cases the interrupt controller). It will be called then the last * most cases the interrupt controller). It will be called then the last
* handler is removed for the vector in bsp_interrupt_handler_remove(). For a * handler is removed for the vector in bsp_interrupt_handler_remove(). It is
* vector out of range this function shall do nothing except returning * guaranteed that the vector number is within the BSP_INTERRUPT_VECTOR_MIN and
* RTEMS_SUCCESSFUL. * BSP_INTERRUPT_VECTOR_MAX range.
* *
* @note You must not install or remove an interrupt handler in this function. * @note You must not install or remove an interrupt handler in this function.
* This may result in a deadlock. * This may result in a deadlock.

View File

@@ -9,7 +9,7 @@
/* /*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette. * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
* *
* Copyright (c) 2008, 2009 * Copyright (c) 2008, 2009, 2010
* embedded brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim

View File

@@ -7,7 +7,7 @@
*/ */
/* /*
* Copyright (c) 2008, 2009 * Copyright (c) 2008, 2009, 2010
* embedded brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
@@ -21,11 +21,8 @@
#include <inttypes.h> #include <inttypes.h>
#include <rtems/irq.h>
#include <bsp/irq-generic.h> #include <bsp/irq-generic.h>
#include <bsp/irq-info.h> #include <bsp/irq-info.h>
#include <bsp/irq-config.h>
typedef struct { typedef struct {
void *context; void *context;

View File

@@ -7,7 +7,7 @@
*/ */
/* /*
* Copyright (c) 2009 * Copyright (c) 2009, 2010
* embedded brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
@@ -21,68 +21,89 @@
#include <stdlib.h> #include <stdlib.h>
#include <rtems.h>
#include <rtems/chain.h>
#include <bsp/irq-generic.h> #include <bsp/irq-generic.h>
#define BSP_INTERRUPT_EVENT RTEMS_EVENT_13
typedef struct bsp_interrupt_server_entry { typedef struct bsp_interrupt_server_entry {
rtems_chain_node node;
rtems_vector_number vector; rtems_vector_number vector;
rtems_interrupt_handler handler; rtems_interrupt_handler handler;
void *arg; void *arg;
struct bsp_interrupt_server_entry *volatile next;
} bsp_interrupt_server_entry; } bsp_interrupt_server_entry;
static rtems_id bsp_interrupt_server_semaphore = RTEMS_ID_NONE; static rtems_id bsp_interrupt_server_id = RTEMS_ID_NONE;
/* LIFO list head */ static RTEMS_CHAIN_DEFINE_EMPTY(bsp_interrupt_server_chain);
static bsp_interrupt_server_entry *volatile
bsp_interrupt_server_list_head = NULL;
static rtems_status_code bsp_interrupt_server_is_initialized(void) static rtems_status_code bsp_interrupt_server_is_initialized(void)
{ {
if (bsp_interrupt_server_semaphore != RTEMS_ID_NONE) { if (bsp_interrupt_server_id != RTEMS_ID_NONE) {
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} else { } else {
return RTEMS_INCORRECT_STATE; return RTEMS_INCORRECT_STATE;
} }
} }
static unsigned bsp_interrupt_server_errors;
static void bsp_interrupt_server_trigger(void *arg) static void bsp_interrupt_server_trigger(void *arg)
{ {
bsp_interrupt_server_entry *e = arg; bsp_interrupt_server_entry *e = arg;
rtems_interrupt_level level;
bsp_interrupt_vector_disable(e->vector); bsp_interrupt_vector_disable(e->vector);
/* Add interrupt server entry to the list */ if (e->node.next == NULL) {
rtems_chain_append(&bsp_interrupt_server_chain, &e->node);
} else {
++bsp_interrupt_server_errors;
}
rtems_event_send(bsp_interrupt_server_id, BSP_INTERRUPT_EVENT);
}
static bsp_interrupt_server_entry *bsp_interrupt_server_get_entry(void)
{
rtems_interrupt_level level;
bsp_interrupt_server_entry *e;
rtems_interrupt_disable(level); rtems_interrupt_disable(level);
e->next = bsp_interrupt_server_list_head; e = (bsp_interrupt_server_entry *)
bsp_interrupt_server_list_head = e; rtems_chain_get_unprotected(&bsp_interrupt_server_chain);
if (e != NULL) {
e->node.next = NULL;
}
rtems_interrupt_enable(level); rtems_interrupt_enable(level);
rtems_semaphore_release(bsp_interrupt_server_semaphore); return e;
} }
static void bsp_interrupt_server_task(rtems_task_argument arg) static void bsp_interrupt_server_task(rtems_task_argument arg)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_id sema = bsp_interrupt_server_semaphore;
rtems_interrupt_level level;
bsp_interrupt_server_entry *e = NULL;
while (true) { while (true) {
sc = rtems_semaphore_obtain(sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); rtems_event_set events = 0;
bsp_interrupt_server_entry *e = NULL;
sc = rtems_event_receive(
BSP_INTERRUPT_EVENT,
RTEMS_EVENT_ALL | RTEMS_WAIT,
RTEMS_NO_TIMEOUT,
&events
);
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
break; break;
} }
/* Fetch next interrupt server entry from the list */ while ((e = bsp_interrupt_server_get_entry()) != NULL) {
rtems_interrupt_disable(level); (*e->handler)(e->arg);
e = bsp_interrupt_server_list_head;
bsp_interrupt_server_list_head = e->next;
rtems_interrupt_enable(level);
(*e->handler)(e->arg); bsp_interrupt_vector_enable(e->vector);
}
bsp_interrupt_vector_enable(e->vector);
} }
rtems_task_delete(RTEMS_SELF); rtems_task_delete(RTEMS_SELF);
@@ -137,7 +158,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
return RTEMS_NOT_IMPLEMENTED; return RTEMS_NOT_IMPLEMENTED;
} }
e = malloc(sizeof(bsp_interrupt_server_entry)); e = calloc(1, sizeof(*e));
if (e == NULL) { if (e == NULL) {
return RTEMS_NO_MEMORY; return RTEMS_NO_MEMORY;
} }
@@ -220,67 +241,34 @@ rtems_status_code rtems_interrupt_server_initialize(
) )
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_id sema_id = RTEMS_ID_NONE;
rtems_id task_id = RTEMS_ID_NONE;
rtems_interrupt_level level;
if (server != NULL) { if (server != NULL) {
return RTEMS_NOT_IMPLEMENTED; return RTEMS_NOT_IMPLEMENTED;
} }
sc = rtems_semaphore_create(
rtems_build_name('I', 'R', 'Q', 'S'),
0,
RTEMS_LOCAL | RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE,
0,
&sema_id
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
sc = rtems_task_create( sc = rtems_task_create(
rtems_build_name('I', 'R', 'Q', 'S'), rtems_build_name('I', 'R', 'Q', 'S'),
priority, priority,
stack_size, stack_size,
modes, modes,
attributes, attributes,
&task_id &bsp_interrupt_server_id
); );
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
rtems_semaphore_delete(sema_id); return RTEMS_TOO_MANY;
return sc;
}
/* Initialize global data (this must be done before the task starts) */
rtems_interrupt_disable(level);
if (bsp_interrupt_server_semaphore == RTEMS_ID_NONE) {
bsp_interrupt_server_semaphore = sema_id;
sc = RTEMS_SUCCESSFUL;
} else {
sc = RTEMS_INCORRECT_STATE;
}
rtems_interrupt_enable(level);
if (sc != RTEMS_SUCCESSFUL) {
rtems_semaphore_delete(sema_id);
rtems_task_delete(task_id);
return sc;
} }
sc = rtems_task_start( sc = rtems_task_start(
task_id, bsp_interrupt_server_id,
bsp_interrupt_server_task, bsp_interrupt_server_task,
0 0
); );
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
/* In this case we could also panic */ /* In this case we could also panic */
bsp_interrupt_server_semaphore = RTEMS_ID_NONE; rtems_task_delete(bsp_interrupt_server_id);
rtems_semaphore_delete(sema_id); bsp_interrupt_server_id = RTEMS_ID_NONE;
rtems_task_delete(task_id);
return sc; return RTEMS_TOO_MANY;
} }
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;