Changeset e518323 in rtems
- Timestamp:
- 06/25/21 13:52:16 (3 years ago)
- Branches:
- master
- Children:
- b910e60
- Parents:
- 70357f1
- git-author:
- Sebastian Huber <sebastian.huber@…> (06/25/21 13:52:16)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (07/26/21 17:57:31)
- Files:
-
- 3 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
bsps/i386/shared/irq/irq.c
r70357f1 re518323 354 354 static bool bsp_interrupt_handler_is_empty(rtems_vector_number vector) 355 355 { 356 rtems_vector_number index; 357 rtems_interrupt_entry *head; 358 359 index = bsp_interrupt_handler_index(vector); 360 head = &bsp_interrupt_handler_table[index]; 361 362 return bsp_interrupt_is_empty_handler_entry(head); 356 return bsp_interrupt_entry_load_first(vector) == NULL; 363 357 } 364 358 -
bsps/include/bsp/irq-generic.h
r70357f1 re518323 13 13 * Copyright (C) 2016 Chris Johns <chrisj@rtems.org> 14 14 * 15 * Copyright (C) 2008, 20 17embedded brains GmbH (http://www.embedded-brains.de)15 * Copyright (C) 2008, 2021 embedded brains GmbH (http://www.embedded-brains.de) 16 16 * 17 17 * Redistribution and use in source and binary forms, with or without … … 71 71 #endif 72 72 73 /* Internal macros for SMP support, do not use externally */74 #ifdef RTEMS_SMP75 #define bsp_interrupt_disable(level) do { (void) level; } while (0)76 #define bsp_interrupt_enable(level) do { } while (0)77 #define bsp_interrupt_fence(order) _Atomic_Fence(order)78 #else79 #define bsp_interrupt_disable(level) rtems_interrupt_disable(level)80 #define bsp_interrupt_enable(level) rtems_interrupt_enable(level)81 #define bsp_interrupt_fence(order) do { } while (0)82 #endif83 84 73 #define bsp_interrupt_assert(e) _Assert(e) 85 74 86 extern rtems_interrupt_entry bsp_interrupt_handler_table []; 75 /** 76 * @brief Each member of this table references the first installed entry at the 77 * corresponding interrupt vector or is NULL. 78 */ 79 extern rtems_interrupt_entry *bsp_interrupt_handler_table[]; 87 80 88 81 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE … … 141 134 * - bsp_interrupt_vector_disable() 142 135 * - bsp_interrupt_handler_default() 136 * 137 * Optionally, the BSP may define the following macros to customize the vector 138 * installation after installing the first entry and the vector removal before 139 * removing the last entry: 140 * - bsp_interrupt_vector_install() 141 * - bsp_interrupt_vector_remove() 143 142 * 144 143 * The following now deprecated functions are provided for backward … … 363 362 rtems_status_code bsp_interrupt_clear( rtems_vector_number vector ); 364 363 364 #if defined(RTEMS_SMP) 365 /** 366 * @brief Handles a spurious interrupt. 367 * 368 * @param vector is the vector number. 369 */ 370 void bsp_interrupt_spurious( rtems_vector_number vector ); 371 #endif 372 373 /** 374 * @brief Loads the interrupt entry with atomic acquire semantic. 375 * 376 * @param ptr is the pointer to an ::rtems_interrupt_entry pointer. 377 * 378 * @return Returns the pointer value. 379 */ 380 static inline rtems_interrupt_entry *bsp_interrupt_entry_load_acquire( 381 rtems_interrupt_entry * const *ptr 382 ) 383 { 384 #if defined(RTEMS_SMP) 385 return (rtems_interrupt_entry *) _Atomic_Load_uintptr( 386 (const Atomic_Uintptr *) ptr, 387 ATOMIC_ORDER_ACQUIRE 388 ); 389 #else 390 return *ptr; 391 #endif 392 } 393 394 /** 395 * @brief Stores the interrupt entry with atomic release semantic. 396 * 397 * @param[out] ptr is the pointer to an ::rtems_interrupt_entry pointer. 398 * 399 * @param value is the pointer value. 400 */ 401 static inline void bsp_interrupt_entry_store_release( 402 rtems_interrupt_entry **ptr, 403 rtems_interrupt_entry *value 404 ) 405 { 406 #if defined(RTEMS_SMP) 407 _Atomic_Store_uintptr( 408 (Atomic_Uintptr *) ptr, 409 (Atomic_Uintptr) value, 410 ATOMIC_ORDER_RELEASE 411 ); 412 #else 413 rtems_interrupt_level level; 414 415 rtems_interrupt_local_disable( level ); 416 *ptr = value; 417 rtems_interrupt_local_enable( level ); 418 #endif 419 } 420 421 /** 422 * @brief Loads the first interrupt entry installed at the interrupt vector. 423 * 424 * @param vector is the vector number. 425 * 426 * @return Returns the first entry or NULL. 427 */ 428 static inline rtems_interrupt_entry *bsp_interrupt_entry_load_first( 429 rtems_vector_number vector 430 ) 431 { 432 rtems_vector_number index; 433 434 index = bsp_interrupt_handler_index( vector ); 435 436 return bsp_interrupt_entry_load_acquire( 437 &bsp_interrupt_handler_table[ index ] 438 ); 439 } 440 441 /** 442 * @brief Sequentially calls all interrupt handlers of the entry its 443 * successors. 444 * 445 * In uniprocessor configurations, you can call this function within every 446 * context which can be disabled via rtems_interrupt_local_disable(). 447 * 448 * In SMP configurations, you can call this function in every context. 449 * 450 * @param entry is the first entry. 451 */ 452 static inline void bsp_interrupt_dispatch_entries( 453 const rtems_interrupt_entry *entry 454 ) 455 { 456 do { 457 ( *entry->handler )( entry->arg ); 458 entry = bsp_interrupt_entry_load_acquire( &entry->next ); 459 } while ( RTEMS_PREDICT_FALSE( entry != NULL ) ); 460 } 461 365 462 /** 366 463 * @brief Sequentially calls all interrupt handlers installed at the vector. … … 369 466 * out of range, then the behaviour is undefined. 370 467 * 371 * You can call this function within every context which can be disabled via 372 * rtems_interrupt_local_disable(). 468 * In uniprocessor configurations, you can call this function within every 469 * context which can be disabled via rtems_interrupt_local_disable(). 470 * 471 * In SMP configurations, you can call this function in every context. 373 472 * 374 473 * @param vector is the vector number. … … 378 477 ) 379 478 { 380 const rtems_interrupt_entry *e; 381 382 e = &bsp_interrupt_handler_table[ bsp_interrupt_handler_index( vector ) ]; 383 384 do { 385 rtems_interrupt_handler handler; 386 void *arg; 387 388 arg = e->arg; 389 bsp_interrupt_fence( ATOMIC_ORDER_ACQUIRE ); 390 handler = e->handler; 391 ( *handler )( arg ); 392 393 e = e->next; 394 } while ( e != NULL ); 479 const rtems_interrupt_entry *entry; 480 481 entry = bsp_interrupt_entry_load_first( vector ); 482 483 if ( RTEMS_PREDICT_TRUE( entry != NULL ) ) { 484 bsp_interrupt_dispatch_entries( entry ); 485 } else { 486 #if defined(RTEMS_SMP) 487 bsp_interrupt_spurious( vector ); 488 #else 489 bsp_interrupt_handler_default( vector ); 490 #endif 491 } 395 492 } 396 493 … … 402 499 * argument. 403 500 * 404 * You can call this function within every context which can be disabled via 405 * rtems_interrupt_local_disable(). 501 * In uniprocessor configurations, you can call this function within every 502 * context which can be disabled via rtems_interrupt_local_disable(). 503 * 504 * In SMP configurations, you can call this function in every context. 406 505 * 407 506 * @param vector is the vector number. … … 458 557 ); 459 558 559 /* For internal use only */ 560 rtems_interrupt_entry *bsp_interrupt_entry_find( 561 rtems_vector_number vector, 562 rtems_interrupt_handler routine, 563 void *arg, 564 rtems_interrupt_entry ***previous_next 565 ); 566 567 /* For internal use only */ 568 void bsp_interrupt_entry_remove( 569 rtems_vector_number vector, 570 rtems_interrupt_entry *entry, 571 rtems_interrupt_entry **previous_next 572 ); 573 460 574 /** 461 575 * @brief This table contains a bit map which indicates if an entry is unique … … 490 604 491 605 /** 606 * @brief Sets the unique status of the handler entry. 607 * 608 * @param index is the handler index. 609 * 610 * @param unique is the unique status to set. 611 */ 612 static inline void bsp_interrupt_set_handler_unique( 613 rtems_vector_number index, 614 bool unique 615 ) 616 { 617 rtems_vector_number table_index; 618 uint8_t bit; 619 620 table_index = index / 8; 621 bit = (uint8_t) ( 1U << ( index % 8 ) ); 622 623 if (unique) { 624 bsp_interrupt_handler_unique_table[ table_index ] |= bit; 625 } else { 626 bsp_interrupt_handler_unique_table[ table_index ] &= ~bit; 627 } 628 } 629 630 /** 492 631 * @brief Checks if the interrupt support is initialized. 493 632 * … … 500 639 } 501 640 502 /**503 * @brief This handler routine is used for empty entries.504 */505 void bsp_interrupt_handler_empty( void *arg );506 507 /**508 * @brief Checks if a handler entry is empty.509 */510 static inline bool bsp_interrupt_is_empty_handler_entry(511 const rtems_interrupt_entry *entry512 )513 {514 return entry->handler == bsp_interrupt_handler_empty;515 }516 517 641 #ifdef __cplusplus 518 642 } -
bsps/m68k/genmcf548x/include/bsp/irq.h
r70357f1 re518323 100 100 } 101 101 102 void mcf548x_interrupt_vector_install(rtems_vector_number vector); 103 104 void mcf548x_interrupt_vector_remove(rtems_vector_number vector); 105 106 #define bsp_interrupt_vector_install(v) mcf548x_interrupt_vector_install(v) 107 108 #define bsp_interrupt_vector_remove(v) mcf548x_interrupt_vector_remove(v) 109 102 110 #endif /* LIBBSP_M68K_MCF548X_IRQ_H */ -
bsps/m68k/genmcf548x/irq/irq.c
r70357f1 re518323 1 1 /* 2 * Copyright (c) 2013 embedded brains GmbH. All rights reserved.2 * Copyright (c) 2013, 2021 embedded brains GmbH. All rights reserved. 3 3 * 4 4 * embedded brains GmbH … … 20 20 21 21 typedef void (*void_func)(void); 22 23 typedef struct {24 rtems_interrupt_handler handler;25 void *arg;26 const char *info;27 } interrupt_control;28 29 static interrupt_control interrupt_controls[BSP_INTERRUPT_VECTOR_COUNT];30 22 31 23 static uint32_t vector_to_reg(rtems_vector_number vector) … … 132 124 } 133 125 134 static void_func get_exception_handler(rtems_vector_number vector)135 {136 void **vbr;137 void_func *exception_table;138 139 m68k_get_vbr(vbr);140 141 exception_table = (void_func *)vbr;142 143 return exception_table[vector_to_exception_vector(vector)];144 }145 146 126 static void set_exception_handler(rtems_vector_number vector, void_func handler) 147 127 { … … 158 138 static void dispatch_handler(rtems_vector_number exception_vector) 159 139 { 160 const interrupt_control *ic = 161 &interrupt_controls[exception_vector_to_vector(exception_vector)]; 162 163 (*ic->handler)(ic->arg); 140 bsp_interrupt_handler_dispatch_unchecked( 141 exception_vector_to_vector(exception_vector) 142 ); 164 143 } 165 144 166 static uint8_t get_intc_icr(rtems_vector_number vector)145 void mcf548x_interrupt_vector_install(rtems_vector_number vector) 167 146 { 168 volatile uint8_t *icr = &MCF548X_INTC_ICR0;169 170 return icr[vector];147 _ISR_Vector_table[vector_to_exception_vector(vector)] 148 = dispatch_handler; 149 set_exception_handler(vector, _ISR_Handler); 171 150 } 172 151 173 rtems_status_code rtems_interrupt_handler_install( 174 rtems_vector_number vector, 175 const char *info, 176 rtems_option options, 177 rtems_interrupt_handler handler, 178 void *arg 179 ) 152 void mcf548x_interrupt_vector_remove(rtems_vector_number vector) 180 153 { 181 rtems_status_code sc = RTEMS_SUCCESSFUL; 182 183 if (bsp_interrupt_is_valid_vector(vector)) { 184 rtems_interrupt_level level; 185 186 rtems_interrupt_disable(level); 187 188 if ( 189 get_exception_handler(vector) == asm_default_interrupt 190 && get_intc_icr(vector) != 0 191 ) { 192 interrupt_control *ic = &interrupt_controls[vector]; 193 194 ic->handler = handler; 195 ic->arg = arg; 196 ic->info = info; 197 198 _ISR_Vector_table[vector_to_exception_vector(vector)] 199 = dispatch_handler; 200 set_exception_handler(vector, _ISR_Handler); 201 bsp_interrupt_vector_enable(vector); 202 } else { 203 sc = RTEMS_RESOURCE_IN_USE; 204 } 205 206 rtems_interrupt_enable(level); 207 } else { 208 sc = RTEMS_INVALID_ID; 209 } 210 211 return sc; 154 set_exception_handler(vector, asm_default_interrupt); 212 155 } 213 214 static bool is_occupied_by_us(rtems_vector_number vector)215 {216 return get_exception_handler(vector) == _ISR_Handler217 && _ISR_Vector_table[vector_to_exception_vector(vector)]218 == dispatch_handler;219 }220 221 rtems_status_code rtems_interrupt_handler_remove(222 rtems_vector_number vector,223 rtems_interrupt_handler handler,224 void *arg225 )226 {227 rtems_status_code sc = RTEMS_SUCCESSFUL;228 229 if (bsp_interrupt_is_valid_vector(vector)) {230 rtems_interrupt_level level;231 interrupt_control *ic = &interrupt_controls[vector];232 233 rtems_interrupt_disable(level);234 235 if (236 is_occupied_by_us(vector)237 && ic->handler == handler238 && ic->arg == arg239 ) {240 bsp_interrupt_vector_disable(vector);241 set_exception_handler(vector, asm_default_interrupt);242 243 memset(ic, 0, sizeof(*ic));244 } else {245 sc = RTEMS_UNSATISFIED;246 }247 248 rtems_interrupt_enable(level);249 } else {250 sc = RTEMS_INVALID_ID;251 }252 253 return sc;254 }255 256 rtems_status_code rtems_interrupt_handler_iterate(257 rtems_vector_number vector,258 rtems_interrupt_per_handler_routine routine,259 void *arg260 )261 {262 rtems_status_code sc = RTEMS_SUCCESSFUL;263 264 if (bsp_interrupt_is_valid_vector(vector)) {265 if (is_occupied_by_us(vector)) {266 const interrupt_control *ic = &interrupt_controls[vector];267 268 (*routine)(arg, ic->info, RTEMS_INTERRUPT_UNIQUE, ic->handler, ic->arg);269 }270 } else {271 sc = RTEMS_INVALID_ID;272 }273 274 return sc;275 } -
bsps/shared/irq-default-sources.am
r70357f1 re518323 4 4 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c 5 5 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c 6 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c 6 7 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c 8 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c 7 9 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c 10 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c 8 11 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c 9 12 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c -
bsps/shared/irq-sources.am
r70357f1 re518323 2 2 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c 3 3 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c 4 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c 4 5 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c 6 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c 5 7 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c 8 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c 6 9 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c 7 10 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-legacy.c -
bsps/shared/irq/irq-generic.c
r70357f1 re518323 11 11 12 12 /* 13 * Copyright (C) 2008, 20 18embedded brains GmbH (http://www.embedded-brains.de)13 * Copyright (C) 2008, 2021 embedded brains GmbH (http://www.embedded-brains.de) 14 14 * 15 15 * Redistribution and use in source and binary forms, with or without … … 47 47 #endif 48 48 49 rtems_interrupt_entry bsp_interrupt_handler_table50 [BSP_INTERRUPT_HANDLER_TABLE_SIZE];49 rtems_interrupt_entry * 50 bsp_interrupt_handler_table[ BSP_INTERRUPT_HANDLER_TABLE_SIZE ]; 51 51 52 52 /* The last entry indicates if everything is initialized */ … … 54 54 [ ( BSP_INTERRUPT_HANDLER_TABLE_SIZE + 7 + 1 ) / 8 ]; 55 55 56 void bsp_interrupt_handler_empty( void *arg ) 57 { 58 rtems_vector_number vector = (rtems_vector_number) (uintptr_t) arg; 59 60 bsp_interrupt_handler_default( vector ); 61 } 62 63 #ifdef RTEMS_SMP 64 static void bsp_interrupt_handler_do_nothing(void *arg) 65 { 66 (void) arg; 67 } 68 #endif 69 70 static inline void bsp_interrupt_set_handler_unique( 71 rtems_vector_number index, 72 bool unique 73 ) 74 { 75 rtems_vector_number i = index / 8; 76 rtems_vector_number s = index % 8; 77 if (unique) { 78 bsp_interrupt_handler_unique_table [i] |= (uint8_t) (0x1U << s); 56 static inline void bsp_interrupt_set_initialized(void) 57 { 58 bsp_interrupt_set_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE, true); 59 } 60 61 #if defined(BSP_INTERRUPT_USE_INDEX_TABLE) 62 static inline rtems_vector_number bsp_interrupt_allocate_handler_index( 63 rtems_vector_number vector 64 ) 65 { 66 rtems_vector_number i; 67 68 /* The first entry will remain empty */ 69 for ( i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i ) { 70 if ( bsp_interrupt_handler_table[ i ] == NULL ) { 71 break; 72 } 73 } 74 75 return i; 76 } 77 #endif 78 79 #if defined(RTEMS_SMP) 80 RTEMS_STATIC_ASSERT( 81 sizeof( Atomic_Uintptr ) == sizeof( rtems_interrupt_entry * ), 82 rtems_interrupt_entry_pointer_size 83 ); 84 85 void bsp_interrupt_spurious( rtems_vector_number vector ) 86 { 87 Atomic_Uintptr *ptr; 88 rtems_interrupt_entry *first; 89 90 /* 91 * In order to get the last written pointer value to the first entry, we have 92 * to carry out an atomic read-modify-write operation. 93 */ 94 ptr = (Atomic_Uintptr *) &bsp_interrupt_handler_table[ 95 bsp_interrupt_handler_index( vector ) 96 ]; 97 first = (rtems_interrupt_entry *) 98 _Atomic_Fetch_add_uintptr( ptr, 0, ATOMIC_ORDER_ACQUIRE ); 99 100 if ( first == NULL ) { 101 bsp_interrupt_handler_default( vector ); 79 102 } else { 80 bsp_interrupt_handler_unique_table [i] &= (uint8_t) ~(0x1U << s); 81 } 82 } 83 84 static inline void bsp_interrupt_set_initialized(void) 85 { 86 bsp_interrupt_set_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE, true); 87 } 88 89 static inline void bsp_interrupt_clear_handler_entry( 90 rtems_interrupt_entry *e, 91 rtems_vector_number vector 92 ) 93 { 94 e->handler = bsp_interrupt_handler_empty; 95 bsp_interrupt_fence(ATOMIC_ORDER_RELEASE); 96 e->arg = (void *) (uintptr_t) vector; 97 e->info = NULL; 98 e->next = NULL; 99 } 100 101 static inline bool bsp_interrupt_allocate_handler_index( 102 rtems_vector_number vector, 103 rtems_vector_number *index 104 ) 105 { 106 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE 107 rtems_vector_number i = 0; 108 109 /* The first entry will remain empty */ 110 for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) { 111 const rtems_interrupt_entry *e = &bsp_interrupt_handler_table [i]; 112 if (bsp_interrupt_is_empty_handler_entry(e)) { 113 *index = i; 114 return true; 115 } 116 } 117 118 return false; 119 #else 120 *index = bsp_interrupt_handler_index(vector); 121 return true; 122 #endif 123 } 103 bsp_interrupt_dispatch_entries( first ); 104 } 105 } 106 #endif 124 107 125 108 rtems_status_code bsp_interrupt_check_and_lock( 126 109 rtems_vector_number vector, 127 rtems_interrupt_handler handler110 rtems_interrupt_handler routine 128 111 ) 129 112 { … … 132 115 } 133 116 134 if ( handler== NULL ) {117 if ( routine == NULL ) { 135 118 return RTEMS_INVALID_ADDRESS; 136 119 } … … 149 132 } 150 133 151 void bsp_interrupt_initialize(void) 152 { 153 rtems_status_code sc = RTEMS_SUCCESSFUL; 154 size_t i = 0; 155 156 /* Initialize handler table */ 157 for (i = 0; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) { 158 bsp_interrupt_handler_table [i].handler = bsp_interrupt_handler_empty; 159 bsp_interrupt_handler_table [i].arg = (void *) i; 160 } 134 rtems_interrupt_entry *bsp_interrupt_entry_find( 135 rtems_vector_number vector, 136 rtems_interrupt_handler routine, 137 void *arg, 138 rtems_interrupt_entry ***previous_next 139 ) 140 { 141 rtems_vector_number index; 142 rtems_interrupt_entry *entry; 143 144 bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); 145 index = bsp_interrupt_handler_index( vector ); 146 *previous_next = &bsp_interrupt_handler_table[ index ]; 147 entry = bsp_interrupt_handler_table[ index ]; 148 149 while ( entry != NULL ) { 150 if ( entry->handler == routine && entry->arg == arg ) { 151 return entry; 152 } 153 154 *previous_next = &entry->next; 155 entry = entry->next; 156 } 157 158 return NULL; 159 } 160 161 void bsp_interrupt_initialize( void ) 162 { 163 rtems_status_code sc; 161 164 162 165 sc = bsp_interrupt_facility_initialize(); 163 if ( sc != RTEMS_SUCCESSFUL) {164 bsp_fatal( BSP_FATAL_INTERRUPT_INITIALIZATION);166 if ( sc != RTEMS_SUCCESSFUL ) { 167 bsp_fatal( BSP_FATAL_INTERRUPT_INITIALIZATION ); 165 168 } 166 169 … … 168 171 } 169 172 170 /** 171 * @brief Installs an interrupt handler. 172 * 173 * @ingroup bsp_interrupt 174 * 175 * @return In addition to the standard status codes this function returns: 176 * - If the BSP interrupt support is not initialized RTEMS_INTERNAL_ERROR will 177 * be returned. 178 * - If not enough memory for a new handler is available RTEMS_NO_MEMORY will 179 * be returned 180 * 181 * @see rtems_interrupt_handler_install() 182 */ 183 static rtems_status_code bsp_interrupt_handler_install( 184 rtems_vector_number vector, 185 const char *info, 186 rtems_option options, 187 rtems_interrupt_handler handler, 188 void *arg 173 static rtems_status_code bsp_interrupt_entry_install_first( 174 rtems_vector_number vector, 175 rtems_option options, 176 rtems_interrupt_entry *entry 177 ) 178 { 179 rtems_vector_number index; 180 181 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE 182 index = bsp_interrupt_allocate_handler_index( vector ); 183 184 if ( index == BSP_INTERRUPT_HANDLER_TABLE_SIZE ) { 185 /* Handler table is full */ 186 return RTEMS_NO_MEMORY; 187 } 188 #else 189 index = vector; 190 #endif 191 192 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE 193 bsp_interrupt_handler_index_table[ vector ] = index; 194 #endif 195 bsp_interrupt_entry_store_release( 196 &bsp_interrupt_handler_table[ index ], 197 entry 198 ); 199 200 bsp_interrupt_set_handler_unique( 201 index, 202 RTEMS_INTERRUPT_IS_UNIQUE( options ) 203 ); 204 #if defined(bsp_interrupt_vector_install) 205 bsp_interrupt_vector_install( vector ); 206 #else 207 bsp_interrupt_vector_enable( vector ); 208 #endif 209 210 return RTEMS_SUCCESSFUL; 211 } 212 213 static rtems_status_code bsp_interrupt_entry_install( 214 rtems_vector_number vector, 215 rtems_option options, 216 rtems_interrupt_entry *entry 217 ) 218 { 219 rtems_vector_number index; 220 rtems_interrupt_entry *first; 221 rtems_interrupt_entry *other; 222 rtems_interrupt_entry **previous_next; 223 224 if ( RTEMS_INTERRUPT_IS_REPLACE( options ) ) { 225 return RTEMS_INVALID_NUMBER; 226 } 227 228 index = bsp_interrupt_handler_index( vector ); 229 first = bsp_interrupt_handler_table[ index ]; 230 231 if ( first == NULL ) { 232 return bsp_interrupt_entry_install_first( vector, options, entry ); 233 } 234 235 if ( RTEMS_INTERRUPT_IS_UNIQUE( options ) ) { 236 /* Cannot install a unique entry if there is already an entry installed */ 237 return RTEMS_RESOURCE_IN_USE; 238 } 239 240 if ( bsp_interrupt_is_handler_unique( index ) ) { 241 /* 242 * Cannot install another entry if there is already an unique entry 243 * installed. 244 */ 245 return RTEMS_RESOURCE_IN_USE; 246 } 247 248 other = bsp_interrupt_entry_find( 249 vector, 250 entry->handler, 251 entry->arg, 252 &previous_next 253 ); 254 255 if ( other != NULL ) { 256 /* 257 * Cannot install an entry which has the same routine and argument as an 258 * already installed entry. 259 */ 260 return RTEMS_TOO_MANY; 261 } 262 263 bsp_interrupt_entry_store_release( previous_next, entry ); 264 265 return RTEMS_SUCCESSFUL; 266 } 267 268 rtems_status_code rtems_interrupt_entry_install( 269 rtems_vector_number vector, 270 rtems_option options, 271 rtems_interrupt_entry *entry 189 272 ) 190 273 { 191 274 rtems_status_code sc; 192 rtems_interrupt_level level; 193 rtems_vector_number index = 0; 194 rtems_interrupt_entry *head = NULL; 195 bool enable_vector = false; 196 bool replace = RTEMS_INTERRUPT_IS_REPLACE(options); 197 198 sc = bsp_interrupt_check_and_lock( vector, handler ); 275 276 if ( entry == NULL ) { 277 return RTEMS_INVALID_ADDRESS; 278 } 279 280 sc = bsp_interrupt_check_and_lock( vector, entry->handler ); 199 281 200 282 if ( sc != RTEMS_SUCCESSFUL ) { … … 202 284 } 203 285 204 /* Get handler table index */ 205 index = bsp_interrupt_handler_index(vector); 206 207 /* Get head entry of the handler list for current vector */ 208 head = &bsp_interrupt_handler_table [index]; 209 210 if (bsp_interrupt_is_empty_handler_entry(head)) { 211 if (replace) { 212 /* No handler to replace exists */ 213 bsp_interrupt_unlock(); 214 return RTEMS_UNSATISFIED; 215 } 216 217 /* 218 * No real handler installed yet. So allocate a new index in 219 * the handler table and fill the entry with life. 220 */ 221 if (bsp_interrupt_allocate_handler_index(vector, &index)) { 222 bsp_interrupt_disable(level); 223 bsp_interrupt_handler_table [index].arg = arg; 224 bsp_interrupt_fence(ATOMIC_ORDER_RELEASE); 225 bsp_interrupt_handler_table [index].handler = handler; 226 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE 227 bsp_interrupt_handler_index_table [vector] = index; 228 #endif 229 bsp_interrupt_enable(level); 230 bsp_interrupt_handler_table [index].info = info; 231 } else { 232 /* Handler table is full */ 233 bsp_interrupt_unlock(); 234 return RTEMS_NO_MEMORY; 235 } 236 237 /* This is the first handler so enable the vector later */ 238 enable_vector = true; 239 } else { 240 rtems_interrupt_entry *current = head; 241 rtems_interrupt_entry *tail = NULL; 242 rtems_interrupt_entry *match = NULL; 243 244 /* Ensure that a unique handler remains unique */ 245 if ( 246 !replace 247 && (RTEMS_INTERRUPT_IS_UNIQUE(options) 248 || bsp_interrupt_is_handler_unique(index)) 249 ) { 250 /* 251 * Tried to install a unique handler on a not empty 252 * list or there is already a unique handler installed. 253 */ 254 bsp_interrupt_unlock(); 255 return RTEMS_RESOURCE_IN_USE; 256 } 257 258 /* 259 * Search for the list tail and check if the handler is already 260 * installed. 261 */ 262 do { 263 if ( 264 match == NULL 265 && (current->handler == handler || replace) 266 && current->arg == arg 267 ) { 268 match = current; 269 } 270 tail = current; 271 current = current->next; 272 } while (current != NULL); 273 274 if (replace) { 275 /* Ensure that a handler to replace exists */ 276 if (match == NULL) { 277 bsp_interrupt_unlock(); 278 return RTEMS_UNSATISFIED; 279 } 280 281 /* Use existing entry */ 282 current = match; 283 } else { 284 /* Ensure the handler is not already installed */ 285 if (match != NULL) { 286 /* The handler is already installed */ 287 bsp_interrupt_unlock(); 288 return RTEMS_TOO_MANY; 289 } 290 291 /* Allocate a new entry */ 292 current = rtems_malloc(sizeof(*current)); 293 if (current == NULL) { 294 /* Not enough memory */ 295 bsp_interrupt_unlock(); 296 return RTEMS_NO_MEMORY; 297 } 298 } 299 300 /* Update existing entry or set new entry */ 301 current->handler = handler; 302 current->info = info; 303 304 if (!replace) { 305 /* Set new entry */ 306 current->arg = arg; 307 current->next = NULL; 308 309 /* Link to list tail */ 310 bsp_interrupt_disable(level); 311 bsp_interrupt_fence(ATOMIC_ORDER_RELEASE); 312 tail->next = current; 313 bsp_interrupt_enable(level); 314 } 315 } 316 317 /* Make the handler unique if necessary */ 318 bsp_interrupt_set_handler_unique(index, RTEMS_INTERRUPT_IS_UNIQUE(options)); 319 320 /* Enable the vector if necessary */ 321 if (enable_vector) { 322 bsp_interrupt_vector_enable(vector); 323 } 324 325 /* Unlock */ 286 sc = bsp_interrupt_entry_install( vector, options, entry ); 326 287 bsp_interrupt_unlock(); 327 288 328 return RTEMS_SUCCESSFUL; 329 } 330 331 /** 332 * @brief Removes an interrupt handler. 333 * 334 * @ingroup bsp_interrupt 335 * 336 * @return In addition to the standard status codes this function returns 337 * RTEMS_INTERNAL_ERROR if the BSP interrupt support is not initialized. 338 * 339 * @see rtems_interrupt_handler_remove(). 340 */ 341 static rtems_status_code bsp_interrupt_handler_remove( 342 rtems_vector_number vector, 343 rtems_interrupt_handler handler, 344 void *arg 345 ) 346 { 347 rtems_status_code sc; 348 rtems_interrupt_level level; 349 rtems_vector_number index = 0; 350 rtems_interrupt_entry *head = NULL; 351 rtems_interrupt_entry *current = NULL; 352 rtems_interrupt_entry *previous = NULL; 353 rtems_interrupt_entry *match = NULL; 354 355 sc = bsp_interrupt_check_and_lock( vector, handler ); 356 357 if ( sc != RTEMS_SUCCESSFUL ) { 358 return sc; 359 } 360 361 /* Get handler table index */ 362 index = bsp_interrupt_handler_index(vector); 363 364 /* Get head entry of the handler list for current vector */ 365 head = &bsp_interrupt_handler_table [index]; 366 367 /* Search for a matching entry */ 368 current = head; 369 do { 370 if (current->handler == handler && current->arg == arg) { 371 match = current; 372 break; 373 } 374 previous = current; 375 current = current->next; 376 } while (current != NULL); 377 378 /* Remove the matching entry */ 379 if (match != NULL) { 380 if (match->next != NULL) { 381 /* 382 * The match has a successor. A successor is always 383 * allocated. So replace the match with its successor 384 * and free the successor entry. 385 */ 386 current = match->next; 387 388 bsp_interrupt_disable(level); 389 #ifdef RTEMS_SMP 390 match->handler = bsp_interrupt_handler_do_nothing; 391 bsp_interrupt_fence(ATOMIC_ORDER_RELEASE); 392 #endif 393 match->arg = current->arg; 394 bsp_interrupt_fence(ATOMIC_ORDER_RELEASE); 395 match->handler = current->handler; 396 match->info = current->info; 397 match->next = current->next; 398 bsp_interrupt_enable(level); 399 400 free(current); 401 } else if (match == head) { 402 /* 403 * The match is the list head and has no successor. 404 * The list head is stored in a static table so clear 405 * this entry. Since now the list is empty disable the 406 * vector. 407 */ 408 409 /* Disable the vector */ 410 bsp_interrupt_vector_disable(vector); 411 412 /* Clear entry */ 413 bsp_interrupt_disable(level); 414 bsp_interrupt_clear_handler_entry(head, vector); 415 #ifdef BSP_INTERRUPT_USE_INDEX_TABLE 416 bsp_interrupt_handler_index_table [vector] = 0; 417 #endif 418 bsp_interrupt_enable(level); 419 420 /* Allow shared handlers */ 421 bsp_interrupt_set_handler_unique(index, false); 422 } else { 423 /* 424 * The match is the list tail and has a predecessor. 425 * So terminate the predecessor and free the match. 426 */ 427 bsp_interrupt_disable(level); 428 previous->next = NULL; 429 bsp_interrupt_fence(ATOMIC_ORDER_RELEASE); 430 bsp_interrupt_enable(level); 431 432 free(match); 433 } 434 } else { 435 /* No matching entry found */ 436 bsp_interrupt_unlock(); 437 return RTEMS_UNSATISFIED; 438 } 439 440 /* Unlock */ 441 bsp_interrupt_unlock(); 442 443 return RTEMS_SUCCESSFUL; 444 } 445 446 rtems_status_code rtems_interrupt_handler_install( 447 rtems_vector_number vector, 448 const char *info, 449 rtems_option options, 450 rtems_interrupt_handler handler, 451 void *arg 452 ) 453 { 454 return bsp_interrupt_handler_install(vector, info, options, handler, arg); 455 } 456 457 rtems_status_code rtems_interrupt_handler_remove( 458 rtems_vector_number vector, 459 rtems_interrupt_handler handler, 460 void *arg 461 ) 462 { 463 return bsp_interrupt_handler_remove(vector, handler, arg); 464 } 289 return sc; 290 } -
bsps/shared/irq/irq-handler-iterate.c
r70357f1 re518323 11 11 12 12 /* 13 * Copyright (C) 2017 embedded brains GmbH (http://www.embedded-brains.de)13 * Copyright (C) 2017, 2021 embedded brains GmbH (http://www.embedded-brains.de) 14 14 * 15 15 * Redistribution and use in source and binary forms, with or without … … 46 46 rtems_vector_number index; 47 47 rtems_option options; 48 rtems_interrupt_entry * current;48 rtems_interrupt_entry *entry; 49 49 50 50 sc = bsp_interrupt_check_and_lock( … … 57 57 } 58 58 59 index = bsp_interrupt_handler_index(vector); 60 current = &bsp_interrupt_handler_table [index]; 61 if (!bsp_interrupt_is_empty_handler_entry(current)) { 62 do { 63 options = bsp_interrupt_is_handler_unique(index) ? 64 RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED; 65 routine(arg, current->info, options, current->handler, current->arg); 66 current = current->next; 67 } while (current != NULL); 59 index = bsp_interrupt_handler_index( vector ); 60 options = bsp_interrupt_is_handler_unique( index ) ? 61 RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED; 62 entry = bsp_interrupt_handler_table[ index ]; 63 64 while ( entry != NULL ) { 65 ( *routine )( arg, entry->info, options, entry->handler, entry->arg ); 66 entry = entry->next; 68 67 } 69 68 -
c/src/lib/libbsp/m68k/genmcf548x/Makefile.am
r70357f1 re518323 39 39 40 40 # IRQ 41 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-affinity.c42 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c43 41 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c 44 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c45 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c46 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c47 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-legacy.c48 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c49 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-server.c50 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-shell.c51 42 librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/irq.c 52 43 librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/intc-icr-init-values.c … … 60 51 librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/start/cache.c 61 52 53 include $(srcdir)/../../../../../../bsps/shared/irq-sources.am 62 54 include $(srcdir)/../../../../../../bsps/shared/shared-sources.am 63 55 include $(srcdir)/../../../../../../bsps/m68k/genmcf548x/headers.am -
c/src/lib/libbsp/powerpc/ss555/Makefile.am
r70357f1 re518323 52 52 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c 53 53 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c 54 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c 54 55 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c 56 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c 55 57 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c 58 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c 56 59 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c 57 60 librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c -
spec/build/bsps/m68k/genmcf548x/grp.yml
r70357f1 re518323 29 29 uid: ../../obj 30 30 - role: build-dependency 31 uid: ../../objirq 32 - role: build-dependency 31 33 uid: ../../optconsolebaud 32 34 - role: build-dependency -
spec/build/bsps/m68k/genmcf548x/obj.yml
r70357f1 re518323 39 39 - bsps/m68k/shared/memProbe.c 40 40 - bsps/shared/dev/getentropy/getentropy-cpucounter.c 41 - bsps/shared/irq/irq-affinity.c42 - bsps/shared/irq/irq-raise-clear.c43 41 - bsps/shared/irq/irq-default-handler.c 44 - bsps/shared/irq/irq-enable-disable.c45 - bsps/shared/irq/irq-handler-iterate.c46 - bsps/shared/irq/irq-info.c47 - bsps/shared/irq/irq-legacy.c48 - bsps/shared/irq/irq-lock.c49 - bsps/shared/irq/irq-server.c50 - bsps/shared/irq/irq-shell.c51 42 - bsps/shared/start/bspfatal-default.c 52 43 - bsps/shared/start/bspgetworkarea-default.c -
spec/build/bsps/objirq.yml
r70357f1 re518323 14 14 - bsps/shared/irq/irq-raise-clear.c 15 15 - bsps/shared/irq/irq-enable-disable.c 16 - bsps/shared/irq/irq-entry-remove.c 16 17 - bsps/shared/irq/irq-generic.c 18 - bsps/shared/irq/irq-handler-install.c 17 19 - bsps/shared/irq/irq-handler-iterate.c 20 - bsps/shared/irq/irq-handler-remove.c 18 21 - bsps/shared/irq/irq-info.c 19 22 - bsps/shared/irq/irq-legacy.c -
spec/build/bsps/powerpc/ss555/bspss555.yml
r70357f1 re518323 73 73 - bsps/shared/irq/irq-default.c 74 74 - bsps/shared/irq/irq-enable-disable.c 75 - bsps/shared/irq/irq-entry-remove.c 75 76 - bsps/shared/irq/irq-generic.c 77 - bsps/shared/irq/irq-handler-install.c 76 78 - bsps/shared/irq/irq-handler-iterate.c 79 - bsps/shared/irq/irq-handler-remove.c 77 80 - bsps/shared/irq/irq-info.c 78 81 - bsps/shared/irq/irq-lock.c
Note: See TracChangeset
for help on using the changeset viewer.