diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2009-09-08 13:35:07 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2009-09-08 13:35:07 +0000 |
commit | 8634637d1dbb4f736d7bf050c32814165c9a6d3f (patch) | |
tree | 7ff0a95d7d847501174213edf9603be09bf879b3 /c | |
parent | Fix GDB_VERS. (diff) | |
download | rtems-8634637d1dbb4f736d7bf050c32814165c9a6d3f.tar.bz2 |
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.
Diffstat (limited to 'c')
-rw-r--r-- | c/src/lib/libbsp/shared/ChangeLog | 9 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/bsplibc.c | 8 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/include/bootcard.h | 83 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/include/irq-config.h | 31 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/include/irq-generic.h | 103 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/include/irq-info.h | 30 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/include/stackalloc.h | 54 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/src/irq-generic.c | 921 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/src/irq-info.c | 107 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/src/irq-legacy.c | 27 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/src/irq-server.c | 275 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/src/irq-shell.c | 21 | ||||
-rw-r--r-- | c/src/lib/libbsp/shared/src/stackalloc.c | 16 |
13 files changed, 1079 insertions, 606 deletions
diff --git a/c/src/lib/libbsp/shared/ChangeLog b/c/src/lib/libbsp/shared/ChangeLog index 4cecea7cab..fed8fab637 100644 --- a/c/src/lib/libbsp/shared/ChangeLog +++ b/c/src/lib/libbsp/shared/ChangeLog @@ -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 diff --git a/c/src/lib/libbsp/shared/bsplibc.c b/c/src/lib/libbsp/shared/bsplibc.c index ce0090077d..05fdaa7ca8 100644 --- a/c/src/lib/libbsp/shared/bsplibc.c +++ b/c/src/lib/libbsp/shared/bsplibc.c @@ -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 diff --git a/c/src/lib/libbsp/shared/include/bootcard.h b/c/src/lib/libbsp/shared/include/bootcard.h index 9a6dcfdb93..ed0c5598bb 100644 --- a/c/src/lib/libbsp/shared/include/bootcard.h +++ b/c/src/lib/libbsp/shared/include/bootcard.h @@ -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 } diff --git a/c/src/lib/libbsp/shared/include/irq-config.h b/c/src/lib/libbsp/shared/include/irq-config.h index 3fffc779a1..9596f98b5c 100644 --- a/c/src/lib/libbsp/shared/include/irq-config.h +++ b/c/src/lib/libbsp/shared/include/irq-config.h @@ -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 /** @} */ diff --git a/c/src/lib/libbsp/shared/include/irq-generic.h b/c/src/lib/libbsp/shared/include/irq-generic.h index f396e18d17..2386587ccb 100644 --- a/c/src/lib/libbsp/shared/include/irq-generic.h +++ b/c/src/lib/libbsp/shared/include/irq-generic.h @@ -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)]; - - do { - e->handler( vector, e->arg); - e = e->next; - } while (e != NULL); - } else { - bsp_interrupt_handler_default( 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); + } } /** @} */ diff --git a/c/src/lib/libbsp/shared/include/irq-info.h b/c/src/lib/libbsp/shared/include/irq-info.h index f2dee7ed35..02efc955c0 100644 --- a/c/src/lib/libbsp/shared/include/irq-info.h +++ b/c/src/lib/libbsp/shared/include/irq-info.h @@ -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; /** @} */ diff --git a/c/src/lib/libbsp/shared/include/stackalloc.h b/c/src/lib/libbsp/shared/include/stackalloc.h index e95f43591a..56132da317 100644 --- a/c/src/lib/libbsp/shared/include/stackalloc.h +++ b/c/src/lib/libbsp/shared/include/stackalloc.h @@ -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 + * + * @{ + */ + +/** + * @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); -void *bsp_stack_allocate(uint32_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 */ diff --git a/c/src/lib/libbsp/shared/src/irq-generic.c b/c/src/lib/libbsp/shared/src/irq-generic.c index 71ab216ded..8356728f41 100644 --- a/c/src/lib/libbsp/shared/src/irq-generic.c +++ b/c/src/lib/libbsp/shared/src/irq-generic.c @@ -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; - - /* 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; - } - } - - return 0; -#else /* BSP_INTERRUPT_USE_INDEX_TABLE */ - *index = vector; - return 1; -#endif /* BSP_INTERRUPT_USE_INDEX_TABLE */ + #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) { + const bsp_interrupt_handler_entry *e = &bsp_interrupt_handler_table [i]; + if (bsp_interrupt_is_empty_handler_entry(e)) { + *index = i; + return true; + } + } + + 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; - - /* 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; - } - - /* 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 */ - - 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_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_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 */ + + 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; + } } -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; - - /* Lock */ - 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; - } - - /* BSP specific initialization */ - sc = bsp_interrupt_facility_initialize(); - if (sc != RTEMS_SUCCESSFUL) { - bsp_interrupt_unlock(); - return sc; - } - - /* Now we are initialized */ - bsp_interrupt_set_initialized(); - - /* Unlock */ - sc = bsp_interrupt_unlock(); - if (sc != RTEMS_SUCCESSFUL) { - return sc; - } - - return RTEMS_SUCCESSFUL; + rtems_status_code sc = RTEMS_SUCCESSFUL; + size_t i = 0; + + sc = bsp_interrupt_lock(); + if (sc != RTEMS_SUCCESSFUL) { + return sc; + } + + /* 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; + } + + if (bsp_interrupt_is_initialized()) { + bsp_interrupt_unlock(); + return RTEMS_INTERNAL_ERROR; + } + + /* Initialize handler table */ + for (i = 0; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) { + bsp_interrupt_handler_table [i].handler = bsp_interrupt_handler_empty; + } + + sc = bsp_interrupt_facility_initialize(); + if (sc != RTEMS_SUCCESSFUL) { + bsp_interrupt_unlock(); + return sc; + } + + 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; - - /* 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; - } - - /* Lock */ - sc = bsp_interrupt_lock(); - if (sc != RTEMS_SUCCESSFUL) { - return sc; - } - - /* 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]; - - 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; - } - - /* 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); - - /* 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; - } - - /* 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); - } - - /* 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; - } - } - - /* Unlock */ - sc = bsp_interrupt_unlock(); - if (sc != RTEMS_SUCCESSFUL) { - return sc; - } - - return RTEMS_SUCCESSFUL; + 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_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; + } + + /* 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]; + + 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; + } + + /* + * 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; + } + + /* 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; + + /* 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)); + + /* 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; + } + + 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; - - /* 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; - } - - /* Lock */ - sc = bsp_interrupt_lock(); - if (sc != RTEMS_SUCCESSFUL) { - return sc; - } - - /* 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]; - - /* 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; - - 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. - */ - - /* 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); - - /* 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); - - 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; - } - - return RTEMS_SUCCESSFUL; + 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_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; + } + + /* 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]; + + /* 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; + + 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. + */ + + /* 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 + rtems_interrupt_enable(level); + + /* 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); + + 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; + } + + 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; - - /* 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; - } - - /* 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); - } - - /* Unlock */ - sc = bsp_interrupt_unlock(); - if (sc != RTEMS_SUCCESSFUL) { - return sc; - } - - return RTEMS_SUCCESSFUL; + 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_ID; + } else if (rtems_interrupt_is_in_progress()) { + return RTEMS_CALLED_FROM_ISR; + } + + /* 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); + } + + /* Unlock */ + sc = bsp_interrupt_unlock(); + if (sc != RTEMS_SUCCESSFUL) { + return sc; + } + + 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); } diff --git a/c/src/lib/libbsp/shared/src/irq-info.c b/c/src/lib/libbsp/shared/src/irq-info.c index 6736d508b7..474784752d 100644 --- a/c/src/lib/libbsp/shared/src/irq-info.c +++ b/c/src/lib/libbsp/shared/src/irq-info.c @@ -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); } diff --git a/c/src/lib/libbsp/shared/src/irq-legacy.c b/c/src/lib/libbsp/shared/src/irq-legacy.c index 9f916235d0..b864541b8b 100644 --- a/c/src/lib/libbsp/shared/src/irq-legacy.c +++ b/c/src/lib/libbsp/shared/src/irq-legacy.c @@ -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 diff --git a/c/src/lib/libbsp/shared/src/irq-server.c b/c/src/lib/libbsp/shared/src/irq-server.c new file mode 100644 index 0000000000..ac923a9a8e --- /dev/null +++ b/c/src/lib/libbsp/shared/src/irq-server.c @@ -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; +} diff --git a/c/src/lib/libbsp/shared/src/irq-shell.c b/c/src/lib/libbsp/shared/src/irq-shell.c index 341f30364a..2d8d508378 100644 --- a/c/src/lib/libbsp/shared/src/irq-shell.c +++ b/c/src/lib/libbsp/shared/src/irq-shell.c @@ -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", diff --git a/c/src/lib/libbsp/shared/src/stackalloc.c b/c/src/lib/libbsp/shared/src/stackalloc.c index 31b7c14db3..e6145d5873 100644 --- a/c/src/lib/libbsp/shared/src/stackalloc.c +++ b/c/src/lib/libbsp/shared/src/stackalloc.c @@ -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); |