diff --git a/bsps/sparc/leon3/include/bsp/irq.h b/bsps/sparc/leon3/include/bsp/irq.h index 3b8ce260ec..7b0617a27f 100644 --- a/bsps/sparc/leon3/include/bsp/irq.h +++ b/bsps/sparc/leon3/include/bsp/irq.h @@ -42,10 +42,19 @@ #define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */ #define BSP_INTERRUPT_VECTOR_MAX_EXT 31 /* Extended IRQ controller */ -#define BSP_INTERRUPT_VECTOR_MAX_MAP \ - 63 /* Extended IRQ controller with mapping registers */ +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 +/* + * A bus line is an interrupt line of the system interrupt bus. A controller + * line is an interrupt line of the IRQ(A)MP. With an interrupt map, an + * interrupt vector is a bus line. The dispatch table has one entry for each + * controller line. + */ +#define BSP_INTERRUPT_VECTOR_COUNT LEON3_IRQMAP_BUS_LINE_COUNT +#define BSP_INTERRUPT_DISPATCH_TABLE_SIZE ( BSP_INTERRUPT_VECTOR_MAX_EXT + 1 ) +#else #define BSP_INTERRUPT_VECTOR_COUNT ( BSP_INTERRUPT_VECTOR_MAX_EXT + 1 ) +#endif /* The check is different depending on IRQ controller, runtime detected */ #define BSP_INTERRUPT_CUSTOM_VALID_VECTOR @@ -97,9 +106,8 @@ rtems_status_code leon3_irqmap_get( rtems_vector_number *controller_line ); -#ifdef LEON3_IRQAMP_IRQMAP -extern rtems_vector_number - LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_MAX_MAP + 1 ]; +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 +extern uint8_t LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_COUNT ]; #define bsp_interrupt_vector_modify( v ) LEON3_IrqCtrl_Mapping[ ( v ) ] #endif diff --git a/bsps/sparc/leon3/include/bsp/irqimpl.h b/bsps/sparc/leon3/include/bsp/irqimpl.h index 362caf7d7e..af39705814 100644 --- a/bsps/sparc/leon3/include/bsp/irqimpl.h +++ b/bsps/sparc/leon3/include/bsp/irqimpl.h @@ -159,7 +159,7 @@ static inline rtems_vector_number leon3_irqmap_get_unchecked( rtems_vector_number bus_line ) { -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 return LEON3_IrqCtrl_Mapping[ bus_line ]; #else return bus_line; diff --git a/bsps/sparc/leon3/start/bspsmp.c b/bsps/sparc/leon3/start/bspsmp.c index 29d194b86d..91358ac903 100644 --- a/bsps/sparc/leon3/start/bspsmp.c +++ b/bsps/sparc/leon3/start/bspsmp.c @@ -114,7 +114,7 @@ void _CPU_SMP_Send_interrupt( uint32_t target_processor_index ) /* send interrupt to destination CPU */ grlib_store_32( &LEON3_IrqCtrl_Regs->piforce[ target_processor_index ], -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 1U << leon3_irqmap_get_unchecked( LEON3_mp_irq ) #else 1U << LEON3_mp_irq diff --git a/bsps/sparc/leon3/start/eirq.c b/bsps/sparc/leon3/start/eirq.c index ba20e8f418..2359b766d4 100644 --- a/bsps/sparc/leon3/start/eirq.c +++ b/bsps/sparc/leon3/start/eirq.c @@ -49,9 +49,20 @@ uint32_t LEON3_IrqCtrl_EIrq; #endif -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 /* Mapping from bus interrupt lines to IRQ(A)MP interrupt lines */ -rtems_vector_number LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_MAX_MAP + 1 ]; +uint8_t LEON3_IrqCtrl_Mapping[ BSP_INTERRUPT_VECTOR_COUNT ]; + +/* + * A map field is eight bits wide. A field value outside the dispatch table is + * a hardware fault. The mask keeps the controller line inside the dispatch + * table also in this case. + */ +static uint8_t leon3_irqmap_controller_line( uint32_t field ) +{ + return (uint8_t) ( field & ( BSP_INTERRUPT_DISPATCH_TABLE_SIZE - 1 ) ); +} + #endif rtems_status_code leon3_irqmap_get( @@ -63,11 +74,7 @@ rtems_status_code leon3_irqmap_get( return RTEMS_INVALID_ADDRESS; } -#ifdef LEON3_IRQAMP_IRQMAP - if ( bus_line > BSP_INTERRUPT_VECTOR_MAX_MAP ) { -#else if ( bus_line >= BSP_INTERRUPT_VECTOR_COUNT ) { -#endif *controller_line = UINT32_MAX; return RTEMS_INVALID_NUMBER; } @@ -91,25 +98,25 @@ void leon3_ext_irq_init( irqamp *regs ) grlib_load_32( ®s->mpstat ) ); #endif -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 for ( - rtems_vector_number bus_line = 0; bus_line <= BSP_INTERRUPT_VECTOR_MAX_MAP; + rtems_vector_number bus_line = 0; bus_line < BSP_INTERRUPT_VECTOR_COUNT; bus_line += 4 ) { uint32_t n = bus_line / 4; uint32_t irqmap_n = grlib_load_32( &LEON3_IrqCtrl_Regs->irqmap[ n ] ); - LEON3_IrqCtrl_Mapping[ bus_line + 0 ] = IRQAMP_IRQMAP_IRQMAP_4_N_0_GET( - irqmap_n + LEON3_IrqCtrl_Mapping[ bus_line + 0 ] = leon3_irqmap_controller_line( + IRQAMP_IRQMAP_IRQMAP_4_N_0_GET( irqmap_n ) ); - LEON3_IrqCtrl_Mapping[ bus_line + 1 ] = IRQAMP_IRQMAP_IRQMAP_4_N_1_GET( - irqmap_n + LEON3_IrqCtrl_Mapping[ bus_line + 1 ] = leon3_irqmap_controller_line( + IRQAMP_IRQMAP_IRQMAP_4_N_1_GET( irqmap_n ) ); - LEON3_IrqCtrl_Mapping[ bus_line + 2 ] = IRQAMP_IRQMAP_IRQMAP_4_N_2_GET( - irqmap_n + LEON3_IrqCtrl_Mapping[ bus_line + 2 ] = leon3_irqmap_controller_line( + IRQAMP_IRQMAP_IRQMAP_4_N_2_GET( irqmap_n ) ); - LEON3_IrqCtrl_Mapping[ bus_line + 3 ] = IRQAMP_IRQMAP_IRQMAP_4_N_3_GET( - irqmap_n + LEON3_IrqCtrl_Mapping[ bus_line + 3 ] = leon3_irqmap_controller_line( + IRQAMP_IRQMAP_IRQMAP_4_N_3_GET( irqmap_n ) ); } #endif @@ -121,8 +128,9 @@ bool bsp_interrupt_is_valid_vector( rtems_vector_number vector ) return false; } -#if defined( LEON3_IRQAMP_IRQMAP ) - return vector <= BSP_INTERRUPT_VECTOR_MAX_MAP; +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 + return vector < BSP_INTERRUPT_VECTOR_COUNT && + leon3_irqmap_get_unchecked( vector ) != 0; #elif defined( LEON3_IRQAMP_EXTENDED_INTERRUPT ) return vector <= BSP_INTERRUPT_VECTOR_MAX_EXT; #else @@ -184,7 +192,7 @@ rtems_status_code bsp_interrupt_get_attributes( bool is_standard_interrupt; bool is_maskable; -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -216,7 +224,7 @@ rtems_status_code bsp_interrupt_is_pending( bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); bsp_interrupt_assert( pending != NULL ); -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -242,7 +250,7 @@ rtems_status_code bsp_interrupt_raise( rtems_vector_number vector ) bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -272,7 +280,7 @@ rtems_status_code bsp_interrupt_raise_on( bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); bsp_interrupt_assert( cpu_index < rtems_scheduler_get_processor_maximum() ); -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -293,7 +301,7 @@ rtems_status_code bsp_interrupt_clear( rtems_vector_number vector ) bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -323,7 +331,7 @@ rtems_status_code bsp_interrupt_vector_is_enabled( bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -345,7 +353,7 @@ static void leon3_interrupt_vector_enable( rtems_vector_number vector ) uint32_t brdcst; irqamp *regs; -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -399,7 +407,7 @@ rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector ) bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -435,7 +443,7 @@ rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector ) bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) ); -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 vector = leon3_irqmap_get_unchecked( vector ); #endif @@ -508,7 +516,7 @@ rtems_status_code bsp_interrupt_set_affinity( uint32_t bit; irqamp *regs; -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 rtems_vector_number irq_vector; if ( leon3_irqmap_get( vector, &irq_vector ) != RTEMS_SUCCESSFUL ) { @@ -549,7 +557,7 @@ rtems_status_code bsp_interrupt_get_affinity( Processor_mask *affinity ) { -#ifdef LEON3_IRQAMP_IRQMAP +#if LEON3_IRQMAP_BUS_LINE_COUNT != 0 rtems_vector_number irq_vector; if ( leon3_irqmap_get( vector, &irq_vector ) != RTEMS_SUCCESSFUL ) { diff --git a/spec/build/bsps/sparc/leon3/grp.yml b/spec/build/bsps/sparc/leon3/grp.yml index e390a87653..acaf3680a5 100644 --- a/spec/build/bsps/sparc/leon3/grp.yml +++ b/spec/build/bsps/sparc/leon3/grp.yml @@ -47,7 +47,7 @@ links: - role: build-dependency uid: optirqampextirq - role: build-dependency - uid: optirqampirqmap + uid: optirqmapbuslinecount - role: build-dependency uid: optirqampts - role: build-dependency diff --git a/spec/build/bsps/sparc/leon3/optirqampextirq.yml b/spec/build/bsps/sparc/leon3/optirqampextirq.yml index a8defbf606..1819d26711 100644 --- a/spec/build/bsps/sparc/leon3/optirqampextirq.yml +++ b/spec/build/bsps/sparc/leon3/optirqampextirq.yml @@ -17,5 +17,6 @@ format: '{}' links: [] name: LEON3_IRQAMP_EXTENDED_INTERRUPT description: | - This option specifies the interrupt line of the IRQ(A)MP extended interrupt. + This option specifies the controller line of the IRQ(A)MP extended + interrupt. type: build diff --git a/spec/build/bsps/sparc/leon3/optirqampirqmap.yml b/spec/build/bsps/sparc/leon3/optirqampirqmap.yml deleted file mode 100644 index 855b8f1702..0000000000 --- a/spec/build/bsps/sparc/leon3/optirqampirqmap.yml +++ /dev/null @@ -1,20 +0,0 @@ -SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause -copyrights: -- Copyright (C) 2026 Frontgrade Gaisler -actions: -- get-boolean: null -- define-condition: null -build-type: option -default: -- enabled-by: - - sparc/gr740 - - sparc/gr765 - value: true -- enabled-by: true - value: false -enabled-by: true -links: [] -name: LEON3_IRQAMP_IRQMAP -description: | - This option specifies if the IRQ(A)MP interrupt (re-)map registers are available. -type: build diff --git a/spec/build/bsps/sparc/leon3/optirqmapbuslinecount.yml b/spec/build/bsps/sparc/leon3/optirqmapbuslinecount.yml new file mode 100644 index 0000000000..bea165825f --- /dev/null +++ b/spec/build/bsps/sparc/leon3/optirqmapbuslinecount.yml @@ -0,0 +1,28 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +actions: +- get-integer: null +- assert-in-set: + - 0 + - 32 + - 64 +- format-and-define: null +build-type: option +copyrights: +- Copyright (C) 2026 Frontgrade Gaisler +- Copyright (C) 2026 embedded brains GmbH & Co. KG +default: +- enabled-by: sparc/gr740 + value: 32 +- enabled-by: sparc/gr765 + value: 64 +- enabled-by: true + value: 0 +description: | + This option defines the count of bus lines of the IRQ(A)MP interrupt map. + The GR740 has 32 bus lines, and the GR765 has 64. A value of zero specifies + that the BSP uses no interrupt map. +enabled-by: true +format: '{}' +links: [] +name: LEON3_IRQMAP_BUS_LINE_COUNT +type: build diff --git a/testsuites/validation/bsps/tc-sparc-leon3-ext-irq-raise.c b/testsuites/validation/bsps/tc-sparc-leon3-ext-irq-raise.c index 9b64f9c2b3..d434d4528b 100644 --- a/testsuites/validation/bsps/tc-sparc-leon3-ext-irq-raise.c +++ b/testsuites/validation/bsps/tc-sparc-leon3-ext-irq-raise.c @@ -8,6 +8,7 @@ /* * Copyright (C) 2026 Critical Software S.A + * Copyright (C) 2026 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,9 +40,7 @@ #include #include #include - #include - #include #include "tx-support.h" @@ -57,142 +56,205 @@ * @brief This test case validates the extended interrupt raise path for LEON3 * BSPs. * + * The test raises an extended controller line through a read-modify-write of + * the pending register. This is safe only in the test, since no peripheral + * drives the tested bus lines. + * * This test case performs the following actions: * - * - Iterate through each testable extended interrupt vector (16 to 31). + * - Iterate through each interrupt vector whose bus line maps to an extended + * controller line and which has no interrupt handler installed. Get the + * attributes of the vector and try to raise it through the directive. + * Install an interrupt handler, enable the vector, raise the extended + * controller line through the pending register and wait for the handler. + * Clear and disable the vector and remove the handler. * - * - Check that API raise operations are not available for extended vectors. + * - Check that the test exercised each extended controller line. * - * - Check that rtems_interrupt_raise() returns RTEMS_UNSATISFIED and does - * not alter the pending state. + * - Check that the attributes of each tested interrupt vector state that the + * vector can be enabled, disabled and cleared, and that it can neither be + * raised nor be raised on a processor. * - * - Raise the vector using an unsafe test-only support operation. + * - Check that the directive rejected the raise of each tested interrupt + * vector and that the pending state stayed unchanged. * - * - Check that the interrupt handler installed for the vector is called. + * - Check that the pending extended controller line called the interrupt + * handler of each tested interrupt vector exactly once. * * @{ */ +/** + * @brief Test context for spec:/bsp/sparc/leon3/val/ext-irq-raise test case. + */ typedef struct { - volatile uint32_t call_count; + /** + * @brief This member contains the count of tested interrupt vectors. + */ + uint32_t tested_vectors; + + /** + * @brief This member contains the set of the tested controller lines. + */ + uint32_t tested_controller_lines; + + /** + * @brief This member contains the count of tested interrupt vectors which + * the BSP reported as not raisable. + */ + uint32_t not_raisable; + + /** + * @brief This member contains the count of tested interrupt vectors whose + * raise the directive rejected. + */ + uint32_t raise_rejected; + + /** + * @brief This member contains the count of tested interrupt vectors whose + * interrupt handler the BSP dispatched. + */ + uint32_t dispatched; + + /** + * @brief This member contains the call count of the interrupt handler. + */ + volatile uint32_t call_count; + + /** + * @brief This member contains the interrupt vector which the test expects. + */ rtems_vector_number expected_vector; + + /** + * @brief This member contains the interrupt vector which the handler saw. + */ rtems_vector_number handled_vector; } BspSparcLeon3ValExtIrqRaise_Context; -static void BspSparcLeon3ValExtIrqRaise_Handler( void *arg ) +static BspSparcLeon3ValExtIrqRaise_Context + BspSparcLeon3ValExtIrqRaise_Instance; + +typedef BspSparcLeon3ValExtIrqRaise_Context Context; + +static void Handler( void *arg ) { - BspSparcLeon3ValExtIrqRaise_Context *ctx; + Context *ctx; ctx = arg; ctx->handled_vector = ctx->expected_vector; ++ctx->call_count; } -static rtems_status_code UnsafeRaiseExtendedInterrupt( - rtems_vector_number vector -) +static void UnsafeRaiseExtendedInterrupt( rtems_vector_number controller_line ) { rtems_interrupt_lock_context lock_context; - uint32_t bit; uint32_t ipend; irqamp *regs; regs = LEON3_IrqCtrl_Regs; - bit = 1U << vector; - - /* - * This deliberately uses an unsafe read-modify-write sequence to exercise - * the extended interrupt raise path in BSP-specific validation tests. - */ LEON3_IRQCTRL_ACQUIRE( &lock_context ); ipend = grlib_load_32( ®s->ipend ); - ipend |= bit; + ipend |= 1U << controller_line; grlib_store_32( ®s->ipend, ipend ); LEON3_IRQCTRL_RELEASE( &lock_context ); - - return RTEMS_SUCCESSFUL; } +static T_fixture BspSparcLeon3ValExtIrqRaise_Fixture = { + .setup = NULL, + .stop = NULL, + .teardown = NULL, + .scope = NULL, + .initial_context = &BspSparcLeon3ValExtIrqRaise_Instance +}; + /** - * @fn void T_case_body_BspSparcLeon3ValExtIrqRaise( void ) + * @brief Iterate through each interrupt vector whose bus line maps to an + * extended controller line and which has no interrupt handler installed. + * Get the attributes of the vector and try to raise it through the + * directive. Install an interrupt handler, enable the vector, raise the + * extended controller line through the pending register and wait for the + * handler. Clear and disable the vector and remove the handler. */ -T_TEST_CASE( BspSparcLeon3ValExtIrqRaise ) +static void BspSparcLeon3ValExtIrqRaise_Action_0( + BspSparcLeon3ValExtIrqRaise_Context *ctx +) { rtems_vector_number vector; - uint32_t tested_vectors = 0; - for ( - vector = BSP_INTERRUPT_VECTOR_MAX_STD + 1; - vector < BSP_INTERRUPT_VECTOR_COUNT; - ++vector - ) { - rtems_status_code sc; - rtems_interrupt_attributes attr; - bool pending_before; - bool pending_after; - rtems_interrupt_entry entry; - BspSparcLeon3ValExtIrqRaise_Context ctx; + for ( vector = 0; vector < BSP_INTERRUPT_VECTOR_COUNT; ++vector ) { + rtems_vector_number controller_line; + rtems_status_code sc; + rtems_interrupt_attributes attr; + bool pending_before; + bool pending_after; + rtems_interrupt_entry entry; if ( !bsp_interrupt_is_valid_vector( vector ) ) { continue; } + controller_line = leon3_irqmap_get_unchecked( vector ); + + if ( controller_line <= BSP_INTERRUPT_VECTOR_MAX_STD ) { + continue; + } + if ( HasInterruptVectorEntriesInstalled( vector ) ) { continue; } + ++ctx->tested_vectors; + ctx->tested_controller_lines |= 1U << controller_line; + attr = (rtems_interrupt_attributes) { 0 }; sc = rtems_interrupt_get_attributes( vector, &attr ); T_rsc_success( sc ); - T_false( attr.can_raise ); - T_false( attr.can_raise_on ); - T_true( attr.can_enable ); - T_true( attr.can_disable ); - T_true( attr.can_clear ); + if ( + !attr.can_raise && !attr.can_raise_on && attr.can_enable && + attr.can_disable && attr.can_clear + ) { + ++ctx->not_raisable; + } pending_before = true; sc = rtems_interrupt_is_pending( vector, &pending_before ); T_rsc_success( sc ); - /* The API must reject software raises of extended interrupt vectors. */ sc = rtems_interrupt_raise( vector ); - T_rsc( sc, RTEMS_UNSATISFIED ); pending_after = !pending_before; - sc = rtems_interrupt_is_pending( vector, &pending_after ); - T_rsc_success( sc ); - T_eq( pending_after, pending_before ); + (void) rtems_interrupt_is_pending( vector, &pending_after ); - ctx.call_count = 0; - ctx.expected_vector = vector; - ctx.handled_vector = UINT32_MAX; + if ( sc == RTEMS_UNSATISFIED && pending_after == pending_before ) { + ++ctx->raise_rejected; + } - rtems_interrupt_entry_initialize( - &entry, - BspSparcLeon3ValExtIrqRaise_Handler, - &ctx, - "Extended IRQ" + ctx->call_count = 0; + ctx->handled_vector = UINT32_MAX; + ctx->expected_vector = vector; + + rtems_interrupt_entry_initialize( &entry, Handler, ctx, "Extended IRQ" ); + sc = rtems_interrupt_entry_install( + vector, + RTEMS_INTERRUPT_UNIQUE, + &entry ); - - sc = rtems_interrupt_entry_install( vector, RTEMS_INTERRUPT_UNIQUE, &entry ); T_rsc_success( sc ); sc = rtems_interrupt_vector_enable( vector ); T_rsc_success( sc ); - /* - * Raise the extended interrupt vector using the unsafe test-only - * support operation. - */ - sc = UnsafeRaiseExtendedInterrupt( vector ); - T_rsc_success( sc ); + UnsafeRaiseExtendedInterrupt( controller_line ); - while ( ctx.call_count == 0 ) { + while ( ctx->call_count == 0 ) { /* Wait */ } - T_eq_u32( ctx.handled_vector, vector ); + if ( ctx->call_count == 1 && ctx->handled_vector == vector ) { + ++ctx->dispatched; + } sc = rtems_interrupt_clear( vector ); T_rsc_success( sc ); @@ -202,20 +264,46 @@ T_TEST_CASE( BspSparcLeon3ValExtIrqRaise ) sc = rtems_interrupt_entry_remove( vector, &entry ); T_rsc_success( sc ); - - pending_after = true; - sc = rtems_interrupt_is_pending( vector, &pending_after ); - T_rsc_success( sc ); - T_false( pending_after ); - - ++tested_vectors; } - /* Ensure that all extended vectors were effectively exercised. */ - T_eq( - tested_vectors, - BSP_INTERRUPT_VECTOR_MAX_EXT - BSP_INTERRUPT_VECTOR_MAX_STD - ); + /* + * Check that the test exercised each extended controller line. + */ + T_eq_u32( ctx->tested_controller_lines, 0xffff0000 ); + + /* + * Check that the attributes of each tested interrupt vector state that the + * vector can be enabled, disabled and cleared, and that it can neither be + * raised nor be raised on a processor. + */ + T_eq_u32( ctx->not_raisable, ctx->tested_vectors ); + + /* + * Check that the directive rejected the raise of each tested interrupt + * vector and that the pending state stayed unchanged. + */ + T_eq_u32( ctx->raise_rejected, ctx->tested_vectors ); + + /* + * Check that the pending extended controller line called the interrupt + * handler of each tested interrupt vector exactly once. + */ + T_eq_u32( ctx->dispatched, ctx->tested_vectors ); +} + +/** + * @fn void T_case_body_BspSparcLeon3ValExtIrqRaise( void ) + */ +T_TEST_CASE_FIXTURE( + BspSparcLeon3ValExtIrqRaise, + &BspSparcLeon3ValExtIrqRaise_Fixture +) +{ + BspSparcLeon3ValExtIrqRaise_Context *ctx; + + ctx = T_fixture_context(); + + BspSparcLeon3ValExtIrqRaise_Action_0( ctx ); } /** @} */