File indexing completed on 2025-05-11 08:24:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054
0055 #include <string.h>
0056 #include <bsp/irq-generic.h>
0057 #include <rtems/irq-extension.h>
0058
0059 #include "tx-support.h"
0060
0061 #include <rtems/test.h>
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 typedef enum {
0072 RtemsIntrReqRaise_Pre_Vector_Valid,
0073 RtemsIntrReqRaise_Pre_Vector_Invalid,
0074 RtemsIntrReqRaise_Pre_Vector_NA
0075 } RtemsIntrReqRaise_Pre_Vector;
0076
0077 typedef enum {
0078 RtemsIntrReqRaise_Pre_CanRaise_Yes,
0079 RtemsIntrReqRaise_Pre_CanRaise_No,
0080 RtemsIntrReqRaise_Pre_CanRaise_NA
0081 } RtemsIntrReqRaise_Pre_CanRaise;
0082
0083 typedef enum {
0084 RtemsIntrReqRaise_Post_Status_Ok,
0085 RtemsIntrReqRaise_Post_Status_InvId,
0086 RtemsIntrReqRaise_Post_Status_Unsat,
0087 RtemsIntrReqRaise_Post_Status_NA
0088 } RtemsIntrReqRaise_Post_Status;
0089
0090 typedef enum {
0091 RtemsIntrReqRaise_Post_Pending_Yes,
0092 RtemsIntrReqRaise_Post_Pending_No,
0093 RtemsIntrReqRaise_Post_Pending_NA
0094 } RtemsIntrReqRaise_Post_Pending;
0095
0096 typedef struct {
0097 uint8_t Skip : 1;
0098 uint8_t Pre_Vector_NA : 1;
0099 uint8_t Pre_CanRaise_NA : 1;
0100 uint8_t Post_Status : 2;
0101 uint8_t Post_Pending : 2;
0102 } RtemsIntrReqRaise_Entry;
0103
0104
0105
0106
0107 typedef struct {
0108
0109
0110
0111 volatile uint32_t interrupt_count;
0112
0113
0114
0115
0116 bool do_clear;
0117
0118
0119
0120
0121 rtems_vector_number vector;
0122
0123
0124
0125
0126
0127 bool valid_vector;
0128
0129
0130
0131
0132
0133 rtems_status_code status;
0134
0135 struct {
0136
0137
0138
0139
0140 size_t pci[ 2 ];
0141
0142
0143
0144
0145 size_t pcs[ 2 ];
0146
0147
0148
0149
0150 bool in_action_loop;
0151
0152
0153
0154
0155 size_t index;
0156
0157
0158
0159
0160 RtemsIntrReqRaise_Entry entry;
0161
0162
0163
0164
0165
0166 bool skip;
0167 } Map;
0168 } RtemsIntrReqRaise_Context;
0169
0170 static RtemsIntrReqRaise_Context
0171 RtemsIntrReqRaise_Instance;
0172
0173 static const char * const RtemsIntrReqRaise_PreDesc_Vector[] = {
0174 "Valid",
0175 "Invalid",
0176 "NA"
0177 };
0178
0179 static const char * const RtemsIntrReqRaise_PreDesc_CanRaise[] = {
0180 "Yes",
0181 "No",
0182 "NA"
0183 };
0184
0185 static const char * const * const RtemsIntrReqRaise_PreDesc[] = {
0186 RtemsIntrReqRaise_PreDesc_Vector,
0187 RtemsIntrReqRaise_PreDesc_CanRaise,
0188 NULL
0189 };
0190
0191 typedef RtemsIntrReqRaise_Context Context;
0192
0193 static bool IsEnabled( const Context *ctx )
0194 {
0195 rtems_status_code sc;
0196 bool enabled;
0197
0198 enabled = false;
0199 sc = rtems_interrupt_vector_is_enabled( ctx->vector, &enabled );
0200 T_rsc_success( sc );
0201
0202 return enabled;
0203 }
0204
0205 static bool IsPending( const Context *ctx )
0206 {
0207 rtems_status_code sc;
0208 bool pending;
0209
0210 pending = false;
0211 sc = rtems_interrupt_is_pending( ctx->vector, &pending );
0212 T_rsc_success( sc );
0213
0214 return pending;
0215 }
0216
0217 static void Disable( const Context *ctx )
0218 {
0219 rtems_status_code sc;
0220
0221 sc = rtems_interrupt_vector_disable( ctx->vector );
0222 T_rsc_success( sc );
0223 }
0224
0225 static void Raise( const Context *ctx )
0226 {
0227 rtems_status_code sc;
0228
0229 sc = rtems_interrupt_raise( ctx->vector );
0230 T_rsc_success( sc );
0231 }
0232
0233 static void EntryRoutine( void *arg )
0234 {
0235 Context *ctx;
0236 uint32_t count;
0237
0238 (void) arg;
0239 ctx = T_fixture_context();
0240
0241 count = ctx->interrupt_count;
0242 ctx->interrupt_count = count + 1;
0243
0244 if ( ctx->do_clear ) {
0245 rtems_status_code sc;
0246
0247 sc = rtems_interrupt_clear( ctx->vector );
0248 T_rsc_success( sc );
0249 }
0250
0251 if ( count > 2 ) {
0252
0253 Disable( ctx );
0254 }
0255 }
0256
0257 static void CheckUnsatisfied( const Context *ctx )
0258 {
0259 rtems_status_code sc;
0260 bool pending_before;
0261 bool pending_after;
0262
0263 pending_before = true;
0264 sc = rtems_interrupt_is_pending( ctx->vector, &pending_before );
0265 T_rsc_success( sc );
0266
0267 sc = rtems_interrupt_raise( ctx->vector );
0268 T_rsc( sc, RTEMS_UNSATISFIED );
0269
0270 pending_after = !pending_before;
0271 sc = rtems_interrupt_is_pending( ctx->vector, &pending_after );
0272 T_rsc_success( sc );
0273
0274 T_eq( pending_before, pending_after );
0275 }
0276
0277 static void CheckRaise(
0278 Context *ctx,
0279 const rtems_interrupt_attributes *attr,
0280 bool has_installed_entries
0281 )
0282 {
0283 rtems_status_code sc;
0284
0285 if ( !attr->can_raise ) {
0286 CheckUnsatisfied( ctx );
0287 } else if ( has_installed_entries ) {
0288
0289 } else if ( !attr->is_maskable ) {
0290
0291 } else if ( IsPending( ctx ) ) {
0292
0293
0294
0295
0296 } else if (
0297 attr->can_disable && ( attr->can_clear || attr->cleared_by_acknowledge )
0298 ) {
0299 rtems_interrupt_entry entry;
0300 rtems_interrupt_level level;
0301
0302 ctx->interrupt_count = 0;
0303 ctx->do_clear = attr->can_clear && !attr->cleared_by_acknowledge;
0304 rtems_interrupt_entry_initialize( &entry, EntryRoutine, ctx, "Info" );
0305 sc = rtems_interrupt_entry_install(
0306 ctx->vector,
0307 RTEMS_INTERRUPT_UNIQUE,
0308 &entry
0309 );
0310 T_rsc_success( sc );
0311
0312 if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
0313 Disable( ctx );
0314 Raise( ctx );
0315
0316
0317
0318
0319
0320
0321 (void) IsPending( ctx );
0322
0323 sc = rtems_interrupt_vector_enable( ctx->vector );
0324 T_rsc_success( sc );
0325
0326 while ( ctx->interrupt_count < 1 ) {
0327
0328 }
0329
0330 T_false( IsPending( ctx ) );
0331
0332 rtems_interrupt_local_disable( level );
0333 Raise( ctx );
0334 T_true( IsPending( ctx ) );
0335 rtems_interrupt_local_enable( level );
0336
0337 while ( ctx->interrupt_count < 2 ) {
0338
0339 }
0340
0341 T_false( IsPending( ctx ) );
0342 }
0343
0344 sc = rtems_interrupt_entry_remove( ctx->vector, &entry );
0345 T_rsc_success( sc );
0346 }
0347 }
0348
0349 static void RtemsIntrReqRaise_Pre_Vector_Prepare(
0350 RtemsIntrReqRaise_Context *ctx,
0351 RtemsIntrReqRaise_Pre_Vector state
0352 )
0353 {
0354 switch ( state ) {
0355 case RtemsIntrReqRaise_Pre_Vector_Valid: {
0356
0357
0358
0359 ctx->valid_vector = true;
0360 break;
0361 }
0362
0363 case RtemsIntrReqRaise_Pre_Vector_Invalid: {
0364
0365
0366
0367
0368 ctx->valid_vector = false;
0369 break;
0370 }
0371
0372 case RtemsIntrReqRaise_Pre_Vector_NA:
0373 break;
0374 }
0375 }
0376
0377 static void RtemsIntrReqRaise_Pre_CanRaise_Prepare(
0378 RtemsIntrReqRaise_Context *ctx,
0379 RtemsIntrReqRaise_Pre_CanRaise state
0380 )
0381 {
0382 switch ( state ) {
0383 case RtemsIntrReqRaise_Pre_CanRaise_Yes: {
0384
0385
0386
0387
0388
0389
0390
0391
0392 break;
0393 }
0394
0395 case RtemsIntrReqRaise_Pre_CanRaise_No: {
0396
0397
0398
0399
0400
0401
0402
0403
0404 break;
0405 }
0406
0407 case RtemsIntrReqRaise_Pre_CanRaise_NA:
0408 break;
0409 }
0410 }
0411
0412 static void RtemsIntrReqRaise_Post_Status_Check(
0413 RtemsIntrReqRaise_Context *ctx,
0414 RtemsIntrReqRaise_Post_Status state
0415 )
0416 {
0417 switch ( state ) {
0418 case RtemsIntrReqRaise_Post_Status_Ok: {
0419
0420
0421
0422
0423
0424 break;
0425 }
0426
0427 case RtemsIntrReqRaise_Post_Status_InvId: {
0428
0429
0430
0431
0432 T_rsc( ctx->status, RTEMS_INVALID_ID );
0433 break;
0434 }
0435
0436 case RtemsIntrReqRaise_Post_Status_Unsat: {
0437
0438
0439
0440
0441
0442 break;
0443 }
0444
0445 case RtemsIntrReqRaise_Post_Status_NA:
0446 break;
0447 }
0448 }
0449
0450 static void RtemsIntrReqRaise_Post_Pending_Check(
0451 RtemsIntrReqRaise_Context *ctx,
0452 RtemsIntrReqRaise_Post_Pending state
0453 )
0454 {
0455 switch ( state ) {
0456 case RtemsIntrReqRaise_Post_Pending_Yes: {
0457
0458
0459
0460
0461
0462 break;
0463 }
0464
0465 case RtemsIntrReqRaise_Post_Pending_No: {
0466
0467
0468
0469
0470
0471
0472 break;
0473 }
0474
0475 case RtemsIntrReqRaise_Post_Pending_NA:
0476 break;
0477 }
0478 }
0479
0480 static void RtemsIntrReqRaise_Action( RtemsIntrReqRaise_Context *ctx )
0481 {
0482 if ( ctx->valid_vector ) {
0483 for (
0484 ctx->vector = 0;
0485 ctx->vector < BSP_INTERRUPT_VECTOR_COUNT;
0486 ++ctx->vector
0487 ) {
0488 rtems_status_code sc;
0489 rtems_interrupt_attributes attr;
0490 bool has_installed_entries;
0491
0492 memset( &attr, 0, sizeof( attr ) );
0493 sc = rtems_interrupt_get_attributes( ctx->vector, &attr );
0494
0495 if ( sc == RTEMS_INVALID_ID ) {
0496 continue;
0497 }
0498
0499 T_rsc_success( sc );
0500
0501 has_installed_entries = HasInterruptVectorEntriesInstalled( ctx->vector );
0502 CheckRaise( ctx, &attr, has_installed_entries );
0503 }
0504 } else {
0505 ctx->vector = BSP_INTERRUPT_VECTOR_COUNT;
0506 ctx->status = rtems_interrupt_raise( ctx->vector );
0507 }
0508 }
0509
0510 static const RtemsIntrReqRaise_Entry
0511 RtemsIntrReqRaise_Entries[] = {
0512 { 0, 0, 1, RtemsIntrReqRaise_Post_Status_InvId,
0513 RtemsIntrReqRaise_Post_Pending_NA },
0514 { 0, 0, 0, RtemsIntrReqRaise_Post_Status_Ok,
0515 RtemsIntrReqRaise_Post_Pending_Yes },
0516 { 0, 0, 0, RtemsIntrReqRaise_Post_Status_Unsat,
0517 RtemsIntrReqRaise_Post_Pending_No }
0518 };
0519
0520 static const uint8_t
0521 RtemsIntrReqRaise_Map[] = {
0522 1, 2, 0, 0
0523 };
0524
0525 static size_t RtemsIntrReqRaise_Scope( void *arg, char *buf, size_t n )
0526 {
0527 RtemsIntrReqRaise_Context *ctx;
0528
0529 ctx = arg;
0530
0531 if ( ctx->Map.in_action_loop ) {
0532 return T_get_scope( RtemsIntrReqRaise_PreDesc, buf, n, ctx->Map.pcs );
0533 }
0534
0535 return 0;
0536 }
0537
0538 static T_fixture RtemsIntrReqRaise_Fixture = {
0539 .setup = NULL,
0540 .stop = NULL,
0541 .teardown = NULL,
0542 .scope = RtemsIntrReqRaise_Scope,
0543 .initial_context = &RtemsIntrReqRaise_Instance
0544 };
0545
0546 static inline RtemsIntrReqRaise_Entry RtemsIntrReqRaise_PopEntry(
0547 RtemsIntrReqRaise_Context *ctx
0548 )
0549 {
0550 size_t index;
0551
0552 index = ctx->Map.index;
0553 ctx->Map.index = index + 1;
0554 return RtemsIntrReqRaise_Entries[
0555 RtemsIntrReqRaise_Map[ index ]
0556 ];
0557 }
0558
0559 static void RtemsIntrReqRaise_SetPreConditionStates(
0560 RtemsIntrReqRaise_Context *ctx
0561 )
0562 {
0563 ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0564
0565 if ( ctx->Map.entry.Pre_CanRaise_NA ) {
0566 ctx->Map.pcs[ 1 ] = RtemsIntrReqRaise_Pre_CanRaise_NA;
0567 } else {
0568 ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0569 }
0570 }
0571
0572 static void RtemsIntrReqRaise_TestVariant( RtemsIntrReqRaise_Context *ctx )
0573 {
0574 RtemsIntrReqRaise_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0575 RtemsIntrReqRaise_Pre_CanRaise_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0576 RtemsIntrReqRaise_Action( ctx );
0577 RtemsIntrReqRaise_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0578 RtemsIntrReqRaise_Post_Pending_Check( ctx, ctx->Map.entry.Post_Pending );
0579 }
0580
0581
0582
0583
0584 T_TEST_CASE_FIXTURE( RtemsIntrReqRaise, &RtemsIntrReqRaise_Fixture )
0585 {
0586 RtemsIntrReqRaise_Context *ctx;
0587
0588 ctx = T_fixture_context();
0589 ctx->Map.in_action_loop = true;
0590 ctx->Map.index = 0;
0591
0592 for (
0593 ctx->Map.pci[ 0 ] = RtemsIntrReqRaise_Pre_Vector_Valid;
0594 ctx->Map.pci[ 0 ] < RtemsIntrReqRaise_Pre_Vector_NA;
0595 ++ctx->Map.pci[ 0 ]
0596 ) {
0597 for (
0598 ctx->Map.pci[ 1 ] = RtemsIntrReqRaise_Pre_CanRaise_Yes;
0599 ctx->Map.pci[ 1 ] < RtemsIntrReqRaise_Pre_CanRaise_NA;
0600 ++ctx->Map.pci[ 1 ]
0601 ) {
0602 ctx->Map.entry = RtemsIntrReqRaise_PopEntry( ctx );
0603 RtemsIntrReqRaise_SetPreConditionStates( ctx );
0604 RtemsIntrReqRaise_TestVariant( ctx );
0605 }
0606 }
0607 }
0608
0609