forked from Imagelibrary/rtems
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:
@@ -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 */
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user