* 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>
* bootcard.c, bsplibc.c, clockdrv_shell.h, console-polled.c: Fix

View File

@@ -12,12 +12,12 @@
#include <bsp/bootcard.h>
void bsp_libc_init(
void *heap_start,
size_t heap_size,
size_t sbrk_amount
void *heap_begin,
uintptr_t heap_size,
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

View File

@@ -1,9 +1,9 @@
/**
* @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
@@ -37,6 +49,11 @@
extern "C" {
#endif /* __cplusplus */
/**
* @brief Global pointer to the command line of boot_card().
*/
extern const char *bsp_boot_cmdline;
void bsp_start(void);
void bsp_pretasking_hook(void);
@@ -49,20 +66,72 @@ void bsp_cleanup(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
/**
* @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
void bsp_get_work_area(
void **work_area_start,
void **work_area_begin,
uintptr_t *work_area_size,
void **heap_start,
void **heap_begin,
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
}

View File

@@ -9,15 +9,16 @@
/*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008, 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 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.
*/
#ifndef LIBBSP_SHARED_IRQ_CONFIG_H
@@ -60,18 +61,16 @@
#undef BSP_INTERRUPT_NO_HEAP_USAGE
#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.
*/
#define BSP_INTERRUPT_HANDLER_TABLE_SIZE 0
/**
* @brief Integer type capable to index the complete handler table.
*/
typedef uint8_t bsp_interrupt_handler_index_type;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
/**
* @brief Integer type capable to index the complete handler table.
*/
typedef uint8_t bsp_interrupt_handler_index_type;
#endif
/** @} */

View File

@@ -3,21 +3,22 @@
*
* @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.
*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008, 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 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.
*/
#ifndef LIBBSP_SHARED_IRQ_GENERIC_H
@@ -33,29 +34,30 @@
extern "C" {
#endif /* __cplusplus */
#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.
#endif /* !defined( 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"
#endif
#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.
#endif /* defined( BSP_INTERRUPT_USE_INDEX_TABLE) ... */
#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"
#endif
#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.
#endif /* defined( BSP_INTERRUPT_NO_HEAP_USAGE) ... */
#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"
#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
#define BSP_INTERRUPT_HANDLER_TABLE_SIZE BSP_INTERRUPT_VECTOR_NUMBER
#endif /* BSP_INTERRUPT_HANDLER_TABLE_SIZE */
#define BSP_INTERRUPT_HANDLER_TABLE_SIZE BSP_INTERRUPT_VECTOR_NUMBER
#endif
struct bsp_interrupt_handler_entry {
rtems_interrupt_handler handler;
void *arg;
const char *info;
struct bsp_interrupt_handler_entry *next;
rtems_interrupt_handler handler;
void *arg;
const char *info;
struct bsp_interrupt_handler_entry *next;
};
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 [];
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
extern bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table [];
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
extern bsp_interrupt_handler_index_type bsp_interrupt_handler_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
return bsp_interrupt_handler_index_table [vector - BSP_INTERRUPT_VECTOR_MIN];
#else /* BSP_INTERRUPT_USE_INDEX_TABLE */
return vector - BSP_INTERRUPT_VECTOR_MIN;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
return bsp_interrupt_handler_index_table [vector - BSP_INTERRUPT_VECTOR_MIN];
#else
return vector - BSP_INTERRUPT_VECTOR_MIN;
#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.
*/
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
&& vector <= (rtems_vector_number) BSP_INTERRUPT_VECTOR_MAX;
return (rtems_vector_number) BSP_INTERRUPT_VECTOR_MIN <= vector
&& 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.
*/
void bsp_interrupt_handler_default( rtems_vector_number vector);
void bsp_interrupt_handler_default(rtems_vector_number vector);
/**
* @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
* is complete if everything was successful.
*/
rtems_status_code bsp_interrupt_initialize( void);
rtems_status_code bsp_interrupt_initialize(void);
/**
* @brief BSP specific initialization.
@@ -171,7 +175,7 @@ rtems_status_code bsp_interrupt_initialize( void);
*
* @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.
@@ -187,7 +191,7 @@ rtems_status_code bsp_interrupt_facility_initialize( void);
*
* @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.
@@ -203,7 +207,7 @@ rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector);
*
* @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
@@ -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
* 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)) {
bsp_interrupt_handler_entry *e = &bsp_interrupt_handler_table [bsp_interrupt_handler_index( vector)];
if (bsp_interrupt_is_valid_vector(vector)) {
bsp_interrupt_handler_entry *e =
&bsp_interrupt_handler_table [bsp_interrupt_handler_index(vector)];
do {
e->handler( vector, e->arg);
e = e->next;
} while (e != NULL);
} else {
bsp_interrupt_handler_default( vector);
}
do {
(*e->handler)(vector, e->arg);
e = e->next;
} while (e != NULL);
} else {
bsp_interrupt_handler_default(vector);
}
}
/** @} */

View File

@@ -3,19 +3,20 @@
*
* @ingroup bsp_interrupt
*
* @brief Header file for generic BSP interrupt information.
* @brief Generic BSP interrupt information API.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008, 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 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.
*/
#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;
/** @} */

View File

@@ -1,9 +1,9 @@
/**
* @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
#define LIBBSP_SHARED_STACK_ALLOC_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#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);
/**
* @brief Task stack allocator configuration option.
*/
#define CONFIGURE_TASK_STACK_ALLOCATOR bsp_stack_allocate
/**
* @brief Task stack deallocator configuration option.
*/
#define CONFIGURE_TASK_STACK_DEALLOCATOR bsp_stack_free
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -3,219 +3,238 @@
*
* @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.
*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008, 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 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 <stdlib.h> /* malloc, free */
#include <stdlib.h>
#include <bsp/irq-generic.h>
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table [BSP_INTERRUPT_VECTOR_NUMBER];
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table
[BSP_INTERRUPT_VECTOR_NUMBER];
#endif
static void bsp_interrupt_handler_empty( rtems_vector_number vector, void *arg)
{
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
}
};
bsp_interrupt_handler_entry bsp_interrupt_handler_table
[BSP_INTERRUPT_HANDLER_TABLE_SIZE];
/* 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 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;
rtems_vector_number s = index % 8;
return (bsp_interrupt_handler_unique_table [i] >> s) & 0x1;
bsp_interrupt_handler_default(vector);
}
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 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);
}
rtems_vector_number i = index / 8;
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
)
{
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)
{
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)
{
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->arg = NULL;
e->info = NULL;
e->next = NULL;
e->handler = bsp_interrupt_handler_empty;
e->arg = NULL;
e->info = 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
rtems_vector_number i = 0;
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
rtems_vector_number i = 0;
/* The first entry will remain empty */
for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
if (bsp_interrupt_is_empty_handler_entry( &bsp_interrupt_handler_table [i])) {
*index = i;
return 1;
}
}
/* The first entry will remain empty */
for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
const bsp_interrupt_handler_entry *e = &bsp_interrupt_handler_table [i];
if (bsp_interrupt_is_empty_handler_entry(e)) {
*index = i;
return true;
}
}
return 0;
#else /* BSP_INTERRUPT_USE_INDEX_TABLE */
*index = vector;
return 1;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
return false;
#else
*index = vector;
return true;
#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
rtems_vector_number index = 0;
if (bsp_interrupt_allocate_handler_index( 0, &index)) {
return &bsp_interrupt_handler_table [index];
} else {
return NULL;
}
#else /* BSP_INTERRUPT_NO_HEAP_USAGE */
return malloc( sizeof( bsp_interrupt_handler_entry));
#endif /* BSP_INTERRUPT_NO_HEAP_USAGE */
#ifdef BSP_INTERRUPT_NO_HEAP_USAGE
rtems_vector_number index = 0;
if (bsp_interrupt_allocate_handler_index(0, &index)) {
return &bsp_interrupt_handler_table [index];
} else {
return NULL;
}
#else
return malloc(sizeof(bsp_interrupt_handler_entry));
#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
bsp_interrupt_clear_handler_entry( e);
#else /* BSP_INTERRUPT_NO_HEAP_USAGE */
free( e);
#endif /* BSP_INTERRUPT_NO_HEAP_USAGE */
#ifdef BSP_INTERRUPT_NO_HEAP_USAGE
bsp_interrupt_clear_handler_entry(e);
#else
free(e);
#endif
}
static rtems_status_code bsp_interrupt_lock( void)
static rtems_status_code bsp_interrupt_lock(void)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
if (_System_state_Is_up( _System_state_Get())) {
if (bsp_interrupt_mutex == RTEMS_ID_NONE) {
rtems_id mutex = RTEMS_ID_NONE;
rtems_interrupt_level level;
rtems_status_code sc = RTEMS_SUCCESSFUL;
if (_System_state_Is_up(_System_state_Get())) {
if (bsp_interrupt_mutex == RTEMS_ID_NONE) {
rtems_id mutex = RTEMS_ID_NONE;
rtems_interrupt_level level;
/* Create a mutex */
sc = rtems_semaphore_create (
rtems_build_name( 'I', 'N', 'T', 'R'),
1,
RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY,
RTEMS_NO_PRIORITY,
&mutex
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Create a mutex */
sc = rtems_semaphore_create (
rtems_build_name('I', 'N', 'T', 'R'),
1,
RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
0,
&mutex
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Assign the mutex */
rtems_interrupt_disable( level);
if (bsp_interrupt_mutex == RTEMS_ID_NONE) {
/* Nobody else assigned the mutex in the meantime */
/* Assign the mutex */
rtems_interrupt_disable(level);
if (bsp_interrupt_mutex == RTEMS_ID_NONE) {
/* Nobody else assigned the mutex in the meantime */
bsp_interrupt_mutex = mutex;
rtems_interrupt_enable( level);
} else {
/* Somebody else won */
bsp_interrupt_mutex = mutex;
rtems_interrupt_enable(level);
} else {
/* Somebody else won */
rtems_interrupt_enable( level);
sc = rtems_semaphore_delete( mutex);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
}
}
return rtems_semaphore_obtain( bsp_interrupt_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
} else {
return RTEMS_SUCCESSFUL;
}
rtems_interrupt_enable(level);
sc = rtems_semaphore_delete(mutex);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
}
}
return rtems_semaphore_obtain(
bsp_interrupt_mutex,
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) {
return rtems_semaphore_release( bsp_interrupt_mutex);
} else {
return RTEMS_SUCCESSFUL;
}
if (bsp_interrupt_mutex != RTEMS_ID_NONE) {
return rtems_semaphore_release(bsp_interrupt_mutex);
} else {
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();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Check if already initialized */
if (bsp_interrupt_is_initialized()) {
bsp_interrupt_unlock();
return RTEMS_INTERNAL_ERROR;
}
/* We need one semaphore */
if (_System_state_Is_before_initialization(_System_state_Get())) {
Configuration.work_space_size += sizeof(Semaphore_Control);
++Configuration_RTEMS_API.maximum_semaphores;
}
/* BSP specific initialization */
sc = bsp_interrupt_facility_initialize();
if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock();
return sc;
}
if (bsp_interrupt_is_initialized()) {
bsp_interrupt_unlock();
return RTEMS_INTERNAL_ERROR;
}
/* Now we are initialized */
bsp_interrupt_set_initialized();
/* Initialize handler table */
for (i = 0; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
bsp_interrupt_handler_table [i].handler = bsp_interrupt_handler_empty;
}
/* Unlock */
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
sc = bsp_interrupt_facility_initialize();
if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock();
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()
*/
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_interrupt_level level;
rtems_vector_number index = 0;
bsp_interrupt_handler_entry *head = NULL;
bsp_interrupt_handler_entry *tail = NULL;
bsp_interrupt_handler_entry *current = NULL;
bsp_interrupt_handler_entry *match = NULL;
bool enable_vector = false;
rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_interrupt_level level;
rtems_vector_number index = 0;
bsp_interrupt_handler_entry *head = NULL;
bsp_interrupt_handler_entry *tail = NULL;
bsp_interrupt_handler_entry *current = NULL;
bsp_interrupt_handler_entry *match = NULL;
bool enable_vector = false;
/* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector( vector)) {
return RTEMS_INVALID_NUMBER;
} else if (handler == NULL) {
return RTEMS_INVALID_ADDRESS;
} else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
/* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_ID;
} else if (handler == NULL) {
return RTEMS_INVALID_ADDRESS;
} else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
/* Lock */
sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Lock */
sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Get handler table index */
index = bsp_interrupt_handler_index( vector);
/* Get handler table index */
index = bsp_interrupt_handler_index(vector);
/* Get head entry of the handler list for current vector */
head = &bsp_interrupt_handler_table [index];
/* Get head entry of the handler list for current vector */
head = &bsp_interrupt_handler_table [index];
if (bsp_interrupt_is_empty_handler_entry( head)) {
/*
* No real handler installed yet. So allocate a new index in
* the handler table and fill the entry with life.
*/
if (bsp_interrupt_allocate_handler_index( vector, &index)) {
rtems_interrupt_disable( level);
bsp_interrupt_handler_table [index].handler = handler;
bsp_interrupt_handler_table [index].arg = arg;
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_table [vector] = index;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
rtems_interrupt_enable( level);
bsp_interrupt_handler_table [index].info = info;
} else {
/* Handler table is full */
bsp_interrupt_unlock();
return RTEMS_NO_MEMORY;
}
if (bsp_interrupt_is_empty_handler_entry(head)) {
/*
* No real handler installed yet. So allocate a new index in
* the handler table and fill the entry with life.
*/
if (bsp_interrupt_allocate_handler_index(vector, &index)) {
rtems_interrupt_disable(level);
bsp_interrupt_handler_table [index].handler = handler;
bsp_interrupt_handler_table [index].arg = arg;
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_table [vector] = index;
#endif
rtems_interrupt_enable(level);
bsp_interrupt_handler_table [index].info = info;
} else {
/* Handler table is full */
bsp_interrupt_unlock();
return RTEMS_NO_MEMORY;
}
/* This is the first handler so enable the vector later */
enable_vector = true;
} else {
/* Ensure that a unique handler remains unique */
if (RTEMS_INTERRUPT_IS_UNIQUE( options) || bsp_interrupt_is_handler_unique( index)) {
/*
* Tried to install a unique handler on a not empty
* list or there is already a unique handler installed.
*/
bsp_interrupt_unlock();
return RTEMS_RESOURCE_IN_USE;
}
/* This is the first handler so enable the vector later */
enable_vector = true;
} else {
/* Ensure that a unique handler remains unique */
if (
RTEMS_INTERRUPT_IS_UNIQUE(options)
|| bsp_interrupt_is_handler_unique(index)
) {
/*
* Tried to install a unique handler on a not empty
* 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
* installed.
*/
current = head;
do {
if (current->handler == handler && current->arg == arg) {
match = current;
}
tail = current;
current = current->next;
} while (current != NULL);
/*
* Search for the list tail and check if the handler is already
* installed.
*/
current = head;
do {
if (current->handler == handler && current->arg == arg) {
match = current;
}
tail = current;
current = current->next;
} while (current != NULL);
/* Ensure the handler is not already installed */
if (match != NULL) {
/* The handler is already installed */
bsp_interrupt_unlock();
return RTEMS_TOO_MANY;
}
/* Ensure the handler is not already installed */
if (match != NULL) {
/* The handler is already installed */
bsp_interrupt_unlock();
return RTEMS_TOO_MANY;
}
/* Allocate a new entry */
current = bsp_interrupt_allocate_handler_entry();
if (current == NULL) {
/* Not enough memory */
bsp_interrupt_unlock();
return RTEMS_NO_MEMORY;
}
/* Allocate a new entry */
current = bsp_interrupt_allocate_handler_entry();
if (current == NULL) {
/* Not enough memory */
bsp_interrupt_unlock();
return RTEMS_NO_MEMORY;
}
/* Set entry */
current->handler = handler;
current->arg = arg;
current->info = info;
current->next = NULL;
/* Set entry */
current->handler = handler;
current->arg = arg;
current->info = info;
current->next = NULL;
/* Link to list tail */
rtems_interrupt_disable( level);
tail->next = current;
rtems_interrupt_enable( level);
}
/* Link to list tail */
rtems_interrupt_disable(level);
tail->next = current;
rtems_interrupt_enable(level);
}
/* Make the handler unique if necessary */
bsp_interrupt_set_handler_unique( index, RTEMS_INTERRUPT_IS_UNIQUE( options));
/* Make the handler unique if necessary */
bsp_interrupt_set_handler_unique(index, RTEMS_INTERRUPT_IS_UNIQUE(options));
/* Enable the vector if necessary */
if (enable_vector) {
sc = bsp_interrupt_vector_enable( vector);
if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock();
return sc;
}
}
/* Enable the vector if necessary */
if (enable_vector) {
sc = bsp_interrupt_vector_enable(vector);
if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock();
return sc;
}
}
/* Unlock */
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Unlock */
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
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().
*/
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_interrupt_level level;
rtems_vector_number index = 0;
bsp_interrupt_handler_entry *head = NULL;
bsp_interrupt_handler_entry *current = NULL;
bsp_interrupt_handler_entry *previous = NULL;
bsp_interrupt_handler_entry *match = NULL;
rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_interrupt_level level;
rtems_vector_number index = 0;
bsp_interrupt_handler_entry *head = NULL;
bsp_interrupt_handler_entry *current = NULL;
bsp_interrupt_handler_entry *previous = NULL;
bsp_interrupt_handler_entry *match = NULL;
/* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector( vector)) {
return RTEMS_INVALID_NUMBER;
} else if (handler == NULL) {
return RTEMS_INVALID_ADDRESS;
} else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
/* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_ID;
} else if (handler == NULL) {
return RTEMS_INVALID_ADDRESS;
} else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
/* Lock */
sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Lock */
sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Get handler table index */
index = bsp_interrupt_handler_index( vector);
/* Get handler table index */
index = bsp_interrupt_handler_index(vector);
/* Get head entry of the handler list for current vector */
head = &bsp_interrupt_handler_table [index];
/* Get head entry of the handler list for current vector */
head = &bsp_interrupt_handler_table [index];
/* Search for a matching entry */
current = head;
do {
if (current->handler == handler && current->arg == arg) {
match = current;
break;
}
previous = current;
current = current->next;
} while (current != NULL);
/* Search for a matching entry */
current = head;
do {
if (current->handler == handler && current->arg == arg) {
match = current;
break;
}
previous = current;
current = current->next;
} while (current != NULL);
/* Remove the matching entry */
if (match != NULL) {
if (match->next != NULL) {
/*
* The match has a successor. A successor is always
* allocated. So replace the match with its successor
* and free the successor entry.
*/
current = match->next;
/* Remove the matching entry */
if (match != NULL) {
if (match->next != NULL) {
/*
* The match has a successor. A successor is always
* allocated. So replace the match with its successor
* and free the successor entry.
*/
current = match->next;
rtems_interrupt_disable( level);
*match = *current;
rtems_interrupt_enable( level);
rtems_interrupt_disable(level);
*match = *current;
rtems_interrupt_enable(level);
bsp_interrupt_free_handler_entry( current);
} else if (match == head) {
/*
* The match is the list head and has no successor.
* The list head is stored in a static table so clear
* this entry. Since now the list is empty disable the
* vector.
*/
bsp_interrupt_free_handler_entry(current);
} else if (match == head) {
/*
* The match is the list head and has no successor.
* The list head is stored in a static table so clear
* this entry. Since now the list is empty disable the
* vector.
*/
/* Disable the vector */
sc = bsp_interrupt_vector_disable( vector);
/* Disable the vector */
sc = bsp_interrupt_vector_disable(vector);
/* Clear entry */
rtems_interrupt_disable( level);
bsp_interrupt_clear_handler_entry( head);
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_table [vector] = 0;
#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */
rtems_interrupt_enable( level);
/* Clear entry */
rtems_interrupt_disable(level);
bsp_interrupt_clear_handler_entry(head);
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
bsp_interrupt_handler_index_table [vector] = 0;
#endif
rtems_interrupt_enable(level);
/* Allow shared handlers */
bsp_interrupt_set_handler_unique( index, false);
/* Allow shared handlers */
bsp_interrupt_set_handler_unique(index, false);
/* Check status code */
if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock();
return sc;
}
} else {
/*
* The match is the list tail and has a predecessor.
* So terminate the predecessor and free the match.
*/
rtems_interrupt_disable( level);
previous->next = NULL;
rtems_interrupt_enable( level);
/* Check status code */
if (sc != RTEMS_SUCCESSFUL) {
bsp_interrupt_unlock();
return sc;
}
} else {
/*
* The match is the list tail and has a predecessor.
* So terminate the predecessor and free the match.
*/
rtems_interrupt_disable(level);
previous->next = NULL;
rtems_interrupt_enable(level);
bsp_interrupt_free_handler_entry( match);
}
} else {
/* No matching entry found */
bsp_interrupt_unlock();
return RTEMS_UNSATISFIED;
}
bsp_interrupt_free_handler_entry(match);
}
} else {
/* No matching entry found */
bsp_interrupt_unlock();
return RTEMS_UNSATISFIED;
}
/* Unlock */
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Unlock */
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
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().
*/
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;
bsp_interrupt_handler_entry *current = NULL;
rtems_option options = 0;
rtems_vector_number index = 0;
rtems_status_code sc = RTEMS_SUCCESSFUL;
bsp_interrupt_handler_entry *current = NULL;
rtems_option options = 0;
rtems_vector_number index = 0;
/* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector( vector)) {
return RTEMS_INVALID_NUMBER;
} else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
/* Check parameters and system state */
if (!bsp_interrupt_is_initialized()) {
return RTEMS_INTERNAL_ERROR;
} else if (!bsp_interrupt_is_valid_vector(vector)) {
return RTEMS_INVALID_ID;
} else if (rtems_interrupt_is_in_progress()) {
return RTEMS_CALLED_FROM_ISR;
}
/* Lock */
sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Lock */
sc = bsp_interrupt_lock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Interate */
index = bsp_interrupt_handler_index( vector);
current = &bsp_interrupt_handler_table [index];
if (!bsp_interrupt_is_empty_handler_entry( current)) {
do {
options = bsp_interrupt_is_handler_unique( index) ? RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
routine( arg, current->info, options, current->handler, current->arg);
current = current->next;
} while (current != NULL);
}
/* Interate */
index = bsp_interrupt_handler_index(vector);
current = &bsp_interrupt_handler_table [index];
if (!bsp_interrupt_is_empty_handler_entry(current)) {
do {
options = bsp_interrupt_is_handler_unique(index) ?
RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
routine(arg, current->info, options, current->handler, current->arg);
current = current->next;
} while (current != NULL);
}
/* Unlock */
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
/* Unlock */
sc = bsp_interrupt_unlock();
if (sc != RTEMS_SUCCESSFUL) {
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
*
* @brief Source file for generic BSP interrupt information code.
* @brief Generic BSP interrupt information implementation.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008, 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 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 <inttypes.h>
@@ -27,62 +28,70 @@
#include <bsp/irq-config.h>
typedef struct {
void *context;
rtems_printk_plugin_t print;
rtems_vector_number vector;
void *context;
rtems_printk_plugin_t print;
rtems_vector_number vector;
} bsp_interrupt_report_entry;
static void bsp_interrupt_report_per_handler_routine(
void *arg,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *handler_arg
void *arg,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *handler_arg
)
{
bsp_interrupt_report_entry *e = (bsp_interrupt_report_entry *) arg;
const char *opt = options == RTEMS_INTERRUPT_UNIQUE ? "UNIQUE" : "SHARED";
bsp_interrupt_report_entry *e = (bsp_interrupt_report_entry *) arg;
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
);
}
/**
* @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_with_plugin(
void *context,
rtems_printk_plugin_t print
)
{
rtems_vector_number v = 0;
bsp_interrupt_report_entry e = {
.context = context,
.print = print,
.vector = 0
};
rtems_vector_number v = 0;
bsp_interrupt_report_entry e = {
.context = context,
.print = print,
.vector = 0
};
print(
context,
"-------------------------------------------------------------------------------\n"
" INTERRUPT INFORMATION\n"
"--------+----------------------------------+---------+------------+------------\n"
" VECTOR | INFO | OPTIONS | HANDLER | ARGUMENT \n"
"--------+----------------------------------+---------+------------+------------\n"
);
print(
context,
"-------------------------------------------------------------------------------\n"
" INTERRUPT INFORMATION\n"
"--------+----------------------------------+---------+------------+------------\n"
" VECTOR | INFO | OPTIONS | HANDLER | ARGUMENT \n"
"--------+----------------------------------+---------+------------+------------\n"
);
for (v = BSP_INTERRUPT_VECTOR_MIN; v <= BSP_INTERRUPT_VECTOR_MAX; ++v) {
e.vector = v;
(void) rtems_interrupt_handler_iterate( v, bsp_interrupt_report_per_handler_routine, &e);
}
for (v = BSP_INTERRUPT_VECTOR_MIN; v <= BSP_INTERRUPT_VECTOR_MAX; ++v) {
e.vector = v;
rtems_interrupt_handler_iterate(
v,
bsp_interrupt_report_per_handler_routine,
&e
);
}
print(
context,
"--------+----------------------------------+---------+------------+------------\n"
);
print(
context,
"--------+----------------------------------+---------+------------+------------\n"
);
}
/**
* @brief Prints interrupt information via the default printk plugin.
*/
void bsp_interrupt_report( void)
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
*
* @brief Source file for generic BSP interrupt support legacy code.
* @brief Generic BSP interrupt support legacy implementation.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008, 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.
* <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 <stdbool.h>
#include <stdlib.h>
#define BSP_SHARED_HANDLER_SUPPORT
#include <rtems/irq.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)
{
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) {
return 0;
@@ -95,8 +96,7 @@ int BSP_install_rtems_irq_handler(const rtems_irq_connect_data *cd)
sc = rtems_interrupt_handler_install(
cd->name,
"Unique interrupt handler "
"(installed with obsolete BSP_install_rtems_irq_handler())",
"LEGACY INSTALLED",
RTEMS_INTERRUPT_UNIQUE,
bsp_interrupt_legacy_dispatch,
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)
{
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) {
return 0;
@@ -130,8 +130,7 @@ int BSP_install_rtems_shared_irq_handler(const rtems_irq_connect_data *cd)
sc = rtems_interrupt_handler_install(
cd->name,
"Shared interrupt handler "
"(installed with obsolete BSP_install_rtems_shared_irq_handler())",
"LEGACY INSTALLED",
RTEMS_INTERRUPT_SHARED,
bsp_interrupt_legacy_dispatch,
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
*
* @brief Source file for generic BSP interrupt shell code.
* @brief Generic BSP interrupt shell implementation.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 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 <stdio.h>
@@ -25,16 +25,13 @@
#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;
}
/**
* @brief Shell command entry for interrupt information.
*/
struct rtems_shell_cmd_tt bsp_interrupt_shell_command = {
.name = "irq",
.usage = "Prints interrupt information",

View File

@@ -30,21 +30,21 @@ static Heap_Control bsp_stack_heap = {
.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.end = (void *) size;
bsp_stack_heap.area_begin = (uintptr_t) begin;
bsp_stack_heap.area_end = size;
}
void *bsp_stack_allocate(uint32_t size)
void *bsp_stack_allocate(size_t size)
{
void *stack = NULL;
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.begin,
(intptr_t) bsp_stack_heap.end,
(void *) bsp_stack_heap.area_begin,
bsp_stack_heap.area_end,
CPU_STACK_ALIGNMENT
);
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) {
stack = _Workspace_Allocate(size);