File indexing completed on 2025-05-11 08:24:53
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 <rtems.h>
0056 #include <rtems/counter.h>
0057 #include <rtems/timecounter.h>
0058 #include <rtems/score/timecounterimpl.h>
0059
0060 #include "tx-support.h"
0061
0062 #include <rtems/test.h>
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 typedef enum {
0130 STATE_EARLY,
0131 STATE_GET_TIMECOUNT_BEFORE,
0132 STATE_GET_TIMECOUNT_BUSY,
0133 STATE_GET_TIMECOUNT_DONE,
0134 STATE_GET_TIMECOUNT_AFTER
0135 } State;
0136
0137 typedef struct {
0138 struct timecounter base;
0139 State state;
0140 uint_fast32_t busy;
0141 struct bintime tod;
0142 } Timecounter;
0143
0144 static Timecounter test_timecounter;
0145
0146 static uint32_t GetTimecount( struct timecounter *base )
0147 {
0148 Timecounter *tc;
0149
0150 tc = (Timecounter *) base;
0151
0152 if (
0153 tc->state == STATE_GET_TIMECOUNT_BEFORE &&
0154 !rtems_interrupt_is_in_progress()
0155 ) {
0156 tc->state = STATE_GET_TIMECOUNT_BUSY;
0157 T_busy( tc->busy );
0158 tc->state = STATE_GET_TIMECOUNT_DONE;
0159 }
0160
0161 return rtems_counter_read();
0162 }
0163
0164 static void InterruptPrepare( void *arg )
0165 {
0166 Timecounter *tc;
0167
0168 tc = (Timecounter *) arg;
0169 tc->state = STATE_EARLY;
0170 }
0171
0172 static void ActionRealtime( void *arg )
0173 {
0174 Timecounter *tc;
0175 struct timespec ts;
0176
0177 tc = (Timecounter *) arg;
0178 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0179 rtems_clock_get_realtime( &ts );
0180 tc->state = STATE_GET_TIMECOUNT_AFTER;
0181 }
0182
0183 static void ActionRealtimeBintime( void *arg )
0184 {
0185 Timecounter *tc;
0186 struct bintime bt;
0187
0188 tc = (Timecounter *) arg;
0189 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0190 rtems_clock_get_realtime_bintime( &bt );
0191 tc->state = STATE_GET_TIMECOUNT_AFTER;
0192 }
0193
0194 static void ActionRealtimeTimeval( void *arg )
0195 {
0196 Timecounter *tc;
0197 struct timeval tv;
0198
0199 tc = (Timecounter *) arg;
0200 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0201 rtems_clock_get_realtime_timeval( &tv );
0202 tc->state = STATE_GET_TIMECOUNT_AFTER;
0203 }
0204
0205 static void ActionMonotonic( void *arg )
0206 {
0207 Timecounter *tc;
0208 struct timespec ts;
0209
0210 tc = (Timecounter *) arg;
0211 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0212 rtems_clock_get_monotonic( &ts );
0213 tc->state = STATE_GET_TIMECOUNT_AFTER;
0214 }
0215
0216 static void ActionMonotonicBintime( void *arg )
0217 {
0218 Timecounter *tc;
0219 struct bintime bt;
0220
0221 tc = (Timecounter *) arg;
0222 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0223 rtems_clock_get_monotonic_bintime( &bt );
0224 tc->state = STATE_GET_TIMECOUNT_AFTER;
0225 }
0226
0227 static void ActionMonotonicSbintime( void *arg )
0228 {
0229 Timecounter *tc;
0230
0231 tc = (Timecounter *) arg;
0232 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0233 (void) rtems_clock_get_monotonic_sbintime();
0234 tc->state = STATE_GET_TIMECOUNT_AFTER;
0235 }
0236
0237 static void ActionMonotonicTimeval( void *arg )
0238 {
0239 Timecounter *tc;
0240 struct timeval tv;
0241
0242 tc = (Timecounter *) arg;
0243 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0244 rtems_clock_get_monotonic_timeval( &tv );
0245 tc->state = STATE_GET_TIMECOUNT_AFTER;
0246 }
0247
0248 static void ActionCoarseRealtime( void *arg )
0249 {
0250 Timecounter *tc;
0251 struct timespec ts;
0252
0253 tc = (Timecounter *) arg;
0254 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0255 rtems_clock_get_realtime_coarse( &ts );
0256 tc->state = STATE_GET_TIMECOUNT_AFTER;
0257 }
0258
0259 static void ActionCoarseRealtimeBintime( void *arg )
0260 {
0261 Timecounter *tc;
0262 struct bintime bt;
0263
0264 tc = (Timecounter *) arg;
0265 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0266 rtems_clock_get_realtime_coarse_bintime( &bt );
0267 tc->state = STATE_GET_TIMECOUNT_AFTER;
0268 }
0269
0270 static void ActionCoarseRealtimeTimeval( void *arg )
0271 {
0272 Timecounter *tc;
0273 struct timeval tv;
0274
0275 tc = (Timecounter *) arg;
0276 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0277 rtems_clock_get_realtime_coarse_timeval( &tv );
0278 tc->state = STATE_GET_TIMECOUNT_AFTER;
0279 }
0280
0281 static void ActionCoarseMonotonic( void *arg )
0282 {
0283 Timecounter *tc;
0284 struct timespec ts;
0285
0286 tc = (Timecounter *) arg;
0287 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0288 rtems_clock_get_monotonic_coarse( &ts );
0289 tc->state = STATE_GET_TIMECOUNT_AFTER;
0290 }
0291
0292 static void ActionCoarseMonotonicBintime( void *arg )
0293 {
0294 Timecounter *tc;
0295 struct bintime bt;
0296
0297 tc = (Timecounter *) arg;
0298 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0299 rtems_clock_get_monotonic_coarse_bintime( &bt );
0300 tc->state = STATE_GET_TIMECOUNT_AFTER;
0301 }
0302
0303 static void ActionCoarseMonotonicTimeval( void *arg )
0304 {
0305 Timecounter *tc;
0306 struct timeval tv;
0307
0308 tc = (Timecounter *) arg;
0309 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0310 rtems_clock_get_monotonic_coarse_timeval( &tv );
0311 tc->state = STATE_GET_TIMECOUNT_AFTER;
0312 }
0313
0314 static void ActionBootTime( void *arg )
0315 {
0316 Timecounter *tc;
0317 struct timespec ts;
0318
0319 tc = (Timecounter *) arg;
0320 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0321 rtems_clock_get_boot_time( &ts );
0322 tc->state = STATE_GET_TIMECOUNT_AFTER;
0323 }
0324
0325 static void ActionBootTimeBintime( void *arg )
0326 {
0327 Timecounter *tc;
0328 struct bintime bt;
0329
0330 tc = (Timecounter *) arg;
0331 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0332 rtems_clock_get_boot_time_bintime( &bt );
0333 tc->state = STATE_GET_TIMECOUNT_AFTER;
0334 }
0335
0336 static void ActionBootTimeTimeval( void *arg )
0337 {
0338 Timecounter *tc;
0339 struct timeval tv;
0340
0341 tc = (Timecounter *) arg;
0342 tc->state = STATE_GET_TIMECOUNT_BEFORE;
0343 rtems_clock_get_boot_time_timeval( &tv );
0344 tc->state = STATE_GET_TIMECOUNT_AFTER;
0345 }
0346
0347 static void CallTimcounterWindupTwice( const Timecounter *tc )
0348 {
0349 ISR_lock_Context lock_context;
0350
0351
0352
0353
0354
0355
0356 _Timecounter_Acquire( &lock_context );
0357 _Timecounter_Set_clock( &tc->tod, &lock_context );
0358
0359 _Timecounter_Acquire( &lock_context );
0360 _Timecounter_Set_clock( &tc->tod, &lock_context );
0361 }
0362
0363 static T_interrupt_test_state Interrupt( void *arg )
0364 {
0365 Timecounter *tc;
0366 State state;
0367
0368 tc = (Timecounter *) arg;
0369 state = tc->state;
0370
0371 if ( state == STATE_EARLY || state == STATE_GET_TIMECOUNT_BEFORE ) {
0372 return T_INTERRUPT_TEST_EARLY;
0373 }
0374
0375 if ( state == STATE_GET_TIMECOUNT_BUSY ) {
0376 CallTimcounterWindupTwice( tc );
0377
0378 return T_INTERRUPT_TEST_DONE;
0379 }
0380
0381 return T_INTERRUPT_TEST_LATE;
0382 }
0383
0384 static T_interrupt_test_state InterruptCoarse( void *arg )
0385 {
0386 Timecounter *tc;
0387 State state;
0388
0389 tc = (Timecounter *) arg;
0390 state = tc->state;
0391
0392 if ( state == STATE_EARLY ) {
0393 return T_INTERRUPT_TEST_EARLY;
0394 }
0395
0396 if ( state == STATE_GET_TIMECOUNT_BEFORE ) {
0397 CallTimcounterWindupTwice( tc );
0398
0399 return T_INTERRUPT_TEST_DONE;
0400 }
0401
0402 return T_INTERRUPT_TEST_LATE;
0403 }
0404
0405 static bool InterruptTest(
0406 const T_interrupt_test_config *config,
0407 void *arg,
0408 uint32_t iterations
0409 )
0410 {
0411 uint32_t i;
0412 bool ok;
0413
0414 ok = false;
0415
0416 for ( i = 0; i < iterations; ++i ) {
0417 T_interrupt_test_state test_state;
0418
0419 test_state = T_interrupt_test( config, arg );
0420 ok = ok || test_state == T_INTERRUPT_TEST_DONE;
0421 }
0422
0423 return ok;
0424 }
0425
0426
0427
0428
0429
0430 static void ScoreTimecounterValGet_Action_0( void )
0431 {
0432 T_interrupt_test_config config = {
0433 .prepare = InterruptPrepare,
0434 .interrupt = Interrupt,
0435 .max_iteration_count = 10000
0436 };
0437 Timecounter *tc;
0438
0439 tc = &test_timecounter;
0440 tc->base.tc_get_timecount = GetTimecount;
0441 tc->base.tc_counter_mask = 0xffffffff;
0442 tc->base.tc_frequency = rtems_counter_frequency();
0443 tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER + 1;
0444 tc->busy = T_get_one_clock_tick_busy() / 10;
0445 rtems_clock_get_realtime_bintime( &tc->tod );
0446 rtems_timecounter_install( &tc->base );
0447
0448
0449
0450
0451
0452 config.action = ActionRealtime;
0453 T_true( InterruptTest( &config, tc, 1 ) );
0454
0455
0456
0457
0458
0459 config.action = ActionRealtimeBintime;
0460 T_true( InterruptTest( &config, tc, 1 ) );
0461
0462
0463
0464
0465
0466 config.action = ActionRealtimeTimeval;
0467 T_true( InterruptTest( &config, tc, 1 ) );
0468
0469
0470
0471
0472
0473 config.action = ActionMonotonic;
0474 T_true( InterruptTest( &config, tc, 1 ) );
0475
0476
0477
0478
0479
0480 config.action = ActionMonotonicBintime;
0481 T_true( InterruptTest( &config, tc, 1 ) );
0482
0483
0484
0485
0486
0487 config.action = ActionMonotonicSbintime;
0488 T_true( InterruptTest( &config, tc, 1 ) );
0489
0490
0491
0492
0493
0494 config.action = ActionMonotonicTimeval;
0495 T_true( InterruptTest( &config, tc, 1 ) );
0496
0497
0498
0499
0500 config.interrupt = InterruptCoarse;
0501
0502
0503
0504
0505
0506 config.action = ActionCoarseRealtime;
0507 T_true( InterruptTest( &config, tc, 10 ) );
0508
0509
0510
0511
0512
0513 config.action = ActionCoarseRealtimeBintime;
0514 T_true( InterruptTest( &config, tc, 10 ) );
0515
0516
0517
0518
0519
0520 config.action = ActionCoarseRealtimeTimeval;
0521 T_true( InterruptTest( &config, tc, 10 ) );
0522
0523
0524
0525
0526
0527 config.action = ActionCoarseMonotonic;
0528 T_true( InterruptTest( &config, tc, 10 ) );
0529
0530
0531
0532
0533
0534 config.action = ActionCoarseMonotonicBintime;
0535 T_true( InterruptTest( &config, tc, 10 ) );
0536
0537
0538
0539
0540
0541 config.action = ActionCoarseMonotonicTimeval;
0542 T_true( InterruptTest( &config, tc, 10 ) );
0543
0544
0545
0546
0547
0548 config.action = ActionBootTime;
0549 T_true( InterruptTest( &config, tc, 10 ) );
0550
0551
0552
0553
0554
0555 config.action = ActionBootTimeBintime;
0556 T_true( InterruptTest( &config, tc, 10 ) );
0557
0558
0559
0560
0561
0562 config.action = ActionBootTimeTimeval;
0563 T_true( InterruptTest( &config, tc, 10 ) );
0564 }
0565
0566
0567
0568
0569 T_TEST_CASE( ScoreTimecounterValGet )
0570 {
0571 ScoreTimecounterValGet_Action_0();
0572 }
0573
0574