validation: Improve spurious interrupt test case

Use the tm27 support to test a spurious interrupt.  This helps to run the
validation test case on targets which have no software interrupt available for
tests (for example riscv/PLIC/CLINT in the SMP configuration).
This commit is contained in:
Sebastian Huber
2022-11-11 16:30:09 +01:00
parent 908ffc7a93
commit 55318d17b4
3 changed files with 76 additions and 29 deletions

View File

@@ -109,6 +109,12 @@ typedef struct {
* @brief Test context for spec:/bsp/req/interrupt-spurious test case. * @brief Test context for spec:/bsp/req/interrupt-spurious test case.
*/ */
typedef struct { typedef struct {
/**
* @brief This member references the interrupt entry to restore during test
* case teardown.
*/
rtems_interrupt_entry *entry_to_restore;
/** /**
* @brief This member provides a jump buffer to return from the fatal error. * @brief This member provides a jump buffer to return from the fatal error.
*/ */
@@ -119,11 +125,6 @@ typedef struct {
*/ */
rtems_interrupt_entry entry; rtems_interrupt_entry entry;
/**
* @brief If this member is true, then the interrupt shall be cleared.
*/
bool do_clear;
/** /**
* @brief This member is true, then an interrupt occurred. * @brief This member is true, then an interrupt occurred.
*/ */
@@ -234,14 +235,7 @@ static void Disable( const Context *ctx )
static void ProcessInterrupt( Context *ctx ) static void ProcessInterrupt( Context *ctx )
{ {
ctx->interrupt_occurred = true; ctx->interrupt_occurred = true;
CallWithinISRClear();
if ( ctx->do_clear ) {
rtems_status_code sc;
sc = rtems_interrupt_clear( ctx->test_vector );
T_rsc_success( sc );
}
Disable( ctx ); Disable( ctx );
} }
@@ -424,20 +418,15 @@ static void BspReqInterruptSpurious_Setup(
BspReqInterruptSpurious_Context *ctx BspReqInterruptSpurious_Context *ctx
) )
{ {
rtems_interrupt_attributes attr = {
.can_raise = true
};
rtems_status_code sc; rtems_status_code sc;
ctx->test_vector = GetTestableInterruptVector( &attr ); ctx->first = NULL;
ctx->test_vector = CallWithinISRGetVector();
T_assert_lt_u32( ctx->test_vector, BSP_INTERRUPT_VECTOR_COUNT ); T_assert_lt_u32( ctx->test_vector, BSP_INTERRUPT_VECTOR_COUNT );
ctx->first = &bsp_interrupt_handler_table[ ctx->first = &bsp_interrupt_handler_table[
bsp_interrupt_handler_index( ctx->test_vector ) bsp_interrupt_handler_index( ctx->test_vector )
]; ];
ctx->entry_to_restore = *ctx->first;
sc = rtems_interrupt_get_attributes( ctx->test_vector, &attr );
T_rsc_success( sc );
ctx->do_clear = attr.can_clear && !attr.cleared_by_acknowledge;
rtems_interrupt_entry_initialize( &ctx->entry, EntryRoutine, ctx, "Info" ); rtems_interrupt_entry_initialize( &ctx->entry, EntryRoutine, ctx, "Info" );
test_case_active = true; test_case_active = true;
@@ -459,6 +448,10 @@ static void BspReqInterruptSpurious_Teardown(
{ {
SetFatalHandler( NULL, NULL ); SetFatalHandler( NULL, NULL );
test_case_active = false; test_case_active = false;
if ( ctx->first != NULL ) {
*ctx->first = ctx->entry_to_restore;
}
} }
static void BspReqInterruptSpurious_Teardown_Wrap( void *arg ) static void BspReqInterruptSpurious_Teardown_Wrap( void *arg )
@@ -487,12 +480,9 @@ static void BspReqInterruptSpurious_Action(
} else } else
#endif #endif
{ {
rtems_status_code sc;
(void) rtems_interrupt_vector_enable( ctx->test_vector ); (void) rtems_interrupt_vector_enable( ctx->test_vector );
sc = rtems_interrupt_raise( ctx->test_vector ); CallWithinISRRaise();
T_rsc_success( sc );
while ( !ctx->interrupt_occurred ) { while ( !ctx->interrupt_occurred ) {
/* Wait */ /* Wait */

View File

@@ -5,12 +5,13 @@
* *
* @ingroup RTEMSTestSuites * @ingroup RTEMSTestSuites
* *
* @brief This source file contains the implementation of CallWithinISR(), * @brief This source file contains the implementation of CallWithinISRClear(),
* CallWithinISRGetVector(), CallWithinISR(), CallWithinISRRaise(),
* CallWithinISRSubmit(), and CallWithinISRWait(). * CallWithinISRSubmit(), and CallWithinISRWait().
*/ */
/* /*
* Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) * Copyright (C) 2021, 2022 embedded brains GmbH
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -44,6 +45,7 @@
#include <rtems/score/chainimpl.h> #include <rtems/score/chainimpl.h>
#include <bsp.h> #include <bsp.h>
#include <bsp/irq-generic.h>
/* Some target architectures need this variable for <tm27.h> */ /* Some target architectures need this variable for <tm27.h> */
uint32_t Interrupt_nest; uint32_t Interrupt_nest;
@@ -64,6 +66,16 @@ static CallWithinISRContext CallWithinISRInstance = {
.pending = CHAIN_INITIALIZER_EMPTY( CallWithinISRInstance.pending ) .pending = CHAIN_INITIALIZER_EMPTY( CallWithinISRInstance.pending )
}; };
void CallWithinISRRaise( void )
{
Cause_tm27_intr();
}
void CallWithinISRClear( void )
{
Clear_tm27_intr();
}
static void CallWithinISRHandler( rtems_vector_number vector ) static void CallWithinISRHandler( rtems_vector_number vector )
{ {
CallWithinISRContext *ctx; CallWithinISRContext *ctx;
@@ -71,7 +83,7 @@ static void CallWithinISRHandler( rtems_vector_number vector )
(void) vector; (void) vector;
ctx = &CallWithinISRInstance; ctx = &CallWithinISRInstance;
Clear_tm27_intr(); CallWithinISRClear();
while ( true ) { while ( true ) {
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
@@ -114,7 +126,7 @@ void CallWithinISRSubmit( CallWithinISRRequest *request )
_Chain_Append_unprotected( &ctx->pending, &request->node ); _Chain_Append_unprotected( &ctx->pending, &request->node );
rtems_interrupt_lock_release( &ctx->lock, &lock_context ); rtems_interrupt_lock_release( &ctx->lock, &lock_context );
Cause_tm27_intr(); CallWithinISRRaise();
} }
void CallWithinISRWait( const CallWithinISRRequest *request ) void CallWithinISRWait( const CallWithinISRRequest *request )
@@ -124,6 +136,45 @@ void CallWithinISRWait( const CallWithinISRRequest *request )
} }
} }
static void CallWithinISRIsHandlerInstalled(
void *arg,
const char *info,
rtems_option option,
rtems_interrupt_handler handler,
void *handler_arg
)
{
(void) info;
(void) option;
(void) handler_arg;
if ( handler == (rtems_interrupt_handler) CallWithinISRHandler ) {
*(bool *) arg = true;
}
}
rtems_vector_number CallWithinISRGetVector( void )
{
rtems_vector_number vector;
for ( vector = 0; vector < BSP_INTERRUPT_VECTOR_COUNT; ++vector ) {
bool installed;
installed = false;
(void) rtems_interrupt_handler_iterate(
vector,
CallWithinISRIsHandlerInstalled,
&installed
);
if ( installed ) {
return vector;
}
}
return UINT32_MAX;
}
static void CallWithinISRInitialize( void ) static void CallWithinISRInitialize( void )
{ {
Install_tm27_vector( CallWithinISRHandler ); Install_tm27_vector( CallWithinISRHandler );

View File

@@ -390,6 +390,12 @@ void CallWithinISRSubmit( CallWithinISRRequest *request );
void CallWithinISRWait( const CallWithinISRRequest *request ); void CallWithinISRWait( const CallWithinISRRequest *request );
void CallWithinISRRaise( void );
void CallWithinISRClear( void );
rtems_vector_number CallWithinISRGetVector( void );
typedef struct { typedef struct {
Thread_queue_Operations tq_ops; Thread_queue_Operations tq_ops;
const Thread_queue_Operations *wrapped_ops; const Thread_queue_Operations *wrapped_ops;