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 RtemsIntrReqIsPending_Pre_Vector_Valid,
0073 RtemsIntrReqIsPending_Pre_Vector_Invalid,
0074 RtemsIntrReqIsPending_Pre_Vector_NA
0075 } RtemsIntrReqIsPending_Pre_Vector;
0076
0077 typedef enum {
0078 RtemsIntrReqIsPending_Pre_Pending_Obj,
0079 RtemsIntrReqIsPending_Pre_Pending_Null,
0080 RtemsIntrReqIsPending_Pre_Pending_NA
0081 } RtemsIntrReqIsPending_Pre_Pending;
0082
0083 typedef enum {
0084 RtemsIntrReqIsPending_Pre_IsPending_Yes,
0085 RtemsIntrReqIsPending_Pre_IsPending_No,
0086 RtemsIntrReqIsPending_Pre_IsPending_NA
0087 } RtemsIntrReqIsPending_Pre_IsPending;
0088
0089 typedef enum {
0090 RtemsIntrReqIsPending_Post_Status_Ok,
0091 RtemsIntrReqIsPending_Post_Status_InvAddr,
0092 RtemsIntrReqIsPending_Post_Status_InvId,
0093 RtemsIntrReqIsPending_Post_Status_NA
0094 } RtemsIntrReqIsPending_Post_Status;
0095
0096 typedef enum {
0097 RtemsIntrReqIsPending_Post_IsPending_Nop,
0098 RtemsIntrReqIsPending_Post_IsPending_Yes,
0099 RtemsIntrReqIsPending_Post_IsPending_No,
0100 RtemsIntrReqIsPending_Post_IsPending_NA
0101 } RtemsIntrReqIsPending_Post_IsPending;
0102
0103 typedef struct {
0104 uint8_t Skip : 1;
0105 uint8_t Pre_Vector_NA : 1;
0106 uint8_t Pre_Pending_NA : 1;
0107 uint8_t Pre_IsPending_NA : 1;
0108 uint8_t Post_Status : 2;
0109 uint8_t Post_IsPending : 2;
0110 } RtemsIntrReqIsPending_Entry;
0111
0112
0113
0114
0115 typedef struct {
0116
0117
0118
0119 volatile uint32_t interrupt_count;
0120
0121
0122
0123
0124 bool do_clear;
0125
0126
0127
0128
0129 rtems_vector_number vector;
0130
0131
0132
0133
0134 bool pending_obj;
0135
0136
0137
0138
0139
0140 bool valid_vector;
0141
0142
0143
0144
0145 bool *pending;
0146
0147
0148
0149
0150
0151 rtems_status_code status;
0152
0153 struct {
0154
0155
0156
0157
0158 size_t pci[ 3 ];
0159
0160
0161
0162
0163 size_t pcs[ 3 ];
0164
0165
0166
0167
0168 bool in_action_loop;
0169
0170
0171
0172
0173 size_t index;
0174
0175
0176
0177
0178 RtemsIntrReqIsPending_Entry entry;
0179
0180
0181
0182
0183
0184 bool skip;
0185 } Map;
0186 } RtemsIntrReqIsPending_Context;
0187
0188 static RtemsIntrReqIsPending_Context
0189 RtemsIntrReqIsPending_Instance;
0190
0191 static const char * const RtemsIntrReqIsPending_PreDesc_Vector[] = {
0192 "Valid",
0193 "Invalid",
0194 "NA"
0195 };
0196
0197 static const char * const RtemsIntrReqIsPending_PreDesc_Pending[] = {
0198 "Obj",
0199 "Null",
0200 "NA"
0201 };
0202
0203 static const char * const RtemsIntrReqIsPending_PreDesc_IsPending[] = {
0204 "Yes",
0205 "No",
0206 "NA"
0207 };
0208
0209 static const char * const * const RtemsIntrReqIsPending_PreDesc[] = {
0210 RtemsIntrReqIsPending_PreDesc_Vector,
0211 RtemsIntrReqIsPending_PreDesc_Pending,
0212 RtemsIntrReqIsPending_PreDesc_IsPending,
0213 NULL
0214 };
0215
0216 typedef RtemsIntrReqIsPending_Context Context;
0217
0218 static bool IsEnabled( const Context *ctx )
0219 {
0220 rtems_status_code sc;
0221 bool enabled;
0222
0223 enabled = false;
0224 sc = rtems_interrupt_vector_is_enabled( ctx->vector, &enabled );
0225 T_rsc_success( sc );
0226
0227 return enabled;
0228 }
0229
0230 static bool IsPending( const Context *ctx )
0231 {
0232 rtems_status_code sc;
0233 bool pending;
0234
0235 pending = false;
0236 sc = rtems_interrupt_is_pending( ctx->vector, &pending );
0237 T_rsc_success( sc );
0238
0239 return pending;
0240 }
0241
0242 static void Disable( const Context *ctx )
0243 {
0244 rtems_status_code sc;
0245
0246 sc = rtems_interrupt_vector_disable( ctx->vector );
0247 T_rsc_success( sc );
0248 }
0249
0250 static void Raise( const Context *ctx )
0251 {
0252 rtems_status_code sc;
0253
0254 sc = rtems_interrupt_raise( ctx->vector );
0255 T_rsc_success( sc );
0256 }
0257
0258 static void EntryRoutine( void *arg )
0259 {
0260 Context *ctx;
0261 uint32_t count;
0262
0263 (void) arg;
0264 ctx = T_fixture_context();
0265
0266 count = ctx->interrupt_count;
0267 ctx->interrupt_count = count + 1;
0268
0269 if ( ctx->do_clear ) {
0270 rtems_status_code sc;
0271
0272 sc = rtems_interrupt_clear( ctx->vector );
0273 T_rsc_success( sc );
0274 }
0275
0276 if ( count > 2 ) {
0277
0278 Disable( ctx );
0279 }
0280 }
0281
0282 static void CheckIsPending(
0283 Context *ctx,
0284 const rtems_interrupt_attributes *attr,
0285 bool has_installed_entries
0286 )
0287 {
0288 rtems_status_code sc;
0289
0290 if ( has_installed_entries ) {
0291
0292
0293
0294
0295
0296 (void) IsPending( ctx );
0297 } else if ( !attr->is_maskable ) {
0298
0299 T_false( IsPending( ctx ) );
0300 } else if ( IsPending( ctx ) ) {
0301
0302
0303
0304
0305 } else if (
0306 attr->can_raise && attr->can_disable &&
0307 ( attr->can_clear || attr->cleared_by_acknowledge )
0308 ) {
0309 rtems_interrupt_entry entry;
0310 rtems_interrupt_level level;
0311
0312 ctx->interrupt_count = 0;
0313 ctx->do_clear = attr->can_clear && !attr->cleared_by_acknowledge;
0314 rtems_interrupt_entry_initialize( &entry, EntryRoutine, ctx, "Info" );
0315 sc = rtems_interrupt_entry_install(
0316 ctx->vector,
0317 RTEMS_INTERRUPT_UNIQUE,
0318 &entry
0319 );
0320 T_rsc_success( sc );
0321
0322 if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
0323 Disable( ctx );
0324 Raise( ctx );
0325
0326
0327
0328
0329
0330
0331 (void) IsPending( ctx );
0332
0333 sc = rtems_interrupt_vector_enable( ctx->vector );
0334 T_rsc_success( sc );
0335
0336 while ( ctx->interrupt_count < 1 ) {
0337
0338 }
0339
0340 rtems_interrupt_local_disable( level );
0341 Raise( ctx );
0342 T_true( IsPending( ctx ) );
0343 rtems_interrupt_local_enable( level );
0344
0345 while ( ctx->interrupt_count < 2 ) {
0346
0347 }
0348 }
0349
0350 sc = rtems_interrupt_entry_remove( ctx->vector, &entry );
0351 T_rsc_success( sc );
0352 }
0353 }
0354
0355 static void RtemsIntrReqIsPending_Pre_Vector_Prepare(
0356 RtemsIntrReqIsPending_Context *ctx,
0357 RtemsIntrReqIsPending_Pre_Vector state
0358 )
0359 {
0360 switch ( state ) {
0361 case RtemsIntrReqIsPending_Pre_Vector_Valid: {
0362
0363
0364
0365 ctx->valid_vector = true;
0366 break;
0367 }
0368
0369 case RtemsIntrReqIsPending_Pre_Vector_Invalid: {
0370
0371
0372
0373
0374 ctx->valid_vector = false;
0375 break;
0376 }
0377
0378 case RtemsIntrReqIsPending_Pre_Vector_NA:
0379 break;
0380 }
0381 }
0382
0383 static void RtemsIntrReqIsPending_Pre_Pending_Prepare(
0384 RtemsIntrReqIsPending_Context *ctx,
0385 RtemsIntrReqIsPending_Pre_Pending state
0386 )
0387 {
0388 switch ( state ) {
0389 case RtemsIntrReqIsPending_Pre_Pending_Obj: {
0390
0391
0392
0393 ctx->pending = &ctx->pending_obj;
0394 break;
0395 }
0396
0397 case RtemsIntrReqIsPending_Pre_Pending_Null: {
0398
0399
0400
0401 ctx->pending = NULL;
0402 break;
0403 }
0404
0405 case RtemsIntrReqIsPending_Pre_Pending_NA:
0406 break;
0407 }
0408 }
0409
0410 static void RtemsIntrReqIsPending_Pre_IsPending_Prepare(
0411 RtemsIntrReqIsPending_Context *ctx,
0412 RtemsIntrReqIsPending_Pre_IsPending state
0413 )
0414 {
0415 switch ( state ) {
0416 case RtemsIntrReqIsPending_Pre_IsPending_Yes: {
0417
0418
0419
0420
0421
0422
0423 break;
0424 }
0425
0426 case RtemsIntrReqIsPending_Pre_IsPending_No: {
0427
0428
0429
0430
0431
0432
0433 break;
0434 }
0435
0436 case RtemsIntrReqIsPending_Pre_IsPending_NA:
0437 break;
0438 }
0439 }
0440
0441 static void RtemsIntrReqIsPending_Post_Status_Check(
0442 RtemsIntrReqIsPending_Context *ctx,
0443 RtemsIntrReqIsPending_Post_Status state
0444 )
0445 {
0446 switch ( state ) {
0447 case RtemsIntrReqIsPending_Post_Status_Ok: {
0448
0449
0450
0451
0452 T_rsc_success( ctx->status );
0453 break;
0454 }
0455
0456 case RtemsIntrReqIsPending_Post_Status_InvAddr: {
0457
0458
0459
0460
0461 T_rsc( ctx->status, RTEMS_INVALID_ADDRESS );
0462 break;
0463 }
0464
0465 case RtemsIntrReqIsPending_Post_Status_InvId: {
0466
0467
0468
0469
0470 T_rsc( ctx->status, RTEMS_INVALID_ID );
0471 break;
0472 }
0473
0474 case RtemsIntrReqIsPending_Post_Status_NA:
0475 break;
0476 }
0477 }
0478
0479 static void RtemsIntrReqIsPending_Post_IsPending_Check(
0480 RtemsIntrReqIsPending_Context *ctx,
0481 RtemsIntrReqIsPending_Post_IsPending state
0482 )
0483 {
0484 bool pending;
0485
0486 switch ( state ) {
0487 case RtemsIntrReqIsPending_Post_IsPending_Nop: {
0488
0489
0490
0491
0492
0493 memset( &pending, 0xa5, sizeof( pending ) );
0494 T_eq_mem( &ctx->pending_obj, &pending, sizeof( pending ) );
0495 break;
0496 }
0497
0498 case RtemsIntrReqIsPending_Post_IsPending_Yes: {
0499
0500
0501
0502
0503
0504 break;
0505 }
0506
0507 case RtemsIntrReqIsPending_Post_IsPending_No: {
0508
0509
0510
0511
0512
0513 break;
0514 }
0515
0516 case RtemsIntrReqIsPending_Post_IsPending_NA:
0517 break;
0518 }
0519 }
0520
0521 static void RtemsIntrReqIsPending_Action( RtemsIntrReqIsPending_Context *ctx )
0522 {
0523 if ( ctx->valid_vector && ctx->pending != NULL ) {
0524 for (
0525 ctx->vector = 0;
0526 ctx->vector < BSP_INTERRUPT_VECTOR_COUNT;
0527 ++ctx->vector
0528 ) {
0529 rtems_status_code sc;
0530 rtems_interrupt_attributes attr;
0531 bool has_installed_entries;
0532
0533 memset( &attr, 0, sizeof( attr ) );
0534 sc = rtems_interrupt_get_attributes( ctx->vector, &attr );
0535
0536 if ( sc == RTEMS_INVALID_ID ) {
0537 continue;
0538 }
0539
0540 T_rsc_success( sc );
0541
0542 has_installed_entries = HasInterruptVectorEntriesInstalled( ctx->vector );
0543 CheckIsPending( ctx, &attr, has_installed_entries );
0544 }
0545 } else {
0546 if ( ctx->valid_vector ) {
0547 ctx->vector = 0;
0548 } else {
0549 ctx->vector = BSP_INTERRUPT_VECTOR_COUNT;
0550 }
0551
0552 memset( &ctx->pending_obj, 0xa5, sizeof( ctx->pending_obj ) );
0553
0554 ctx->status = rtems_interrupt_is_pending( ctx->vector, ctx->pending );
0555 }
0556 }
0557
0558 static const RtemsIntrReqIsPending_Entry
0559 RtemsIntrReqIsPending_Entries[] = {
0560 { 0, 0, 0, 0, RtemsIntrReqIsPending_Post_Status_InvAddr,
0561 RtemsIntrReqIsPending_Post_IsPending_Nop },
0562 { 0, 0, 0, 1, RtemsIntrReqIsPending_Post_Status_InvId,
0563 RtemsIntrReqIsPending_Post_IsPending_Nop },
0564 { 0, 0, 0, 1, RtemsIntrReqIsPending_Post_Status_InvAddr,
0565 RtemsIntrReqIsPending_Post_IsPending_Nop },
0566 { 0, 0, 0, 0, RtemsIntrReqIsPending_Post_Status_Ok,
0567 RtemsIntrReqIsPending_Post_IsPending_Yes },
0568 { 0, 0, 0, 0, RtemsIntrReqIsPending_Post_Status_Ok,
0569 RtemsIntrReqIsPending_Post_IsPending_No }
0570 };
0571
0572 static const uint8_t
0573 RtemsIntrReqIsPending_Map[] = {
0574 3, 4, 0, 0, 1, 1, 2, 2
0575 };
0576
0577 static size_t RtemsIntrReqIsPending_Scope( void *arg, char *buf, size_t n )
0578 {
0579 RtemsIntrReqIsPending_Context *ctx;
0580
0581 ctx = arg;
0582
0583 if ( ctx->Map.in_action_loop ) {
0584 return T_get_scope( RtemsIntrReqIsPending_PreDesc, buf, n, ctx->Map.pcs );
0585 }
0586
0587 return 0;
0588 }
0589
0590 static T_fixture RtemsIntrReqIsPending_Fixture = {
0591 .setup = NULL,
0592 .stop = NULL,
0593 .teardown = NULL,
0594 .scope = RtemsIntrReqIsPending_Scope,
0595 .initial_context = &RtemsIntrReqIsPending_Instance
0596 };
0597
0598 static inline RtemsIntrReqIsPending_Entry RtemsIntrReqIsPending_PopEntry(
0599 RtemsIntrReqIsPending_Context *ctx
0600 )
0601 {
0602 size_t index;
0603
0604 index = ctx->Map.index;
0605 ctx->Map.index = index + 1;
0606 return RtemsIntrReqIsPending_Entries[
0607 RtemsIntrReqIsPending_Map[ index ]
0608 ];
0609 }
0610
0611 static void RtemsIntrReqIsPending_SetPreConditionStates(
0612 RtemsIntrReqIsPending_Context *ctx
0613 )
0614 {
0615 ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0616 ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0617
0618 if ( ctx->Map.entry.Pre_IsPending_NA ) {
0619 ctx->Map.pcs[ 2 ] = RtemsIntrReqIsPending_Pre_IsPending_NA;
0620 } else {
0621 ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
0622 }
0623 }
0624
0625 static void RtemsIntrReqIsPending_TestVariant(
0626 RtemsIntrReqIsPending_Context *ctx
0627 )
0628 {
0629 RtemsIntrReqIsPending_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0630 RtemsIntrReqIsPending_Pre_Pending_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0631 RtemsIntrReqIsPending_Pre_IsPending_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0632 RtemsIntrReqIsPending_Action( ctx );
0633 RtemsIntrReqIsPending_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0634 RtemsIntrReqIsPending_Post_IsPending_Check(
0635 ctx,
0636 ctx->Map.entry.Post_IsPending
0637 );
0638 }
0639
0640
0641
0642
0643 T_TEST_CASE_FIXTURE( RtemsIntrReqIsPending, &RtemsIntrReqIsPending_Fixture )
0644 {
0645 RtemsIntrReqIsPending_Context *ctx;
0646
0647 ctx = T_fixture_context();
0648 ctx->Map.in_action_loop = true;
0649 ctx->Map.index = 0;
0650
0651 for (
0652 ctx->Map.pci[ 0 ] = RtemsIntrReqIsPending_Pre_Vector_Valid;
0653 ctx->Map.pci[ 0 ] < RtemsIntrReqIsPending_Pre_Vector_NA;
0654 ++ctx->Map.pci[ 0 ]
0655 ) {
0656 for (
0657 ctx->Map.pci[ 1 ] = RtemsIntrReqIsPending_Pre_Pending_Obj;
0658 ctx->Map.pci[ 1 ] < RtemsIntrReqIsPending_Pre_Pending_NA;
0659 ++ctx->Map.pci[ 1 ]
0660 ) {
0661 for (
0662 ctx->Map.pci[ 2 ] = RtemsIntrReqIsPending_Pre_IsPending_Yes;
0663 ctx->Map.pci[ 2 ] < RtemsIntrReqIsPending_Pre_IsPending_NA;
0664 ++ctx->Map.pci[ 2 ]
0665 ) {
0666 ctx->Map.entry = RtemsIntrReqIsPending_PopEntry( ctx );
0667 RtemsIntrReqIsPending_SetPreConditionStates( ctx );
0668 RtemsIntrReqIsPending_TestVariant( ctx );
0669 }
0670 }
0671 }
0672 }
0673
0674