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