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 RtemsIntrReqVectorEnable_Pre_Vector_Valid,
0073 RtemsIntrReqVectorEnable_Pre_Vector_Invalid,
0074 RtemsIntrReqVectorEnable_Pre_Vector_NA
0075 } RtemsIntrReqVectorEnable_Pre_Vector;
0076
0077 typedef enum {
0078 RtemsIntrReqVectorEnable_Pre_IsEnabled_Yes,
0079 RtemsIntrReqVectorEnable_Pre_IsEnabled_No,
0080 RtemsIntrReqVectorEnable_Pre_IsEnabled_NA
0081 } RtemsIntrReqVectorEnable_Pre_IsEnabled;
0082
0083 typedef enum {
0084 RtemsIntrReqVectorEnable_Pre_CanEnable_Yes,
0085 RtemsIntrReqVectorEnable_Pre_CanEnable_Maybe,
0086 RtemsIntrReqVectorEnable_Pre_CanEnable_No,
0087 RtemsIntrReqVectorEnable_Pre_CanEnable_NA
0088 } RtemsIntrReqVectorEnable_Pre_CanEnable;
0089
0090 typedef enum {
0091 RtemsIntrReqVectorEnable_Post_Status_Ok,
0092 RtemsIntrReqVectorEnable_Post_Status_InvId,
0093 RtemsIntrReqVectorEnable_Post_Status_Unsat,
0094 RtemsIntrReqVectorEnable_Post_Status_NA
0095 } RtemsIntrReqVectorEnable_Post_Status;
0096
0097 typedef enum {
0098 RtemsIntrReqVectorEnable_Post_IsEnabled_Nop,
0099 RtemsIntrReqVectorEnable_Post_IsEnabled_Yes,
0100 RtemsIntrReqVectorEnable_Post_IsEnabled_Maybe,
0101 RtemsIntrReqVectorEnable_Post_IsEnabled_NA
0102 } RtemsIntrReqVectorEnable_Post_IsEnabled;
0103
0104 typedef struct {
0105 uint8_t Skip : 1;
0106 uint8_t Pre_Vector_NA : 1;
0107 uint8_t Pre_IsEnabled_NA : 1;
0108 uint8_t Pre_CanEnable_NA : 1;
0109 uint8_t Post_Status : 2;
0110 uint8_t Post_IsEnabled : 2;
0111 } RtemsIntrReqVectorEnable_Entry;
0112
0113
0114
0115
0116 typedef struct {
0117
0118
0119
0120 bool interrupt_occurred;
0121
0122
0123
0124
0125 rtems_vector_number vector;
0126
0127
0128
0129
0130
0131 bool valid_vector;
0132
0133
0134
0135
0136
0137 rtems_status_code status;
0138
0139 struct {
0140
0141
0142
0143
0144 size_t pci[ 3 ];
0145
0146
0147
0148
0149 size_t pcs[ 3 ];
0150
0151
0152
0153
0154 bool in_action_loop;
0155
0156
0157
0158
0159 size_t index;
0160
0161
0162
0163
0164 RtemsIntrReqVectorEnable_Entry entry;
0165
0166
0167
0168
0169
0170 bool skip;
0171 } Map;
0172 } RtemsIntrReqVectorEnable_Context;
0173
0174 static RtemsIntrReqVectorEnable_Context
0175 RtemsIntrReqVectorEnable_Instance;
0176
0177 static const char * const RtemsIntrReqVectorEnable_PreDesc_Vector[] = {
0178 "Valid",
0179 "Invalid",
0180 "NA"
0181 };
0182
0183 static const char * const RtemsIntrReqVectorEnable_PreDesc_IsEnabled[] = {
0184 "Yes",
0185 "No",
0186 "NA"
0187 };
0188
0189 static const char * const RtemsIntrReqVectorEnable_PreDesc_CanEnable[] = {
0190 "Yes",
0191 "Maybe",
0192 "No",
0193 "NA"
0194 };
0195
0196 static const char * const * const RtemsIntrReqVectorEnable_PreDesc[] = {
0197 RtemsIntrReqVectorEnable_PreDesc_Vector,
0198 RtemsIntrReqVectorEnable_PreDesc_IsEnabled,
0199 RtemsIntrReqVectorEnable_PreDesc_CanEnable,
0200 NULL
0201 };
0202
0203 typedef RtemsIntrReqVectorEnable_Context Context;
0204
0205 static bool IsEnabled( const Context *ctx )
0206 {
0207 rtems_status_code sc;
0208 bool enabled;
0209
0210 enabled = false;
0211 sc = rtems_interrupt_vector_is_enabled( ctx->vector, &enabled );
0212 T_rsc_success( sc );
0213
0214 return enabled;
0215 }
0216
0217 static void Enable( const Context *ctx )
0218 {
0219 rtems_status_code sc;
0220
0221 sc = rtems_interrupt_vector_enable( ctx->vector );
0222 T_rsc_success( sc );
0223 }
0224
0225 static void Disable( const Context *ctx )
0226 {
0227 rtems_status_code sc;
0228
0229 sc = rtems_interrupt_vector_disable( ctx->vector );
0230 T_rsc_success( sc );
0231 }
0232
0233 static void EntryRoutine( void *arg )
0234 {
0235 Context *ctx;
0236
0237 (void) arg;
0238 ctx = T_fixture_context();
0239
0240 T_true( IsEnabled( ctx ) );
0241 Enable( ctx );
0242 T_true( IsEnabled( ctx ) );
0243 Disable( ctx );
0244 T_false( IsEnabled( ctx ) );
0245 ctx->interrupt_occurred = true;
0246 }
0247
0248 static void CheckUnsatisfied( const Context *ctx )
0249 {
0250 rtems_status_code sc;
0251 bool enabled_before;
0252 bool enabled_after;
0253
0254 enabled_before = true;
0255 sc = rtems_interrupt_vector_is_enabled( ctx->vector, &enabled_before );
0256 T_rsc_success( sc );
0257
0258 sc = rtems_interrupt_vector_enable( ctx->vector );
0259 T_rsc( sc, RTEMS_UNSATISFIED );
0260
0261 enabled_after = !enabled_before;
0262 sc = rtems_interrupt_vector_is_enabled( ctx->vector, &enabled_after );
0263 T_rsc_success( sc );
0264
0265 T_eq( enabled_before, enabled_after );
0266 }
0267
0268 static void CheckVectorEnable(
0269 Context *ctx,
0270 const rtems_interrupt_attributes *attr,
0271 bool has_installed_entries
0272 )
0273 {
0274 rtems_status_code sc;
0275
0276 if ( !attr->maybe_enable ) {
0277 CheckUnsatisfied( ctx );
0278 } else if ( has_installed_entries ) {
0279 cpu_set_t affinity_old;
0280 cpu_set_t affinity_new;
0281
0282 CPU_ZERO(&affinity_old);
0283 CPU_ZERO(&affinity_new);
0284 T_true( IsEnabled( ctx ) );
0285
0286 if ( attr->can_get_affinity ) {
0287
0288
0289
0290
0291
0292
0293 sc = rtems_task_get_affinity(
0294 RTEMS_SELF,
0295 sizeof( affinity_old ),
0296 &affinity_old
0297 );
0298 T_rsc_success( sc );
0299
0300 sc = rtems_interrupt_get_affinity(
0301 ctx->vector,
0302 sizeof( affinity_new ),
0303 &affinity_new
0304 );
0305 T_rsc_success( sc );
0306
0307 sc = rtems_task_set_affinity(
0308 RTEMS_SELF,
0309 sizeof( affinity_new ),
0310 &affinity_new
0311 );
0312
0313 if ( sc != RTEMS_SUCCESSFUL ) {
0314
0315
0316
0317
0318 return;
0319 }
0320 }
0321
0322 if ( attr->can_disable ) {
0323 Disable( ctx );
0324 T_false( IsEnabled( ctx ) );
0325 }
0326
0327 Enable( ctx );
0328
0329 if ( attr->can_get_affinity ) {
0330 sc = rtems_task_set_affinity(
0331 RTEMS_SELF,
0332 sizeof( affinity_old ),
0333 &affinity_old
0334 );
0335 T_rsc_success( sc );
0336 }
0337
0338 T_true( IsEnabled( ctx ) );
0339 } else if ( attr->is_maskable && attr->can_disable ) {
0340 rtems_interrupt_entry entry;
0341 bool enabled;
0342
0343 ctx->interrupt_occurred = false;
0344 rtems_interrupt_entry_initialize( &entry, EntryRoutine, ctx, "Info" );
0345 sc = rtems_interrupt_entry_install(
0346 ctx->vector,
0347 RTEMS_INTERRUPT_UNIQUE,
0348 &entry
0349 );
0350 T_rsc_success( sc );
0351
0352 if ( attr->can_disable ) {
0353 Disable( ctx );
0354 T_false( IsEnabled( ctx ) );
0355 }
0356
0357 Enable( ctx );
0358 Enable( ctx );
0359
0360 enabled = false;
0361 sc = rtems_interrupt_vector_is_enabled( ctx->vector, &enabled );
0362 T_rsc_success( sc );
0363 T_true( enabled || ctx->interrupt_occurred || attr->maybe_enable );
0364
0365 sc = rtems_interrupt_entry_remove( ctx->vector, &entry );
0366 T_rsc_success( sc );
0367
0368 T_true( !attr->can_disable || !IsEnabled( ctx ) );
0369 }
0370 }
0371
0372 static void RtemsIntrReqVectorEnable_Pre_Vector_Prepare(
0373 RtemsIntrReqVectorEnable_Context *ctx,
0374 RtemsIntrReqVectorEnable_Pre_Vector state
0375 )
0376 {
0377 switch ( state ) {
0378 case RtemsIntrReqVectorEnable_Pre_Vector_Valid: {
0379
0380
0381
0382 ctx->valid_vector = true;
0383 break;
0384 }
0385
0386 case RtemsIntrReqVectorEnable_Pre_Vector_Invalid: {
0387
0388
0389
0390
0391 ctx->valid_vector = false;
0392 break;
0393 }
0394
0395 case RtemsIntrReqVectorEnable_Pre_Vector_NA:
0396 break;
0397 }
0398 }
0399
0400 static void RtemsIntrReqVectorEnable_Pre_IsEnabled_Prepare(
0401 RtemsIntrReqVectorEnable_Context *ctx,
0402 RtemsIntrReqVectorEnable_Pre_IsEnabled state
0403 )
0404 {
0405 switch ( state ) {
0406 case RtemsIntrReqVectorEnable_Pre_IsEnabled_Yes: {
0407
0408
0409
0410
0411
0412
0413
0414
0415 break;
0416 }
0417
0418 case RtemsIntrReqVectorEnable_Pre_IsEnabled_No: {
0419
0420
0421
0422
0423
0424
0425
0426
0427 break;
0428 }
0429
0430 case RtemsIntrReqVectorEnable_Pre_IsEnabled_NA:
0431 break;
0432 }
0433 }
0434
0435 static void RtemsIntrReqVectorEnable_Pre_CanEnable_Prepare(
0436 RtemsIntrReqVectorEnable_Context *ctx,
0437 RtemsIntrReqVectorEnable_Pre_CanEnable state
0438 )
0439 {
0440 switch ( state ) {
0441 case RtemsIntrReqVectorEnable_Pre_CanEnable_Yes: {
0442
0443
0444
0445
0446
0447
0448
0449
0450 break;
0451 }
0452
0453 case RtemsIntrReqVectorEnable_Pre_CanEnable_Maybe: {
0454
0455
0456
0457
0458
0459
0460
0461
0462 break;
0463 }
0464
0465 case RtemsIntrReqVectorEnable_Pre_CanEnable_No: {
0466
0467
0468
0469
0470
0471
0472
0473
0474 break;
0475 }
0476
0477 case RtemsIntrReqVectorEnable_Pre_CanEnable_NA:
0478 break;
0479 }
0480 }
0481
0482 static void RtemsIntrReqVectorEnable_Post_Status_Check(
0483 RtemsIntrReqVectorEnable_Context *ctx,
0484 RtemsIntrReqVectorEnable_Post_Status state
0485 )
0486 {
0487 switch ( state ) {
0488 case RtemsIntrReqVectorEnable_Post_Status_Ok: {
0489
0490
0491
0492
0493
0494
0495
0496
0497 break;
0498 }
0499
0500 case RtemsIntrReqVectorEnable_Post_Status_InvId: {
0501
0502
0503
0504
0505 T_rsc( ctx->status, RTEMS_INVALID_ID );
0506 break;
0507 }
0508
0509 case RtemsIntrReqVectorEnable_Post_Status_Unsat: {
0510
0511
0512
0513
0514
0515
0516
0517
0518 break;
0519 }
0520
0521 case RtemsIntrReqVectorEnable_Post_Status_NA:
0522 break;
0523 }
0524 }
0525
0526 static void RtemsIntrReqVectorEnable_Post_IsEnabled_Check(
0527 RtemsIntrReqVectorEnable_Context *ctx,
0528 RtemsIntrReqVectorEnable_Post_IsEnabled state
0529 )
0530 {
0531 switch ( state ) {
0532 case RtemsIntrReqVectorEnable_Post_IsEnabled_Nop: {
0533
0534
0535
0536
0537
0538
0539
0540
0541 break;
0542 }
0543
0544 case RtemsIntrReqVectorEnable_Post_IsEnabled_Yes: {
0545
0546
0547
0548
0549
0550
0551
0552 break;
0553 }
0554
0555 case RtemsIntrReqVectorEnable_Post_IsEnabled_Maybe: {
0556
0557
0558
0559
0560
0561
0562
0563 break;
0564 }
0565
0566 case RtemsIntrReqVectorEnable_Post_IsEnabled_NA:
0567 break;
0568 }
0569 }
0570
0571 static void RtemsIntrReqVectorEnable_Action(
0572 RtemsIntrReqVectorEnable_Context *ctx
0573 )
0574 {
0575 if ( ctx->valid_vector ) {
0576 for (
0577 ctx->vector = 0;
0578 ctx->vector < BSP_INTERRUPT_VECTOR_COUNT;
0579 ++ctx->vector
0580 ) {
0581 rtems_status_code sc;
0582 rtems_interrupt_attributes attr;
0583 bool has_installed_entries;
0584
0585 memset( &attr, 0, sizeof( attr ) );
0586 sc = rtems_interrupt_get_attributes( ctx->vector, &attr );
0587
0588 if ( sc == RTEMS_INVALID_ID ) {
0589 continue;
0590 }
0591
0592 T_rsc_success( sc );
0593
0594 has_installed_entries = HasInterruptVectorEntriesInstalled( ctx->vector );
0595 CheckVectorEnable( ctx, &attr, has_installed_entries );
0596 }
0597 } else {
0598 ctx->vector = BSP_INTERRUPT_VECTOR_COUNT;
0599 ctx->status = rtems_interrupt_vector_enable( ctx->vector );
0600 }
0601 }
0602
0603 static const RtemsIntrReqVectorEnable_Entry
0604 RtemsIntrReqVectorEnable_Entries[] = {
0605 { 0, 0, 1, 1, RtemsIntrReqVectorEnable_Post_Status_InvId,
0606 RtemsIntrReqVectorEnable_Post_IsEnabled_NA },
0607 { 0, 0, 0, 0, RtemsIntrReqVectorEnable_Post_Status_Ok,
0608 RtemsIntrReqVectorEnable_Post_IsEnabled_Yes },
0609 { 0, 0, 0, 0, RtemsIntrReqVectorEnable_Post_Status_Ok,
0610 RtemsIntrReqVectorEnable_Post_IsEnabled_Maybe },
0611 { 0, 0, 0, 0, RtemsIntrReqVectorEnable_Post_Status_Unsat,
0612 RtemsIntrReqVectorEnable_Post_IsEnabled_Nop }
0613 };
0614
0615 static const uint8_t
0616 RtemsIntrReqVectorEnable_Map[] = {
0617 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0
0618 };
0619
0620 static size_t RtemsIntrReqVectorEnable_Scope( void *arg, char *buf, size_t n )
0621 {
0622 RtemsIntrReqVectorEnable_Context *ctx;
0623
0624 ctx = arg;
0625
0626 if ( ctx->Map.in_action_loop ) {
0627 return T_get_scope(
0628 RtemsIntrReqVectorEnable_PreDesc,
0629 buf,
0630 n,
0631 ctx->Map.pcs
0632 );
0633 }
0634
0635 return 0;
0636 }
0637
0638 static T_fixture RtemsIntrReqVectorEnable_Fixture = {
0639 .setup = NULL,
0640 .stop = NULL,
0641 .teardown = NULL,
0642 .scope = RtemsIntrReqVectorEnable_Scope,
0643 .initial_context = &RtemsIntrReqVectorEnable_Instance
0644 };
0645
0646 static inline RtemsIntrReqVectorEnable_Entry RtemsIntrReqVectorEnable_PopEntry(
0647 RtemsIntrReqVectorEnable_Context *ctx
0648 )
0649 {
0650 size_t index;
0651
0652 index = ctx->Map.index;
0653 ctx->Map.index = index + 1;
0654 return RtemsIntrReqVectorEnable_Entries[
0655 RtemsIntrReqVectorEnable_Map[ index ]
0656 ];
0657 }
0658
0659 static void RtemsIntrReqVectorEnable_SetPreConditionStates(
0660 RtemsIntrReqVectorEnable_Context *ctx
0661 )
0662 {
0663 ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0664
0665 if ( ctx->Map.entry.Pre_IsEnabled_NA ) {
0666 ctx->Map.pcs[ 1 ] = RtemsIntrReqVectorEnable_Pre_IsEnabled_NA;
0667 } else {
0668 ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0669 }
0670
0671 if ( ctx->Map.entry.Pre_CanEnable_NA ) {
0672 ctx->Map.pcs[ 2 ] = RtemsIntrReqVectorEnable_Pre_CanEnable_NA;
0673 } else {
0674 ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
0675 }
0676 }
0677
0678 static void RtemsIntrReqVectorEnable_TestVariant(
0679 RtemsIntrReqVectorEnable_Context *ctx
0680 )
0681 {
0682 RtemsIntrReqVectorEnable_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0683 RtemsIntrReqVectorEnable_Pre_IsEnabled_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0684 RtemsIntrReqVectorEnable_Pre_CanEnable_Prepare( ctx, ctx->Map.pcs[ 2 ] );
0685 RtemsIntrReqVectorEnable_Action( ctx );
0686 RtemsIntrReqVectorEnable_Post_Status_Check(
0687 ctx,
0688 ctx->Map.entry.Post_Status
0689 );
0690 RtemsIntrReqVectorEnable_Post_IsEnabled_Check(
0691 ctx,
0692 ctx->Map.entry.Post_IsEnabled
0693 );
0694 }
0695
0696
0697
0698
0699 T_TEST_CASE_FIXTURE(
0700 RtemsIntrReqVectorEnable,
0701 &RtemsIntrReqVectorEnable_Fixture
0702 )
0703 {
0704 RtemsIntrReqVectorEnable_Context *ctx;
0705
0706 ctx = T_fixture_context();
0707 ctx->Map.in_action_loop = true;
0708 ctx->Map.index = 0;
0709
0710 for (
0711 ctx->Map.pci[ 0 ] = RtemsIntrReqVectorEnable_Pre_Vector_Valid;
0712 ctx->Map.pci[ 0 ] < RtemsIntrReqVectorEnable_Pre_Vector_NA;
0713 ++ctx->Map.pci[ 0 ]
0714 ) {
0715 for (
0716 ctx->Map.pci[ 1 ] = RtemsIntrReqVectorEnable_Pre_IsEnabled_Yes;
0717 ctx->Map.pci[ 1 ] < RtemsIntrReqVectorEnable_Pre_IsEnabled_NA;
0718 ++ctx->Map.pci[ 1 ]
0719 ) {
0720 for (
0721 ctx->Map.pci[ 2 ] = RtemsIntrReqVectorEnable_Pre_CanEnable_Yes;
0722 ctx->Map.pci[ 2 ] < RtemsIntrReqVectorEnable_Pre_CanEnable_NA;
0723 ++ctx->Map.pci[ 2 ]
0724 ) {
0725 ctx->Map.entry = RtemsIntrReqVectorEnable_PopEntry( ctx );
0726 RtemsIntrReqVectorEnable_SetPreConditionStates( ctx );
0727 RtemsIntrReqVectorEnable_TestVariant( ctx );
0728 }
0729 }
0730 }
0731 }
0732
0733