* include/irq-config.h, include/irq-generic.h, include/irq-info.h,
	src/irq-generic.c, src/irq-info.c, src/irq-legacy.c, src/irq-shell.c:
	Format, cleanup and documentation.
	* src/irq-server.c: New file.
	* include/bootcard.h, include/stackalloc.h, src/stackalloc.c,
	bsplibc.c: Update for heap API changes. Documentation.
This commit is contained in:
Joel Sherrill
2009-09-08 13:35:07 +00:00
parent 17310b9d1e
commit 8634637d1d
13 changed files with 1031 additions and 558 deletions

View File

@@ -1,3 +1,12 @@
2009-09-08 Sebastian Huber <sebastian.huber@embedded-brains.de>
* include/irq-config.h, include/irq-generic.h, include/irq-info.h,
src/irq-generic.c, src/irq-info.c, src/irq-legacy.c, src/irq-shell.c:
Format, cleanup and documentation.
* src/irq-server.c: New file.
* include/bootcard.h, include/stackalloc.h, src/stackalloc.c,
bsplibc.c: Update for heap API changes. Documentation.
2009-08-28 Joel Sherrill <joel.sherrill@OARcorp.com> 2009-08-28 Joel Sherrill <joel.sherrill@OARcorp.com>
* bootcard.c, bsplibc.c, clockdrv_shell.h, console-polled.c: Fix * bootcard.c, bsplibc.c, clockdrv_shell.h, console-polled.c: Fix

View File

@@ -12,12 +12,12 @@
#include <bsp/bootcard.h> #include <bsp/bootcard.h>
void bsp_libc_init( void bsp_libc_init(
void *heap_start, void *heap_begin,
size_t heap_size, uintptr_t heap_size,
size_t sbrk_amount size_t sbrk_amount
) )
{ {
RTEMS_Malloc_Initialize( heap_start, heap_size, sbrk_amount ); RTEMS_Malloc_Initialize( heap_begin, heap_size, sbrk_amount );
/* /*
* Init the RTEMS libio facility to provide UNIX-like system * Init the RTEMS libio facility to provide UNIX-like system

View File

@@ -1,9 +1,9 @@
/** /**
* @file * @file
* *
* @ingroup bsp_shared * @ingroup bsp_bootcard
* *
* @brief Header file for basic BSP startup functions. * @brief Standard system startup.
*/ */
/* /*
@@ -21,7 +21,19 @@
*/ */
/** /**
* @defgroup bsp_shared Shared BSP Code * @defgroup bsp_kit Board Support Package
*
* @brief Board support package dependent code.
*/
/**
* @defgroup bsp_bootcard Bootcard
*
* @ingroup bsp_kit
*
* @brief Standard system startup.
*
* @{
*/ */
#ifndef LIBBSP_SHARED_BOOTCARD_H #ifndef LIBBSP_SHARED_BOOTCARD_H
@@ -37,6 +49,11 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
/**
* @brief Global pointer to the command line of boot_card().
*/
extern const char *bsp_boot_cmdline;
void bsp_start(void); void bsp_start(void);
void bsp_pretasking_hook(void); void bsp_pretasking_hook(void);
@@ -49,20 +66,72 @@ void bsp_cleanup(void);
void bsp_reset(void); void bsp_reset(void);
/**
* @brief Should be used as the heap begin address in bsp_get_work_area() if
* the heap area is contained in the work area.
*/
#define BSP_BOOTCARD_HEAP_USES_WORK_AREA NULL #define BSP_BOOTCARD_HEAP_USES_WORK_AREA NULL
/**
* @brief Should be used to request the default heap size in bsp_get_work_area().
*
* In case that the heap area is contained in the work area this heap size
* value indicates that the area outside the work space should be used as heap
* space.
*/
#define BSP_BOOTCARD_HEAP_SIZE_DEFAULT 0 #define BSP_BOOTCARD_HEAP_SIZE_DEFAULT 0
void bsp_get_work_area( void bsp_get_work_area(
void **work_area_start, void **work_area_begin,
uintptr_t *work_area_size, uintptr_t *work_area_size,
void **heap_start, void **heap_begin,
uintptr_t *heap_size uintptr_t *heap_size
); );
int boot_card( const char *cmdline ); /**
* @brief Standard system initialization procedure.
*
* You may pass a command line in @a cmdline. It is later available via the
* global @ref bsp_boot_cmdline variable.
*
* This is the C entry point for ALL RTEMS BSPs. It is invoked from the
* assembly language initialization file usually called @c start.S which does
* the basic CPU setup (stack, C runtime environment, zero BSS, load other
* sections) and calls afterwards boot_card(). The boot card function provides
* the framework for the BSP initialization sequence. The basic flow of
* initialization is:
*
* - disable interrupts, interrupts will be enabled during the first context switch
* - bsp_start() - more advanced initialization
* - obtain information on BSP memory via bsp_get_work_area() and allocate RTEMS Workspace
* - rtems_initialize_data_structures()
* - allocate memory for C Program Heap
* - initialize C Library and C Program Heap
* - bsp_pretasking_hook()
* - if defined( RTEMS_DEBUG )
* - rtems_debug_enable( RTEMS_DEBUG_ALL_MASK )
* - rtems_initialize_before_drivers()
* - bsp_predriver_hook()
* - rtems_initialize_device_drivers()
* - initialization of all device drivers
* - bsp_postdriver_hook()
* - rtems_initialize_start_multitasking()
* - 1st task executes C++ global constructors
* - .... appplication runs ...
* - exit
* - back to here eventually
* - bsp_cleanup()
*
* If something goes wrong bsp_cleanup() will be called out of order.
*
* This style of initialization ensures that the C++ global constructors are
* executed after RTEMS is initialized.
*/
int boot_card(const char *cmdline);
void bsp_libc_init( void *heap_start, size_t heap_size, size_t sbrk_amount); /** @} */
void bsp_libc_init(void *heap_begin, uintptr_t heap_size, size_t sbrk_amount);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -9,15 +9,16 @@
/* /*
* 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 * Copyright (c) 2008, 2009
* Embedded Brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be found in the file * The license and distribution terms for this file may be
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE. * found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/ */
#ifndef LIBBSP_SHARED_IRQ_CONFIG_H #ifndef LIBBSP_SHARED_IRQ_CONFIG_H
@@ -60,18 +61,16 @@
#undef BSP_INTERRUPT_NO_HEAP_USAGE #undef BSP_INTERRUPT_NO_HEAP_USAGE
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
/**
* @brief Size of the handler table.
*/
#define BSP_INTERRUPT_HANDLER_TABLE_SIZE 0
/** /**
* @brief Size of the handler table. * @brief Integer type capable to index the complete handler table.
*/ */
#define BSP_INTERRUPT_HANDLER_TABLE_SIZE 0 typedef uint8_t bsp_interrupt_handler_index_type;
#endif
/**
* @brief Integer type capable to index the complete handler table.
*/
typedef uint8_t bsp_interrupt_handler_index_type;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
/** @} */ /** @} */

View File

@@ -3,21 +3,22 @@
* *
* @ingroup bsp_interrupt * @ingroup bsp_interrupt
* *
* @brief Header file for generic BSP interrupt support. * @brief Generic BSP interrupt support API.
*/ */
/* /*
* 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 * Copyright (c) 2008, 2009
* Embedded Brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be found in the file * The license and distribution terms for this file may be
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE. * found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/ */
#ifndef LIBBSP_SHARED_IRQ_GENERIC_H #ifndef LIBBSP_SHARED_IRQ_GENERIC_H
@@ -33,29 +34,30 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
#if !defined( BSP_INTERRUPT_VECTOR_MIN) || !defined( BSP_INTERRUPT_VECTOR_MAX) || (BSP_INTERRUPT_VECTOR_MAX + 1) < BSP_INTERRUPT_VECTOR_MIN #if !defined(BSP_INTERRUPT_VECTOR_MIN) || !defined(BSP_INTERRUPT_VECTOR_MAX) || (BSP_INTERRUPT_VECTOR_MAX + 1) < BSP_INTERRUPT_VECTOR_MIN
#error Invalid BSP_INTERRUPT_VECTOR_MIN or BSP_INTERRUPT_VECTOR_MAX. #error "invalid BSP_INTERRUPT_VECTOR_MIN or BSP_INTERRUPT_VECTOR_MAX"
#endif /* !defined( BSP_INTERRUPT_VECTOR_MIN) ... */ #endif
#if defined( BSP_INTERRUPT_USE_INDEX_TABLE) && !defined( BSP_INTERRUPT_HANDLER_TABLE_SIZE) #if defined(BSP_INTERRUPT_USE_INDEX_TABLE) && !defined(BSP_INTERRUPT_HANDLER_TABLE_SIZE)
#error If you define BSP_INTERRUPT_USE_INDEX_TABLE, you have to define BSP_INTERRUPT_HANDLER_TABLE_SIZE etc. as well. #error "if you define BSP_INTERRUPT_USE_INDEX_TABLE, you have to define BSP_INTERRUPT_HANDLER_TABLE_SIZE etc. as well"
#endif /* defined( BSP_INTERRUPT_USE_INDEX_TABLE) ... */ #endif
#if defined( BSP_INTERRUPT_NO_HEAP_USAGE) && !defined( BSP_INTERRUPT_USE_INDEX_TABLE) #if defined(BSP_INTERRUPT_NO_HEAP_USAGE) && !defined(BSP_INTERRUPT_USE_INDEX_TABLE)
#error If you define BSP_INTERRUPT_NO_HEAP_USAGE, you have to define BSP_INTERRUPT_USE_INDEX_TABLE etc. as well. #error "if you define BSP_INTERRUPT_NO_HEAP_USAGE, you have to define BSP_INTERRUPT_USE_INDEX_TABLE etc. as well"
#endif /* defined( BSP_INTERRUPT_NO_HEAP_USAGE) ... */ #endif
#define BSP_INTERRUPT_VECTOR_NUMBER (BSP_INTERRUPT_VECTOR_MAX - BSP_INTERRUPT_VECTOR_MIN + 1) #define BSP_INTERRUPT_VECTOR_NUMBER \
(BSP_INTERRUPT_VECTOR_MAX - BSP_INTERRUPT_VECTOR_MIN + 1)
#ifndef BSP_INTERRUPT_HANDLER_TABLE_SIZE #ifndef BSP_INTERRUPT_HANDLER_TABLE_SIZE
#define BSP_INTERRUPT_HANDLER_TABLE_SIZE BSP_INTERRUPT_VECTOR_NUMBER #define BSP_INTERRUPT_HANDLER_TABLE_SIZE BSP_INTERRUPT_VECTOR_NUMBER
#endif /* BSP_INTERRUPT_HANDLER_TABLE_SIZE */ #endif
struct bsp_interrupt_handler_entry { struct bsp_interrupt_handler_entry {
rtems_interrupt_handler handler; rtems_interrupt_handler handler;
void *arg; void *arg;
const char *info; const char *info;
struct bsp_interrupt_handler_entry *next; struct bsp_interrupt_handler_entry *next;
}; };
typedef struct bsp_interrupt_handler_entry bsp_interrupt_handler_entry; typedef struct bsp_interrupt_handler_entry bsp_interrupt_handler_entry;
@@ -63,16 +65,18 @@ typedef struct bsp_interrupt_handler_entry bsp_interrupt_handler_entry;
extern bsp_interrupt_handler_entry bsp_interrupt_handler_table []; extern bsp_interrupt_handler_entry bsp_interrupt_handler_table [];
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
extern bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table []; extern bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table [];
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */ #endif
static inline rtems_vector_number bsp_interrupt_handler_index( rtems_vector_number vector) static inline rtems_vector_number bsp_interrupt_handler_index(
rtems_vector_number vector
)
{ {
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
return bsp_interrupt_handler_index_table [vector - BSP_INTERRUPT_VECTOR_MIN]; return bsp_interrupt_handler_index_table [vector - BSP_INTERRUPT_VECTOR_MIN];
#else /* BSP_INTERRUPT_USE_INDEX_TABLE */ #else
return vector - BSP_INTERRUPT_VECTOR_MIN; return vector - BSP_INTERRUPT_VECTOR_MIN;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */ #endif
} }
/** /**
@@ -129,10 +133,10 @@ static inline rtems_vector_number bsp_interrupt_handler_index( rtems_vector_numb
/** /**
* @brief Returns true if the interrupt vector with number @a vector is valid. * @brief Returns true if the interrupt vector with number @a vector is valid.
*/ */
static inline bool bsp_interrupt_is_valid_vector( rtems_vector_number vector) static inline bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
{ {
return (rtems_vector_number) BSP_INTERRUPT_VECTOR_MIN <= vector return (rtems_vector_number) BSP_INTERRUPT_VECTOR_MIN <= vector
&& vector <= (rtems_vector_number) BSP_INTERRUPT_VECTOR_MAX; && vector <= (rtems_vector_number) BSP_INTERRUPT_VECTOR_MAX;
} }
/** /**
@@ -144,7 +148,7 @@ static inline bool bsp_interrupt_is_valid_vector( rtems_vector_number vector)
* *
* @note This function must cope with arbitrary vector numbers @a vector. * @note This function must cope with arbitrary vector numbers @a vector.
*/ */
void bsp_interrupt_handler_default( rtems_vector_number vector); void bsp_interrupt_handler_default(rtems_vector_number vector);
/** /**
* @brief Initialize BSP interrupt support. * @brief Initialize BSP interrupt support.
@@ -154,7 +158,7 @@ void bsp_interrupt_handler_default( rtems_vector_number vector);
* function will be called after all internals are initialized. Initialization * function will be called after all internals are initialized. Initialization
* is complete if everything was successful. * is complete if everything was successful.
*/ */
rtems_status_code bsp_interrupt_initialize( void); rtems_status_code bsp_interrupt_initialize(void);
/** /**
* @brief BSP specific initialization. * @brief BSP specific initialization.
@@ -171,7 +175,7 @@ rtems_status_code bsp_interrupt_initialize( void);
* *
* @return On success RTEMS_SUCCESSFUL shall be returned. * @return On success RTEMS_SUCCESSFUL shall be returned.
*/ */
rtems_status_code bsp_interrupt_facility_initialize( void); rtems_status_code bsp_interrupt_facility_initialize(void);
/** /**
* @brief Enables the interrupt vector with number @a vector. * @brief Enables the interrupt vector with number @a vector.
@@ -187,7 +191,7 @@ rtems_status_code bsp_interrupt_facility_initialize( void);
* *
* @return On success RTEMS_SUCCESSFUL shall be returned. * @return On success RTEMS_SUCCESSFUL shall be returned.
*/ */
rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector); rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector);
/** /**
* @brief Disables the interrupt vector with number @a vector. * @brief Disables the interrupt vector with number @a vector.
@@ -203,7 +207,7 @@ rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector);
* *
* @return On success RTEMS_SUCCESSFUL shall be returned. * @return On success RTEMS_SUCCESSFUL shall be returned.
*/ */
rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector); rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector);
/** /**
* @brief Sequencially calls all interrupt handlers for the vector number @a * @brief Sequencially calls all interrupt handlers for the vector number @a
@@ -215,18 +219,19 @@ rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector);
* You can call this function within every context which can be disabled via * You can call this function within every context which can be disabled via
* rtems_interrupt_disable(). * rtems_interrupt_disable().
*/ */
static inline void bsp_interrupt_handler_dispatch( rtems_vector_number vector) static inline void bsp_interrupt_handler_dispatch(rtems_vector_number vector)
{ {
if (bsp_interrupt_is_valid_vector( vector)) { if (bsp_interrupt_is_valid_vector(vector)) {
bsp_interrupt_handler_entry *e = &bsp_interrupt_handler_table [bsp_interrupt_handler_index( vector)]; bsp_interrupt_handler_entry *e =
&bsp_interrupt_handler_table [bsp_interrupt_handler_index(vector)];
do { do {
e->handler( vector, e->arg); (*e->handler)(vector, e->arg);
e = e->next; e = e->next;
} while (e != NULL); } while (e != NULL);
} else { } else {
bsp_interrupt_handler_default( vector); bsp_interrupt_handler_default(vector);
} }
} }
/** @} */ /** @} */

View File

@@ -3,19 +3,20 @@
* *
* @ingroup bsp_interrupt * @ingroup bsp_interrupt
* *
* @brief Header file for generic BSP interrupt information. * @brief Generic BSP interrupt information API.
*/ */
/* /*
* Copyright (c) 2008 * Copyright (c) 2008, 2009
* Embedded Brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be found in the file * The license and distribution terms for this file may be
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE. * found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/ */
#ifndef LIBBSP_SHARED_IRQ_INFO_H #ifndef LIBBSP_SHARED_IRQ_INFO_H
@@ -36,10 +37,23 @@ extern "C" {
* @{ * @{
*/ */
void bsp_interrupt_report_with_plugin( void *context, rtems_printk_plugin_t print); /**
* @brief Prints interrupt information via the printk plugin @a print with the
* context @a context.
*/
void bsp_interrupt_report_with_plugin(
void *context,
rtems_printk_plugin_t print
);
void bsp_interrupt_report( void); /**
* @brief Prints interrupt information via the default printk plugin.
*/
void bsp_interrupt_report(void);
/**
* @brief Shell command entry for interrupt information.
*/
extern struct rtems_shell_cmd_tt bsp_interrupt_shell_command; extern struct rtems_shell_cmd_tt bsp_interrupt_shell_command;
/** @} */ /** @} */

View File

@@ -1,9 +1,9 @@
/** /**
* @file * @file
* *
* @ingroup bsp_shared * @ingroup bsp_stack
* *
* @brief Stack initialization, allocation and free functions. * @brief Task stack initialization, allocation and free functions.
*/ */
/* /*
@@ -22,22 +22,68 @@
#ifndef LIBBSP_SHARED_STACK_ALLOC_H #ifndef LIBBSP_SHARED_STACK_ALLOC_H
#define LIBBSP_SHARED_STACK_ALLOC_H #define LIBBSP_SHARED_STACK_ALLOC_H
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void bsp_stack_initialize(void *start, intptr_t size); /**
* @defgroup bsp_stack Task Stack Allocator
*
* @ingroup bsp_kit
*
* @brief Task stack initialization, allocation and free functions.
*
* Initialize the task stack allocator with bsp_stack_initialize(). To enable
* the task stack allocator use the following in the system configuration:
*
* @code
* #include <bsp/stackalloc.h>
*
* #define CONFIGURE_INIT
*
* #include <confdefs.h>
* @endcode
*
* @{
*/
void *bsp_stack_allocate(uint32_t size); /**
* @brief Task stack management initialization.
*
* This function should be called in bsp_start() with the designated task stack
* area begin address @a begin and task stack area size @a size in bytes. The
* area boundaries have to be aligned properly.
*/
void bsp_stack_initialize(void *begin, uintptr_t size);
/**
* @brief Task stack allocator for @ref CONFIGURE_TASK_STACK_ALLOCATOR.
*
* In case the designated task stack space from bsp_stack_initialize() is
* completely in use the work space will be used to allocate the stack.
*/
void *bsp_stack_allocate(size_t size);
/**
* @brief Task stack free function for @ref CONFIGURE_TASK_STACK_DEALLOCATOR.
*/
void bsp_stack_free(void *stack); void bsp_stack_free(void *stack);
/**
* @brief Task stack allocator configuration option.
*/
#define CONFIGURE_TASK_STACK_ALLOCATOR bsp_stack_allocate #define CONFIGURE_TASK_STACK_ALLOCATOR bsp_stack_allocate
/**
* @brief Task stack deallocator configuration option.
*/
#define CONFIGURE_TASK_STACK_DEALLOCATOR bsp_stack_free #define CONFIGURE_TASK_STACK_DEALLOCATOR bsp_stack_free
/** @} */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@@ -3,219 +3,238 @@
* *
* @ingroup bsp_interrupt * @ingroup bsp_interrupt
* *
* @brief Source file for generic BSP interrupt support. * @brief Generic BSP interrupt support implementation.
*/ */
/* /*
* 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 * Copyright (c) 2008, 2009
* Embedded Brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be found in the file * The license and distribution terms for this file may be
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE. * found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/ */
#include <stdlib.h> /* malloc, free */ #include <stdlib.h>
#include <bsp/irq-generic.h> #include <bsp/irq-generic.h>
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table [BSP_INTERRUPT_VECTOR_NUMBER]; bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */ [BSP_INTERRUPT_VECTOR_NUMBER];
#endif
static void bsp_interrupt_handler_empty( rtems_vector_number vector, void *arg) bsp_interrupt_handler_entry bsp_interrupt_handler_table
{ [BSP_INTERRUPT_HANDLER_TABLE_SIZE];
bsp_interrupt_handler_default( vector);
}
bsp_interrupt_handler_entry bsp_interrupt_handler_table [BSP_INTERRUPT_HANDLER_TABLE_SIZE] = {
[0 ... BSP_INTERRUPT_HANDLER_TABLE_SIZE - 1] = {
.handler = bsp_interrupt_handler_empty,
.arg = NULL,
.info = NULL,
.next = NULL
}
};
/* The last entry indicates if everything is initialized */ /* The last entry indicates if everything is initialized */
static uint8_t bsp_interrupt_handler_unique_table [(BSP_INTERRUPT_HANDLER_TABLE_SIZE + 7 + 1) / 8]; static uint8_t bsp_interrupt_handler_unique_table
[(BSP_INTERRUPT_HANDLER_TABLE_SIZE + 7 + 1) / 8];
static rtems_id bsp_interrupt_mutex = RTEMS_ID_NONE; static rtems_id bsp_interrupt_mutex = RTEMS_ID_NONE;
static inline bool bsp_interrupt_is_handler_unique( rtems_vector_number index) static void bsp_interrupt_handler_empty(rtems_vector_number vector, void *arg)
{ {
rtems_vector_number i = index / 8; bsp_interrupt_handler_default(vector);
rtems_vector_number s = index % 8;
return (bsp_interrupt_handler_unique_table [i] >> s) & 0x1;
} }
static inline void bsp_interrupt_set_handler_unique( rtems_vector_number index, bool unique) static inline bool bsp_interrupt_is_handler_unique(rtems_vector_number index)
{ {
rtems_vector_number i = index / 8; rtems_vector_number i = index / 8;
rtems_vector_number s = index % 8; rtems_vector_number s = index % 8;
if (unique) { return (bsp_interrupt_handler_unique_table [i] >> s) & 0x1;
bsp_interrupt_handler_unique_table [i] |= (uint8_t) (0x1U << s); }
} else {
bsp_interrupt_handler_unique_table [i] &= (uint8_t) ~(0x1U << s); static inline void bsp_interrupt_set_handler_unique(
} rtems_vector_number index,
bool unique
)
{
rtems_vector_number i = index / 8;
rtems_vector_number s = index % 8;
if (unique) {
bsp_interrupt_handler_unique_table [i] |= (uint8_t) (0x1U << s);
} else {
bsp_interrupt_handler_unique_table [i] &= (uint8_t) ~(0x1U << s);
}
} }
static inline bool bsp_interrupt_is_initialized(void) static inline bool bsp_interrupt_is_initialized(void)
{ {
return bsp_interrupt_is_handler_unique( BSP_INTERRUPT_HANDLER_TABLE_SIZE); return bsp_interrupt_is_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE);
} }
static inline void bsp_interrupt_set_initialized(void) static inline void bsp_interrupt_set_initialized(void)
{ {
bsp_interrupt_set_handler_unique( BSP_INTERRUPT_HANDLER_TABLE_SIZE, true); bsp_interrupt_set_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE, true);
} }
static inline bool bsp_interrupt_is_empty_handler_entry( bsp_interrupt_handler_entry *e) static inline bool bsp_interrupt_is_empty_handler_entry(
bsp_interrupt_handler_entry *e
)
{ {
return e->handler == bsp_interrupt_handler_empty; return e->handler == bsp_interrupt_handler_empty;
} }
static inline void bsp_interrupt_clear_handler_entry( bsp_interrupt_handler_entry *e) static inline void bsp_interrupt_clear_handler_entry(
bsp_interrupt_handler_entry *e
)
{ {
e->handler = bsp_interrupt_handler_empty; e->handler = bsp_interrupt_handler_empty;
e->arg = NULL; e->arg = NULL;
e->info = NULL; e->info = NULL;
e->next = NULL; e->next = NULL;
} }
static inline bool bsp_interrupt_allocate_handler_index( rtems_vector_number vector, rtems_vector_number *index) static inline bool bsp_interrupt_allocate_handler_index(
rtems_vector_number vector,
rtems_vector_number *index
)
{ {
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
rtems_vector_number i = 0; rtems_vector_number i = 0;
/* The first entry will remain empty */ /* The first entry will remain empty */
for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) { for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
if (bsp_interrupt_is_empty_handler_entry( &bsp_interrupt_handler_table [i])) { const bsp_interrupt_handler_entry *e = &bsp_interrupt_handler_table [i];
*index = i; if (bsp_interrupt_is_empty_handler_entry(e)) {
return 1; *index = i;
} return true;
} }
}
return 0; return false;
#else /* BSP_INTERRUPT_USE_INDEX_TABLE */ #else
*index = vector; *index = vector;
return 1; return true;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */ #endif
} }
static bsp_interrupt_handler_entry *bsp_interrupt_allocate_handler_entry( void) static bsp_interrupt_handler_entry *bsp_interrupt_allocate_handler_entry(void)
{ {
#ifdef BSP_INTERRUPT_NO_HEAP_USAGE #ifdef BSP_INTERRUPT_NO_HEAP_USAGE
rtems_vector_number index = 0; rtems_vector_number index = 0;
if (bsp_interrupt_allocate_handler_index( 0, &index)) { if (bsp_interrupt_allocate_handler_index(0, &index)) {
return &bsp_interrupt_handler_table [index]; return &bsp_interrupt_handler_table [index];
} else { } else {
return NULL; return NULL;
} }
#else /* BSP_INTERRUPT_NO_HEAP_USAGE */ #else
return malloc( sizeof( bsp_interrupt_handler_entry)); return malloc(sizeof(bsp_interrupt_handler_entry));
#endif /* BSP_INTERRUPT_NO_HEAP_USAGE */ #endif
} }
static void bsp_interrupt_free_handler_entry( bsp_interrupt_handler_entry *e) static void bsp_interrupt_free_handler_entry(bsp_interrupt_handler_entry *e)
{ {
#ifdef BSP_INTERRUPT_NO_HEAP_USAGE #ifdef BSP_INTERRUPT_NO_HEAP_USAGE
bsp_interrupt_clear_handler_entry( e); bsp_interrupt_clear_handler_entry(e);
#else /* BSP_INTERRUPT_NO_HEAP_USAGE */ #else
free( e); free(e);
#endif /* BSP_INTERRUPT_NO_HEAP_USAGE */ #endif
} }
static rtems_status_code bsp_interrupt_lock( void) static rtems_status_code bsp_interrupt_lock(void)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
if (_System_state_Is_up( _System_state_Get())) { if (_System_state_Is_up(_System_state_Get())) {
if (bsp_interrupt_mutex == RTEMS_ID_NONE) { if (bsp_interrupt_mutex == RTEMS_ID_NONE) {
rtems_id mutex = RTEMS_ID_NONE; rtems_id mutex = RTEMS_ID_NONE;
rtems_interrupt_level level; rtems_interrupt_level level;
/* Create a mutex */ /* Create a mutex */
sc = rtems_semaphore_create ( sc = rtems_semaphore_create (
rtems_build_name( 'I', 'N', 'T', 'R'), rtems_build_name('I', 'N', 'T', 'R'),
1, 1,
RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
RTEMS_NO_PRIORITY, 0,
&mutex &mutex
); );
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
/* Assign the mutex */ /* Assign the mutex */
rtems_interrupt_disable( level); rtems_interrupt_disable(level);
if (bsp_interrupt_mutex == RTEMS_ID_NONE) { if (bsp_interrupt_mutex == RTEMS_ID_NONE) {
/* Nobody else assigned the mutex in the meantime */ /* Nobody else assigned the mutex in the meantime */
bsp_interrupt_mutex = mutex; bsp_interrupt_mutex = mutex;
rtems_interrupt_enable( level); rtems_interrupt_enable(level);
} else { } else {
/* Somebody else won */ /* Somebody else won */
rtems_interrupt_enable( level); rtems_interrupt_enable(level);
sc = rtems_semaphore_delete( mutex); sc = rtems_semaphore_delete(mutex);
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
} }
} }
return rtems_semaphore_obtain( bsp_interrupt_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); return rtems_semaphore_obtain(
} else { bsp_interrupt_mutex,
return RTEMS_SUCCESSFUL; RTEMS_WAIT,
} RTEMS_NO_TIMEOUT
);
} else {
return RTEMS_SUCCESSFUL;
}
} }
static rtems_status_code bsp_interrupt_unlock( void) static rtems_status_code bsp_interrupt_unlock(void)
{ {
if (bsp_interrupt_mutex != RTEMS_ID_NONE) { if (bsp_interrupt_mutex != RTEMS_ID_NONE) {
return rtems_semaphore_release( bsp_interrupt_mutex); return rtems_semaphore_release(bsp_interrupt_mutex);
} else { } else {
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
} }
rtems_status_code bsp_interrupt_initialize( void) rtems_status_code bsp_interrupt_initialize(void)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
size_t i = 0;
/* Lock */ sc = bsp_interrupt_lock();
sc = bsp_interrupt_lock(); if (sc != RTEMS_SUCCESSFUL) {
if (sc != RTEMS_SUCCESSFUL) { return sc;
return sc; }
}
/* Check if already initialized */ /* We need one semaphore */
if (bsp_interrupt_is_initialized()) { if (_System_state_Is_before_initialization(_System_state_Get())) {
bsp_interrupt_unlock(); Configuration.work_space_size += sizeof(Semaphore_Control);
return RTEMS_INTERNAL_ERROR; ++Configuration_RTEMS_API.maximum_semaphores;
} }
/* BSP specific initialization */ if (bsp_interrupt_is_initialized()) {
sc = bsp_interrupt_facility_initialize(); bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) { return RTEMS_INTERNAL_ERROR;
bsp_interrupt_unlock(); }
return sc;
}
/* Now we are initialized */ /* Initialize handler table */
bsp_interrupt_set_initialized(); for (i = 0; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
bsp_interrupt_handler_table [i].handler = bsp_interrupt_handler_empty;
}
/* Unlock */ sc = bsp_interrupt_facility_initialize();
sc = bsp_interrupt_unlock(); if (sc != RTEMS_SUCCESSFUL) {
if (sc != RTEMS_SUCCESSFUL) { bsp_interrupt_unlock();
return sc; return sc;
} }
return RTEMS_SUCCESSFUL; bsp_interrupt_set_initialized();
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
return RTEMS_SUCCESSFUL;
} }
/** /**
@@ -231,132 +250,141 @@ rtems_status_code bsp_interrupt_initialize( void)
* *
* @see rtems_interrupt_handler_install() * @see rtems_interrupt_handler_install()
*/ */
static rtems_status_code bsp_interrupt_handler_install( rtems_vector_number vector, const char *info, rtems_option options, rtems_interrupt_handler handler, void *arg) static rtems_status_code bsp_interrupt_handler_install(
rtems_vector_number vector,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *arg
)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_interrupt_level level; rtems_interrupt_level level;
rtems_vector_number index = 0; rtems_vector_number index = 0;
bsp_interrupt_handler_entry *head = NULL; bsp_interrupt_handler_entry *head = NULL;
bsp_interrupt_handler_entry *tail = NULL; bsp_interrupt_handler_entry *tail = NULL;
bsp_interrupt_handler_entry *current = NULL; bsp_interrupt_handler_entry *current = NULL;
bsp_interrupt_handler_entry *match = NULL; bsp_interrupt_handler_entry *match = NULL;
bool enable_vector = false; bool enable_vector = false;
/* Check parameters and system state */ /* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) { if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR; return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector( vector)) { } else if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_NUMBER; return RTEMS_INVALID_ID;
} else if (handler == NULL) { } else if (handler == NULL) {
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
} else if (rtems_interrupt_is_in_progress()) { } else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR; return RTEMS_CALLED_FROM_ISR;
} }
/* Lock */ /* Lock */
sc = bsp_interrupt_lock(); sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
/* Get handler table index */ /* Get handler table index */
index = bsp_interrupt_handler_index( vector); index = bsp_interrupt_handler_index(vector);
/* Get head entry of the handler list for current vector */ /* Get head entry of the handler list for current vector */
head = &bsp_interrupt_handler_table [index]; head = &bsp_interrupt_handler_table [index];
if (bsp_interrupt_is_empty_handler_entry( head)) { if (bsp_interrupt_is_empty_handler_entry(head)) {
/* /*
* No real handler installed yet. So allocate a new index in * No real handler installed yet. So allocate a new index in
* the handler table and fill the entry with life. * the handler table and fill the entry with life.
*/ */
if (bsp_interrupt_allocate_handler_index( vector, &index)) { if (bsp_interrupt_allocate_handler_index(vector, &index)) {
rtems_interrupt_disable( level); rtems_interrupt_disable(level);
bsp_interrupt_handler_table [index].handler = handler; bsp_interrupt_handler_table [index].handler = handler;
bsp_interrupt_handler_table [index].arg = arg; bsp_interrupt_handler_table [index].arg = arg;
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_table [vector] = index; bsp_interrupt_handler_index_table [vector] = index;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */ #endif
rtems_interrupt_enable( level); rtems_interrupt_enable(level);
bsp_interrupt_handler_table [index].info = info; bsp_interrupt_handler_table [index].info = info;
} else { } else {
/* Handler table is full */ /* Handler table is full */
bsp_interrupt_unlock(); bsp_interrupt_unlock();
return RTEMS_NO_MEMORY; return RTEMS_NO_MEMORY;
} }
/* This is the first handler so enable the vector later */ /* This is the first handler so enable the vector later */
enable_vector = true; enable_vector = true;
} else { } else {
/* Ensure that a unique handler remains unique */ /* Ensure that a unique handler remains unique */
if (RTEMS_INTERRUPT_IS_UNIQUE( options) || bsp_interrupt_is_handler_unique( index)) { if (
/* RTEMS_INTERRUPT_IS_UNIQUE(options)
* Tried to install a unique handler on a not empty || bsp_interrupt_is_handler_unique(index)
* list or there is already a unique handler installed. ) {
*/ /*
bsp_interrupt_unlock(); * Tried to install a unique handler on a not empty
return RTEMS_RESOURCE_IN_USE; * list or there is already a unique handler installed.
} */
bsp_interrupt_unlock();
return RTEMS_RESOURCE_IN_USE;
}
/* /*
* Search for the list tail and check if the handler is already * Search for the list tail and check if the handler is already
* installed. * installed.
*/ */
current = head; current = head;
do { do {
if (current->handler == handler && current->arg == arg) { if (current->handler == handler && current->arg == arg) {
match = current; match = current;
} }
tail = current; tail = current;
current = current->next; current = current->next;
} while (current != NULL); } while (current != NULL);
/* Ensure the handler is not already installed */ /* Ensure the handler is not already installed */
if (match != NULL) { if (match != NULL) {
/* The handler is already installed */ /* The handler is already installed */
bsp_interrupt_unlock(); bsp_interrupt_unlock();
return RTEMS_TOO_MANY; return RTEMS_TOO_MANY;
} }
/* Allocate a new entry */ /* Allocate a new entry */
current = bsp_interrupt_allocate_handler_entry(); current = bsp_interrupt_allocate_handler_entry();
if (current == NULL) { if (current == NULL) {
/* Not enough memory */ /* Not enough memory */
bsp_interrupt_unlock(); bsp_interrupt_unlock();
return RTEMS_NO_MEMORY; return RTEMS_NO_MEMORY;
} }
/* Set entry */ /* Set entry */
current->handler = handler; current->handler = handler;
current->arg = arg; current->arg = arg;
current->info = info; current->info = info;
current->next = NULL; current->next = NULL;
/* Link to list tail */ /* Link to list tail */
rtems_interrupt_disable( level); rtems_interrupt_disable(level);
tail->next = current; tail->next = current;
rtems_interrupt_enable( level); rtems_interrupt_enable(level);
} }
/* Make the handler unique if necessary */ /* Make the handler unique if necessary */
bsp_interrupt_set_handler_unique( index, RTEMS_INTERRUPT_IS_UNIQUE( options)); bsp_interrupt_set_handler_unique(index, RTEMS_INTERRUPT_IS_UNIQUE(options));
/* Enable the vector if necessary */ /* Enable the vector if necessary */
if (enable_vector) { if (enable_vector) {
sc = bsp_interrupt_vector_enable( vector); sc = bsp_interrupt_vector_enable(vector);
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock(); bsp_interrupt_unlock();
return sc; return sc;
} }
} }
/* Unlock */ /* Unlock */
sc = bsp_interrupt_unlock(); sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
/** /**
@@ -369,116 +397,120 @@ static rtems_status_code bsp_interrupt_handler_install( rtems_vector_number vect
* *
* @see rtems_interrupt_handler_remove(). * @see rtems_interrupt_handler_remove().
*/ */
static rtems_status_code bsp_interrupt_handler_remove( rtems_vector_number vector, rtems_interrupt_handler handler, void *arg) static rtems_status_code bsp_interrupt_handler_remove(
rtems_vector_number vector,
rtems_interrupt_handler handler,
void *arg
)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_interrupt_level level; rtems_interrupt_level level;
rtems_vector_number index = 0; rtems_vector_number index = 0;
bsp_interrupt_handler_entry *head = NULL; bsp_interrupt_handler_entry *head = NULL;
bsp_interrupt_handler_entry *current = NULL; bsp_interrupt_handler_entry *current = NULL;
bsp_interrupt_handler_entry *previous = NULL; bsp_interrupt_handler_entry *previous = NULL;
bsp_interrupt_handler_entry *match = NULL; bsp_interrupt_handler_entry *match = NULL;
/* Check parameters and system state */ /* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) { if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR; return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector( vector)) { } else if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_NUMBER; return RTEMS_INVALID_ID;
} else if (handler == NULL) { } else if (handler == NULL) {
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
} else if (rtems_interrupt_is_in_progress()) { } else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR; return RTEMS_CALLED_FROM_ISR;
} }
/* Lock */ /* Lock */
sc = bsp_interrupt_lock(); sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
/* Get handler table index */ /* Get handler table index */
index = bsp_interrupt_handler_index( vector); index = bsp_interrupt_handler_index(vector);
/* Get head entry of the handler list for current vector */ /* Get head entry of the handler list for current vector */
head = &bsp_interrupt_handler_table [index]; head = &bsp_interrupt_handler_table [index];
/* Search for a matching entry */ /* Search for a matching entry */
current = head; current = head;
do { do {
if (current->handler == handler && current->arg == arg) { if (current->handler == handler && current->arg == arg) {
match = current; match = current;
break; break;
} }
previous = current; previous = current;
current = current->next; current = current->next;
} while (current != NULL); } while (current != NULL);
/* Remove the matching entry */ /* Remove the matching entry */
if (match != NULL) { if (match != NULL) {
if (match->next != NULL) { if (match->next != NULL) {
/* /*
* The match has a successor. A successor is always * The match has a successor. A successor is always
* allocated. So replace the match with its successor * allocated. So replace the match with its successor
* and free the successor entry. * and free the successor entry.
*/ */
current = match->next; current = match->next;
rtems_interrupt_disable( level); rtems_interrupt_disable(level);
*match = *current; *match = *current;
rtems_interrupt_enable( level); rtems_interrupt_enable(level);
bsp_interrupt_free_handler_entry( current); bsp_interrupt_free_handler_entry(current);
} else if (match == head) { } else if (match == head) {
/* /*
* The match is the list head and has no successor. * The match is the list head and has no successor.
* The list head is stored in a static table so clear * The list head is stored in a static table so clear
* this entry. Since now the list is empty disable the * this entry. Since now the list is empty disable the
* vector. * vector.
*/ */
/* Disable the vector */ /* Disable the vector */
sc = bsp_interrupt_vector_disable( vector); sc = bsp_interrupt_vector_disable(vector);
/* Clear entry */ /* Clear entry */
rtems_interrupt_disable( level); rtems_interrupt_disable(level);
bsp_interrupt_clear_handler_entry( head); bsp_interrupt_clear_handler_entry(head);
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_table [vector] = 0; bsp_interrupt_handler_index_table [vector] = 0;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */ #endif
rtems_interrupt_enable( level); rtems_interrupt_enable(level);
/* Allow shared handlers */ /* Allow shared handlers */
bsp_interrupt_set_handler_unique( index, false); bsp_interrupt_set_handler_unique(index, false);
/* Check status code */ /* Check status code */
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock(); bsp_interrupt_unlock();
return sc; return sc;
} }
} else { } else {
/* /*
* The match is the list tail and has a predecessor. * The match is the list tail and has a predecessor.
* So terminate the predecessor and free the match. * So terminate the predecessor and free the match.
*/ */
rtems_interrupt_disable( level); rtems_interrupt_disable(level);
previous->next = NULL; previous->next = NULL;
rtems_interrupt_enable( level); rtems_interrupt_enable(level);
bsp_interrupt_free_handler_entry( match); bsp_interrupt_free_handler_entry(match);
} }
} else { } else {
/* No matching entry found */ /* No matching entry found */
bsp_interrupt_unlock(); bsp_interrupt_unlock();
return RTEMS_UNSATISFIED; return RTEMS_UNSATISFIED;
} }
/* Unlock */ /* Unlock */
sc = bsp_interrupt_unlock(); sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
/** /**
@@ -491,59 +523,78 @@ static rtems_status_code bsp_interrupt_handler_remove( rtems_vector_number vecto
* *
* @see rtems_interrupt_handler_iterate(). * @see rtems_interrupt_handler_iterate().
*/ */
static rtems_status_code bsp_interrupt_handler_iterate( rtems_vector_number vector, rtems_interrupt_per_handler_routine routine, void *arg) static rtems_status_code bsp_interrupt_handler_iterate(
rtems_vector_number vector,
rtems_interrupt_per_handler_routine routine,
void *arg
)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
bsp_interrupt_handler_entry *current = NULL; bsp_interrupt_handler_entry *current = NULL;
rtems_option options = 0; rtems_option options = 0;
rtems_vector_number index = 0; rtems_vector_number index = 0;
/* Check parameters and system state */ /* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) { if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR; return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector( vector)) { } else if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_NUMBER; return RTEMS_INVALID_ID;
} else if (rtems_interrupt_is_in_progress()) { } else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR; return RTEMS_CALLED_FROM_ISR;
} }
/* Lock */ /* Lock */
sc = bsp_interrupt_lock(); sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
/* Interate */ /* Interate */
index = bsp_interrupt_handler_index( vector); index = bsp_interrupt_handler_index(vector);
current = &bsp_interrupt_handler_table [index]; current = &bsp_interrupt_handler_table [index];
if (!bsp_interrupt_is_empty_handler_entry( current)) { if (!bsp_interrupt_is_empty_handler_entry(current)) {
do { do {
options = bsp_interrupt_is_handler_unique( index) ? RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED; options = bsp_interrupt_is_handler_unique(index) ?
routine( arg, current->info, options, current->handler, current->arg); RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
current = current->next; routine(arg, current->info, options, current->handler, current->arg);
} while (current != NULL); current = current->next;
} } while (current != NULL);
}
/* Unlock */ /* Unlock */
sc = bsp_interrupt_unlock(); sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
return sc; return sc;
} }
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
rtems_status_code rtems_interrupt_handler_install( rtems_vector_number vector, const char *info, rtems_option options, rtems_interrupt_handler handler, void *arg) rtems_status_code rtems_interrupt_handler_install(
rtems_vector_number vector,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *arg
)
{ {
return bsp_interrupt_handler_install( vector, info, options, handler, arg); return bsp_interrupt_handler_install(vector, info, options, handler, arg);
} }
rtems_status_code rtems_interrupt_handler_remove( rtems_vector_number vector, rtems_interrupt_handler handler, void *arg) rtems_status_code rtems_interrupt_handler_remove(
rtems_vector_number vector,
rtems_interrupt_handler handler,
void *arg
)
{ {
return bsp_interrupt_handler_remove( vector, handler, arg); return bsp_interrupt_handler_remove(vector, handler, arg);
} }
rtems_status_code rtems_interrupt_handler_iterate( rtems_vector_number vector, rtems_interrupt_per_handler_routine routine, void *arg) rtems_status_code rtems_interrupt_handler_iterate(
rtems_vector_number vector,
rtems_interrupt_per_handler_routine routine,
void *arg
)
{ {
return bsp_interrupt_handler_iterate( vector, routine, arg); return bsp_interrupt_handler_iterate(vector, routine, arg);
} }

View File

@@ -3,19 +3,20 @@
* *
* @ingroup bsp_interrupt * @ingroup bsp_interrupt
* *
* @brief Source file for generic BSP interrupt information code. * @brief Generic BSP interrupt information implementation.
*/ */
/* /*
* Copyright (c) 2008 * Copyright (c) 2008, 2009
* Embedded Brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be found in the file * The license and distribution terms for this file may be
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE. * found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/ */
#include <inttypes.h> #include <inttypes.h>
@@ -27,62 +28,70 @@
#include <bsp/irq-config.h> #include <bsp/irq-config.h>
typedef struct { typedef struct {
void *context; void *context;
rtems_printk_plugin_t print; rtems_printk_plugin_t print;
rtems_vector_number vector; rtems_vector_number vector;
} bsp_interrupt_report_entry; } bsp_interrupt_report_entry;
static void bsp_interrupt_report_per_handler_routine( static void bsp_interrupt_report_per_handler_routine(
void *arg, void *arg,
const char *info, const char *info,
rtems_option options, rtems_option options,
rtems_interrupt_handler handler, rtems_interrupt_handler handler,
void *handler_arg void *handler_arg
) )
{ {
bsp_interrupt_report_entry *e = (bsp_interrupt_report_entry *) arg; bsp_interrupt_report_entry *e = (bsp_interrupt_report_entry *) arg;
const char *opt = options == RTEMS_INTERRUPT_UNIQUE ? "UNIQUE" : "SHARED"; const char *opt = options == RTEMS_INTERRUPT_UNIQUE ? "UNIQUE" : "SHARED";
e->print( e->context, "%7" PRIu32 " | %-32s | %7s | %010p | %010p\n", e->vector, info, opt, handler, handler_arg); e->print(
e->context,
"%7" PRIu32 " | %-32s | %7s | %010p | %010p\n",
e->vector,
info,
opt,
handler,
handler_arg
);
} }
/** void bsp_interrupt_report_with_plugin(
* @brief Prints interrupt information via the printk plugin @a print with the void *context,
* context @a context. rtems_printk_plugin_t print
*/ )
void bsp_interrupt_report_with_plugin( void *context, rtems_printk_plugin_t print)
{ {
rtems_vector_number v = 0; rtems_vector_number v = 0;
bsp_interrupt_report_entry e = { bsp_interrupt_report_entry e = {
.context = context, .context = context,
.print = print, .print = print,
.vector = 0 .vector = 0
}; };
print( print(
context, context,
"-------------------------------------------------------------------------------\n" "-------------------------------------------------------------------------------\n"
" INTERRUPT INFORMATION\n" " INTERRUPT INFORMATION\n"
"--------+----------------------------------+---------+------------+------------\n" "--------+----------------------------------+---------+------------+------------\n"
" VECTOR | INFO | OPTIONS | HANDLER | ARGUMENT \n" " VECTOR | INFO | OPTIONS | HANDLER | ARGUMENT \n"
"--------+----------------------------------+---------+------------+------------\n" "--------+----------------------------------+---------+------------+------------\n"
); );
for (v = BSP_INTERRUPT_VECTOR_MIN; v <= BSP_INTERRUPT_VECTOR_MAX; ++v) { for (v = BSP_INTERRUPT_VECTOR_MIN; v <= BSP_INTERRUPT_VECTOR_MAX; ++v) {
e.vector = v; e.vector = v;
(void) rtems_interrupt_handler_iterate( v, bsp_interrupt_report_per_handler_routine, &e); rtems_interrupt_handler_iterate(
} v,
bsp_interrupt_report_per_handler_routine,
&e
);
}
print( print(
context, context,
"--------+----------------------------------+---------+------------+------------\n" "--------+----------------------------------+---------+------------+------------\n"
); );
} }
/** void bsp_interrupt_report(void)
* @brief Prints interrupt information via the default printk plugin.
*/
void bsp_interrupt_report( void)
{ {
bsp_interrupt_report_with_plugin( NULL, printk_plugin); bsp_interrupt_report_with_plugin(NULL, printk_plugin);
} }

View File

@@ -3,26 +3,27 @@
* *
* @ingroup bsp_interrupt * @ingroup bsp_interrupt
* *
* @brief Source file for generic BSP interrupt support legacy code. * @brief Generic BSP interrupt support legacy implementation.
*/ */
/* /*
* Copyright (c) 2008 * Copyright (c) 2008, 2009
* Embedded Brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
* *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#define BSP_SHARED_HANDLER_SUPPORT
#include <rtems/irq.h> #include <rtems/irq.h>
#include <bsp/irq-generic.h> #include <bsp/irq-generic.h>
@@ -84,7 +85,7 @@ int BSP_get_current_rtems_irq_handler(rtems_irq_connect_data *cd)
int BSP_install_rtems_irq_handler(const rtems_irq_connect_data *cd) int BSP_install_rtems_irq_handler(const rtems_irq_connect_data *cd)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
bsp_interrupt_legacy_entry *e = malloc(sizeof( bsp_interrupt_legacy_entry)); bsp_interrupt_legacy_entry *e = malloc(sizeof(bsp_interrupt_legacy_entry));
if (e == NULL) { if (e == NULL) {
return 0; return 0;
@@ -95,8 +96,7 @@ int BSP_install_rtems_irq_handler(const rtems_irq_connect_data *cd)
sc = rtems_interrupt_handler_install( sc = rtems_interrupt_handler_install(
cd->name, cd->name,
"Unique interrupt handler " "LEGACY INSTALLED",
"(installed with obsolete BSP_install_rtems_irq_handler())",
RTEMS_INTERRUPT_UNIQUE, RTEMS_INTERRUPT_UNIQUE,
bsp_interrupt_legacy_dispatch, bsp_interrupt_legacy_dispatch,
e e
@@ -119,7 +119,7 @@ int BSP_install_rtems_irq_handler(const rtems_irq_connect_data *cd)
int BSP_install_rtems_shared_irq_handler(const rtems_irq_connect_data *cd) int BSP_install_rtems_shared_irq_handler(const rtems_irq_connect_data *cd)
{ {
rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_status_code sc = RTEMS_SUCCESSFUL;
bsp_interrupt_legacy_entry *e = malloc(sizeof( bsp_interrupt_legacy_entry)); bsp_interrupt_legacy_entry *e = malloc(sizeof(bsp_interrupt_legacy_entry));
if (e == NULL) { if (e == NULL) {
return 0; return 0;
@@ -130,8 +130,7 @@ int BSP_install_rtems_shared_irq_handler(const rtems_irq_connect_data *cd)
sc = rtems_interrupt_handler_install( sc = rtems_interrupt_handler_install(
cd->name, cd->name,
"Shared interrupt handler " "LEGACY INSTALLED",
"(installed with obsolete BSP_install_rtems_shared_irq_handler())",
RTEMS_INTERRUPT_SHARED, RTEMS_INTERRUPT_SHARED,
bsp_interrupt_legacy_dispatch, bsp_interrupt_legacy_dispatch,
e e

View File

@@ -0,0 +1,275 @@
/**
* @file
*
* @ingroup bsp_interrupt
*
* @brief Generic BSP interrupt server implementation.
*/
/*
* Copyright (c) 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*/
#include <stdlib.h>
#include <bsp/irq-generic.h>
typedef struct bsp_interrupt_server_entry {
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;
/* LIFO list head */
static bsp_interrupt_server_entry *volatile
bsp_interrupt_server_list_head = NULL;
static rtems_status_code bsp_interrupt_server_is_initialized(void)
{
if (bsp_interrupt_server_semaphore != RTEMS_ID_NONE) {
return RTEMS_SUCCESSFUL;
} else {
return RTEMS_INCORRECT_STATE;
}
}
static void bsp_interrupt_server_trigger(rtems_vector_number vector, 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 */
rtems_interrupt_disable(level);
e->next = bsp_interrupt_server_list_head;
bsp_interrupt_server_list_head = e;
rtems_interrupt_enable(level);
rtems_semaphore_release(bsp_interrupt_server_semaphore);
}
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);
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);
(*e->handler)(e->vector, e->arg);
bsp_interrupt_vector_enable(e->vector);
}
rtems_task_delete(RTEMS_SELF);
}
typedef struct {
rtems_interrupt_handler handler;
void *arg;
bsp_interrupt_server_entry *entry;
} bsp_interrupt_server_iterate_entry;
static void bsp_interrupt_server_per_handler_routine(
void *iterate_arg,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *handler_arg
)
{
bsp_interrupt_server_iterate_entry *ie = iterate_arg;
bsp_interrupt_server_entry *e = handler_arg;
if (handler == bsp_interrupt_server_trigger) {
if (e->handler == ie->handler && e->arg == ie->arg) {
ie->entry = e;
}
}
}
rtems_status_code rtems_interrupt_server_handler_install(
rtems_id server,
rtems_vector_number vector,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *arg
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
bsp_interrupt_server_entry *e = NULL;
sc = bsp_interrupt_server_is_initialized();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
if (RTEMS_INTERRUPT_IS_SHARED(options)) {
return RTEMS_NOT_IMPLEMENTED;
}
e = malloc(sizeof(bsp_interrupt_server_entry));
if (e == NULL) {
return RTEMS_NO_MEMORY;
}
e->vector = vector;
e->handler = handler;
e->arg = arg;
sc = rtems_interrupt_handler_install(
vector,
info,
options,
bsp_interrupt_server_trigger,
e
);
if (sc != RTEMS_SUCCESSFUL) {
free(e);
return sc;
}
return RTEMS_SUCCESSFUL;
}
rtems_status_code rtems_interrupt_server_handler_remove(
rtems_id server,
rtems_vector_number vector,
rtems_interrupt_handler handler,
void *arg
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
bsp_interrupt_server_iterate_entry ie = {
.handler = handler,
.arg = arg,
.entry = NULL
};
sc = bsp_interrupt_server_is_initialized();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Query corresponding interrupt server entry */
sc = rtems_interrupt_handler_iterate(
vector,
bsp_interrupt_server_per_handler_routine,
&ie
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
} else if (ie.entry == NULL) {
return RTEMS_INVALID_ID;
}
sc = rtems_interrupt_handler_remove(
vector,
ie.entry->handler,
ie.entry->arg
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
free(ie.entry);
return RTEMS_SUCCESSFUL;
}
rtems_status_code rtems_interrupt_server_initialize(
rtems_task_priority priority,
size_t stack_size,
rtems_mode modes,
rtems_attribute attributes,
rtems_id *server
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_id sema_id = RTEMS_ID_NONE;
rtems_id task_id = RTEMS_ID_NONE;
rtems_interrupt_level level;
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
);
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;
}
sc = rtems_task_start(
task_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);
return sc;
}
return RTEMS_SUCCESSFUL;
}

View File

@@ -3,20 +3,20 @@
* *
* @ingroup bsp_interrupt * @ingroup bsp_interrupt
* *
* @brief Source file for generic BSP interrupt shell code. * @brief Generic BSP interrupt shell implementation.
*/ */
/* /*
* Copyright (c) 2008 * Copyright (c) 2009
* Embedded Brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * D-82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE. * http://www.rtems.com/license/LICENSE.
*/ */
#include <stdio.h> #include <stdio.h>
@@ -25,16 +25,13 @@
#include <bsp/irq-info.h> #include <bsp/irq-info.h>
static int bsp_interrupt_shell_main( int argc, char **argv) static int bsp_interrupt_shell_main(int argc, char **argv)
{ {
bsp_interrupt_report_with_plugin( stdout, (rtems_printk_plugin_t) fprintf); bsp_interrupt_report_with_plugin(stdout, (rtems_printk_plugin_t) fprintf);
return 0; return 0;
} }
/**
* @brief Shell command entry for interrupt information.
*/
struct rtems_shell_cmd_tt bsp_interrupt_shell_command = { struct rtems_shell_cmd_tt bsp_interrupt_shell_command = {
.name = "irq", .name = "irq",
.usage = "Prints interrupt information", .usage = "Prints interrupt information",

View File

@@ -30,21 +30,21 @@ static Heap_Control bsp_stack_heap = {
.page_size = BSP_STACK_MAGIC .page_size = BSP_STACK_MAGIC
}; };
void bsp_stack_initialize(void *start, intptr_t size) void bsp_stack_initialize(void *begin, uintptr_t size)
{ {
bsp_stack_heap.begin = start; bsp_stack_heap.area_begin = (uintptr_t) begin;
bsp_stack_heap.end = (void *) size; bsp_stack_heap.area_end = size;
} }
void *bsp_stack_allocate(uint32_t size) void *bsp_stack_allocate(size_t size)
{ {
void *stack = NULL; void *stack = NULL;
if (bsp_stack_heap.page_size == BSP_STACK_MAGIC) { if (bsp_stack_heap.page_size == BSP_STACK_MAGIC) {
uint32_t rv = _Heap_Initialize( uintptr_t rv = _Heap_Initialize(
&bsp_stack_heap, &bsp_stack_heap,
bsp_stack_heap.begin, (void *) bsp_stack_heap.area_begin,
(intptr_t) bsp_stack_heap.end, bsp_stack_heap.area_end,
CPU_STACK_ALIGNMENT CPU_STACK_ALIGNMENT
); );
if (rv == 0) { if (rv == 0) {
@@ -52,7 +52,7 @@ void *bsp_stack_allocate(uint32_t size)
} }
} }
stack = _Heap_Allocate(&bsp_stack_heap, (intptr_t) size); stack = _Heap_Allocate(&bsp_stack_heap, size);
if (stack == NULL) { if (stack == NULL) {
stack = _Workspace_Allocate(size); stack = _Workspace_Allocate(size);