forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -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;
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
275
c/src/lib/libbsp/shared/src/irq-server.c
Normal file
275
c/src/lib/libbsp/shared/src/irq-server.c
Normal 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;
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user