mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
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.
This commit is contained in:
@@ -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>
|
||||
|
||||
* include/bootcard.h: Documentation.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/*
|
||||
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
|
||||
*
|
||||
* Copyright (c) 2008, 2009
|
||||
* Copyright (c) 2008, 2009, 2010
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* D-82178 Puchheim
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include <rtems/irq-extension.h>
|
||||
|
||||
#include <bsp/irq-config.h>
|
||||
#include <bsp/irq.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
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
|
||||
* ranging from @ref BSP_INTERRUPT_VECTOR_MIN to @ref BSP_INTERRUPT_VECTOR_MAX
|
||||
* including the end points. It provides methods to @ref
|
||||
* bsp_interrupt_handler_install() "install", @ref
|
||||
* bsp_interrupt_handler_remove() "remove" and @ref
|
||||
* bsp_interrupt_handler_dispatch() "dispatch" interrupt handlers for each
|
||||
* including the end points. It provides methods to
|
||||
* @ref bsp_interrupt_handler_install() "install",
|
||||
* @ref bsp_interrupt_handler_remove() "remove" and
|
||||
* @ref bsp_interrupt_handler_dispatch() "dispatch" interrupt handlers for each
|
||||
* vector number. It implements parts of the RTEMS interrupt manager.
|
||||
*
|
||||
* The entry points to a list of interrupt handlers are stored in a table
|
||||
* (= handler table).
|
||||
*
|
||||
* You have to configure the BSP interrupt support in the bsp/irq-config.h file
|
||||
* for each BSP. For a minimum configuration you have to provide @ref
|
||||
* BSP_INTERRUPT_VECTOR_MIN and @ref BSP_INTERRUPT_VECTOR_MAX.
|
||||
* 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 BSP_INTERRUPT_VECTOR_MIN and @ref BSP_INTERRUPT_VECTOR_MAX.
|
||||
*
|
||||
* For boards with small memory requirements you can define @ref
|
||||
* BSP_INTERRUPT_USE_INDEX_TABLE. With an enabled index table the handler
|
||||
* For boards with small memory requirements you can define
|
||||
* @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
|
||||
* the handler table with @ref BSP_INTERRUPT_HANDLER_TABLE_SIZE. You must
|
||||
* provide a data type for the index table (@ref
|
||||
* bsp_interrupt_handler_index_type). It must be an integer type big enough to
|
||||
* index the complete handler table.
|
||||
* provide a data type for the index table
|
||||
* (@ref bsp_interrupt_handler_index_type). It must be an integer type big
|
||||
* enough to index the complete handler table.
|
||||
*
|
||||
* Normally new list entries are allocated from the heap. You may define @ref
|
||||
* BSP_INTERRUPT_NO_HEAP_USAGE, if you do not want to use the heap. For this
|
||||
* option you have to define @ref BSP_INTERRUPT_USE_INDEX_TABLE as well.
|
||||
* Normally new list entries are allocated from the heap. You may define
|
||||
* @ref BSP_INTERRUPT_NO_HEAP_USAGE, if you do not want to use the heap. For
|
||||
* 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
|
||||
* 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
|
||||
* cases the interrupt controller). It will be called then the first handler
|
||||
* is installed for the vector in bsp_interrupt_handler_install(). For a
|
||||
* vector out of range this function shall do nothing except returning
|
||||
* RTEMS_SUCCESSFUL.
|
||||
* is installed for the vector in bsp_interrupt_handler_install(). It is
|
||||
* guaranteed that the vector number is within the BSP_INTERRUPT_VECTOR_MIN and
|
||||
* BSP_INTERRUPT_VECTOR_MAX range.
|
||||
*
|
||||
* @note You must not install or remove an interrupt handler in this function.
|
||||
* 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
|
||||
* 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
|
||||
* vector out of range this function shall do nothing except returning
|
||||
* RTEMS_SUCCESSFUL.
|
||||
* handler is removed for the vector in bsp_interrupt_handler_remove(). It is
|
||||
* guaranteed that the vector number is within the BSP_INTERRUPT_VECTOR_MIN and
|
||||
* BSP_INTERRUPT_VECTOR_MAX range.
|
||||
*
|
||||
* @note You must not install or remove an interrupt handler in this function.
|
||||
* This may result in a deadlock.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/*
|
||||
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
|
||||
*
|
||||
* Copyright (c) 2008, 2009
|
||||
* Copyright (c) 2008, 2009, 2010
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* D-82178 Puchheim
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008, 2009
|
||||
* Copyright (c) 2008, 2009, 2010
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* D-82178 Puchheim
|
||||
@@ -21,11 +21,8 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <rtems/irq.h>
|
||||
|
||||
#include <bsp/irq-generic.h>
|
||||
#include <bsp/irq-info.h>
|
||||
#include <bsp/irq-config.h>
|
||||
|
||||
typedef struct {
|
||||
void *context;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009
|
||||
* Copyright (c) 2009, 2010
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* D-82178 Puchheim
|
||||
@@ -21,69 +21,90 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/chain.h>
|
||||
|
||||
#include <bsp/irq-generic.h>
|
||||
|
||||
#define BSP_INTERRUPT_EVENT RTEMS_EVENT_13
|
||||
|
||||
typedef struct bsp_interrupt_server_entry {
|
||||
rtems_chain_node node;
|
||||
rtems_vector_number vector;
|
||||
rtems_interrupt_handler handler;
|
||||
void *arg;
|
||||
struct bsp_interrupt_server_entry *volatile next;
|
||||
} 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 bsp_interrupt_server_entry *volatile
|
||||
bsp_interrupt_server_list_head = NULL;
|
||||
static RTEMS_CHAIN_DEFINE_EMPTY(bsp_interrupt_server_chain);
|
||||
|
||||
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;
|
||||
} else {
|
||||
return RTEMS_INCORRECT_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned bsp_interrupt_server_errors;
|
||||
|
||||
static void bsp_interrupt_server_trigger(void *arg)
|
||||
{
|
||||
bsp_interrupt_server_entry *e = arg;
|
||||
rtems_interrupt_level level;
|
||||
|
||||
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);
|
||||
e->next = bsp_interrupt_server_list_head;
|
||||
bsp_interrupt_server_list_head = e;
|
||||
e = (bsp_interrupt_server_entry *)
|
||||
rtems_chain_get_unprotected(&bsp_interrupt_server_chain);
|
||||
if (e != NULL) {
|
||||
e->node.next = NULL;
|
||||
}
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
rtems_semaphore_release(bsp_interrupt_server_semaphore);
|
||||
return e;
|
||||
}
|
||||
|
||||
static void bsp_interrupt_server_task(rtems_task_argument arg)
|
||||
{
|
||||
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) {
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fetch next interrupt server entry from the list */
|
||||
rtems_interrupt_disable(level);
|
||||
e = bsp_interrupt_server_list_head;
|
||||
bsp_interrupt_server_list_head = e->next;
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
while ((e = bsp_interrupt_server_get_entry()) != NULL) {
|
||||
(*e->handler)(e->arg);
|
||||
|
||||
bsp_interrupt_vector_enable(e->vector);
|
||||
}
|
||||
}
|
||||
|
||||
rtems_task_delete(RTEMS_SELF);
|
||||
}
|
||||
@@ -137,7 +158,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
|
||||
return RTEMS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
e = malloc(sizeof(bsp_interrupt_server_entry));
|
||||
e = calloc(1, sizeof(*e));
|
||||
if (e == NULL) {
|
||||
return RTEMS_NO_MEMORY;
|
||||
}
|
||||
@@ -220,67 +241,34 @@ rtems_status_code rtems_interrupt_server_initialize(
|
||||
)
|
||||
{
|
||||
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) {
|
||||
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(
|
||||
rtems_build_name('I', 'R', 'Q', 'S'),
|
||||
priority,
|
||||
stack_size,
|
||||
modes,
|
||||
attributes,
|
||||
&task_id
|
||||
&bsp_interrupt_server_id
|
||||
);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
rtems_semaphore_delete(sema_id);
|
||||
|
||||
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;
|
||||
return RTEMS_TOO_MANY;
|
||||
}
|
||||
|
||||
sc = rtems_task_start(
|
||||
task_id,
|
||||
bsp_interrupt_server_id,
|
||||
bsp_interrupt_server_task,
|
||||
0
|
||||
);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
/* In this case we could also panic */
|
||||
bsp_interrupt_server_semaphore = RTEMS_ID_NONE;
|
||||
rtems_semaphore_delete(sema_id);
|
||||
rtems_task_delete(task_id);
|
||||
rtems_task_delete(bsp_interrupt_server_id);
|
||||
bsp_interrupt_server_id = RTEMS_ID_NONE;
|
||||
|
||||
return sc;
|
||||
return RTEMS_TOO_MANY;
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
|
||||
Reference in New Issue
Block a user