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 RtemsIntrReqClear_Pre_Vector_Valid,
0073 RtemsIntrReqClear_Pre_Vector_Invalid,
0074 RtemsIntrReqClear_Pre_Vector_NA
0075 } RtemsIntrReqClear_Pre_Vector;
0076
0077 typedef enum {
0078 RtemsIntrReqClear_Pre_CanClear_Yes,
0079 RtemsIntrReqClear_Pre_CanClear_No,
0080 RtemsIntrReqClear_Pre_CanClear_NA
0081 } RtemsIntrReqClear_Pre_CanClear;
0082
0083 typedef enum {
0084 RtemsIntrReqClear_Post_Status_Ok,
0085 RtemsIntrReqClear_Post_Status_InvId,
0086 RtemsIntrReqClear_Post_Status_Unsat,
0087 RtemsIntrReqClear_Post_Status_NA
0088 } RtemsIntrReqClear_Post_Status;
0089
0090 typedef enum {
0091 RtemsIntrReqClear_Post_Cleared_Yes,
0092 RtemsIntrReqClear_Post_Cleared_No,
0093 RtemsIntrReqClear_Post_Cleared_NA
0094 } RtemsIntrReqClear_Post_Cleared;
0095
0096 typedef struct {
0097 uint8_t Skip : 1;
0098 uint8_t Pre_Vector_NA : 1;
0099 uint8_t Pre_CanClear_NA : 1;
0100 uint8_t Post_Status : 2;
0101 uint8_t Post_Cleared : 2;
0102 } RtemsIntrReqClear_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 RtemsIntrReqClear_Entry entry;
0161
0162
0163
0164
0165
0166 bool skip;
0167 } Map;
0168 } RtemsIntrReqClear_Context;
0169
0170 static RtemsIntrReqClear_Context
0171 RtemsIntrReqClear_Instance;
0172
0173 static const char * const RtemsIntrReqClear_PreDesc_Vector[] = {
0174 "Valid",
0175 "Invalid",
0176 "NA"
0177 };
0178
0179 static const char * const RtemsIntrReqClear_PreDesc_CanClear[] = {
0180 "Yes",
0181 "No",
0182 "NA"
0183 };
0184
0185 static const char * const * const RtemsIntrReqClear_PreDesc[] = {
0186 RtemsIntrReqClear_PreDesc_Vector,
0187 RtemsIntrReqClear_PreDesc_CanClear,
0188 NULL
0189 };
0190
0191 typedef RtemsIntrReqClear_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 Clear( const Context *ctx )
0234 {
0235 rtems_status_code sc;
0236
0237 sc = rtems_interrupt_clear( ctx->vector );
0238 T_rsc_success( sc );
0239 }
0240
0241 static void EntryRoutine( void *arg )
0242 {
0243 Context *ctx;
0244 uint32_t count;
0245
0246 (void) arg;
0247 ctx = T_fixture_context();
0248
0249 count = ctx->interrupt_count;
0250 ctx->interrupt_count = count + 1;
0251
0252 if ( ctx->do_clear ) {
0253 rtems_status_code sc;
0254
0255 sc = rtems_interrupt_clear( ctx->vector );
0256 T_rsc_success( sc );
0257 }
0258
0259 if ( count > 2 ) {
0260
0261 Disable( ctx );
0262 }
0263 }
0264
0265 static void CheckUnsatisfied( const Context *ctx )
0266 {
0267 rtems_status_code sc;
0268 bool pending_before;
0269 bool pending_after;
0270
0271 pending_before = true;
0272 sc = rtems_interrupt_is_pending( ctx->vector, &pending_before );
0273 T_rsc_success( sc );
0274
0275 sc = rtems_interrupt_clear( ctx->vector );
0276 T_rsc( sc, RTEMS_UNSATISFIED );
0277
0278 pending_after = !pending_before;
0279 sc = rtems_interrupt_is_pending( ctx->vector, &pending_after );
0280 T_rsc_success( sc );
0281
0282 T_eq( pending_before, pending_after );
0283 }
0284
0285 static void CheckClear(
0286 Context *ctx,
0287 const rtems_interrupt_attributes *attr,
0288 bool has_installed_entries
0289 )
0290 {
0291 rtems_status_code sc;
0292
0293 if ( !attr->can_clear ) {
0294 CheckUnsatisfied( ctx );
0295 } else if ( has_installed_entries ) {
0296
0297 } else if ( !attr->is_maskable ) {
0298
0299 } else if ( IsPending( ctx ) ) {
0300
0301
0302
0303
0304 } else if ( attr->can_disable ) {
0305 rtems_interrupt_entry entry;
0306 rtems_interrupt_level level;
0307
0308 ctx->interrupt_count = 0;
0309 ctx->do_clear = !attr->cleared_by_acknowledge;
0310 rtems_interrupt_entry_initialize( &entry, EntryRoutine, ctx, "Info" );
0311 sc = rtems_interrupt_entry_install(
0312 ctx->vector,
0313 RTEMS_INTERRUPT_UNIQUE,
0314 &entry
0315 );
0316 T_rsc_success( sc );
0317
0318 Clear( ctx );
0319
0320 if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
0321 T_false( IsPending( ctx ) );
0322 Clear( ctx );
0323 T_false( IsPending( ctx ) );
0324
0325 if ( attr->can_disable ) {
0326 Disable( ctx );
0327 Raise( ctx );
0328 T_true( IsPending( ctx ) );
0329 Clear( ctx );
0330 T_false( IsPending( ctx ) );
0331
0332 sc = rtems_interrupt_vector_enable( ctx->vector );
0333 T_rsc_success( sc );
0334 }
0335
0336 T_false( IsPending( ctx ) );
0337 Clear( ctx );
0338 T_false( IsPending( ctx ) );
0339
0340 rtems_interrupt_local_disable( level );
0341 Raise( ctx );
0342 T_true( IsPending( ctx ) );
0343 Clear( ctx );
0344 T_false( IsPending( ctx ) );
0345 rtems_interrupt_local_enable( level );
0346
0347 T_false( IsPending( ctx ) );
0348 Clear( ctx );
0349 T_false( IsPending( ctx ) );
0350 }
0351
0352 sc = rtems_interrupt_entry_remove( ctx->vector, &entry );
0353 T_rsc_success( sc );
0354 }
0355 }
0356
0357 static void RtemsIntrReqClear_Pre_Vector_Prepare(
0358 RtemsIntrReqClear_Context *ctx,
0359 RtemsIntrReqClear_Pre_Vector state
0360 )
0361 {
0362 switch ( state ) {
0363 case RtemsIntrReqClear_Pre_Vector_Valid: {
0364
0365
0366
0367 ctx->valid_vector = true;
0368 break;
0369 }
0370
0371 case RtemsIntrReqClear_Pre_Vector_Invalid: {
0372
0373
0374
0375
0376 ctx->valid_vector = false;
0377 break;
0378 }
0379
0380 case RtemsIntrReqClear_Pre_Vector_NA:
0381 break;
0382 }
0383 }
0384
0385 static void RtemsIntrReqClear_Pre_CanClear_Prepare(
0386 RtemsIntrReqClear_Context *ctx,
0387 RtemsIntrReqClear_Pre_CanClear state
0388 )
0389 {
0390 switch ( state ) {
0391 case RtemsIntrReqClear_Pre_CanClear_Yes: {
0392
0393
0394
0395
0396
0397
0398
0399
0400 break;
0401 }
0402
0403 case RtemsIntrReqClear_Pre_CanClear_No: {
0404
0405
0406
0407
0408
0409
0410
0411
0412 break;
0413 }
0414
0415 case RtemsIntrReqClear_Pre_CanClear_NA:
0416 break;
0417 }
0418 }
0419
0420 static void RtemsIntrReqClear_Post_Status_Check(
0421 RtemsIntrReqClear_Context *ctx,
0422 RtemsIntrReqClear_Post_Status state
0423 )
0424 {
0425 switch ( state ) {
0426 case RtemsIntrReqClear_Post_Status_Ok: {
0427
0428
0429
0430
0431
0432 break;
0433 }
0434
0435 case RtemsIntrReqClear_Post_Status_InvId: {
0436
0437
0438
0439
0440 T_rsc( ctx->status, RTEMS_INVALID_ID );
0441 break;
0442 }
0443
0444 case RtemsIntrReqClear_Post_Status_Unsat: {
0445
0446
0447
0448
0449
0450 break;
0451 }
0452
0453 case RtemsIntrReqClear_Post_Status_NA:
0454 break;
0455 }
0456 }
0457
0458 static void RtemsIntrReqClear_Post_Cleared_Check(
0459 RtemsIntrReqClear_Context *ctx,
0460 RtemsIntrReqClear_Post_Cleared state
0461 )
0462 {
0463 switch ( state ) {
0464 case RtemsIntrReqClear_Post_Cleared_Yes: {
0465
0466
0467
0468
0469
0470
0471
0472 break;
0473 }
0474
0475 case RtemsIntrReqClear_Post_Cleared_No: {
0476
0477
0478
0479
0480
0481
0482 break;
0483 }
0484
0485 case RtemsIntrReqClear_Post_Cleared_NA:
0486 break;
0487 }
0488 }
0489
0490 static void RtemsIntrReqClear_Action( RtemsIntrReqClear_Context *ctx )
0491 {
0492 if ( ctx->valid_vector ) {
0493 for (
0494 ctx->vector = 0;
0495 ctx->vector < BSP_INTERRUPT_VECTOR_COUNT;
0496 ++ctx->vector
0497 ) {
0498 rtems_status_code sc;
0499 rtems_interrupt_attributes attr;
0500 bool has_installed_entries;
0501
0502 memset( &attr, 0, sizeof( attr ) );
0503 sc = rtems_interrupt_get_attributes( ctx->vector, &attr );
0504
0505 if ( sc == RTEMS_INVALID_ID ) {
0506 continue;
0507 }
0508
0509 T_rsc_success( sc );
0510
0511 has_installed_entries = HasInterruptVectorEntriesInstalled( ctx->vector );
0512 CheckClear( ctx, &attr, has_installed_entries );
0513 }
0514 } else {
0515 ctx->vector = BSP_INTERRUPT_VECTOR_COUNT;
0516 ctx->status = rtems_interrupt_clear( ctx->vector );
0517 }
0518 }
0519
0520 static const RtemsIntrReqClear_Entry
0521 RtemsIntrReqClear_Entries[] = {
0522 { 0, 0, 1, RtemsIntrReqClear_Post_Status_InvId,
0523 RtemsIntrReqClear_Post_Cleared_NA },
0524 { 0, 0, 0, RtemsIntrReqClear_Post_Status_Ok,
0525 RtemsIntrReqClear_Post_Cleared_Yes },
0526 { 0, 0, 0, RtemsIntrReqClear_Post_Status_Unsat,
0527 RtemsIntrReqClear_Post_Cleared_No }
0528 };
0529
0530 static const uint8_t
0531 RtemsIntrReqClear_Map[] = {
0532 1, 2, 0, 0
0533 };
0534
0535 static size_t RtemsIntrReqClear_Scope( void *arg, char *buf, size_t n )
0536 {
0537 RtemsIntrReqClear_Context *ctx;
0538
0539 ctx = arg;
0540
0541 if ( ctx->Map.in_action_loop ) {
0542 return T_get_scope( RtemsIntrReqClear_PreDesc, buf, n, ctx->Map.pcs );
0543 }
0544
0545 return 0;
0546 }
0547
0548 static T_fixture RtemsIntrReqClear_Fixture = {
0549 .setup = NULL,
0550 .stop = NULL,
0551 .teardown = NULL,
0552 .scope = RtemsIntrReqClear_Scope,
0553 .initial_context = &RtemsIntrReqClear_Instance
0554 };
0555
0556 static inline RtemsIntrReqClear_Entry RtemsIntrReqClear_PopEntry(
0557 RtemsIntrReqClear_Context *ctx
0558 )
0559 {
0560 size_t index;
0561
0562 index = ctx->Map.index;
0563 ctx->Map.index = index + 1;
0564 return RtemsIntrReqClear_Entries[
0565 RtemsIntrReqClear_Map[ index ]
0566 ];
0567 }
0568
0569 static void RtemsIntrReqClear_SetPreConditionStates(
0570 RtemsIntrReqClear_Context *ctx
0571 )
0572 {
0573 ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0574
0575 if ( ctx->Map.entry.Pre_CanClear_NA ) {
0576 ctx->Map.pcs[ 1 ] = RtemsIntrReqClear_Pre_CanClear_NA;
0577 } else {
0578 ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0579 }
0580 }
0581
0582 static void RtemsIntrReqClear_TestVariant( RtemsIntrReqClear_Context *ctx )
0583 {
0584 RtemsIntrReqClear_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0585 RtemsIntrReqClear_Pre_CanClear_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0586 RtemsIntrReqClear_Action( ctx );
0587 RtemsIntrReqClear_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0588 RtemsIntrReqClear_Post_Cleared_Check( ctx, ctx->Map.entry.Post_Cleared );
0589 }
0590
0591
0592
0593
0594 T_TEST_CASE_FIXTURE( RtemsIntrReqClear, &RtemsIntrReqClear_Fixture )
0595 {
0596 RtemsIntrReqClear_Context *ctx;
0597
0598 ctx = T_fixture_context();
0599 ctx->Map.in_action_loop = true;
0600 ctx->Map.index = 0;
0601
0602 for (
0603 ctx->Map.pci[ 0 ] = RtemsIntrReqClear_Pre_Vector_Valid;
0604 ctx->Map.pci[ 0 ] < RtemsIntrReqClear_Pre_Vector_NA;
0605 ++ctx->Map.pci[ 0 ]
0606 ) {
0607 for (
0608 ctx->Map.pci[ 1 ] = RtemsIntrReqClear_Pre_CanClear_Yes;
0609 ctx->Map.pci[ 1 ] < RtemsIntrReqClear_Pre_CanClear_NA;
0610 ++ctx->Map.pci[ 1 ]
0611 ) {
0612 ctx->Map.entry = RtemsIntrReqClear_PopEntry( ctx );
0613 RtemsIntrReqClear_SetPreConditionStates( ctx );
0614 RtemsIntrReqClear_TestVariant( ctx );
0615 }
0616 }
0617 }
0618
0619