Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:53

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup ScoreTimecounterValGet
0007  */
0008 
0009 /*
0010  * Copyright (C) 2021 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 /*
0035  * This file is part of the RTEMS quality process and was automatically
0036  * generated.  If you find something that needs to be fixed or
0037  * worded better please post a report or patch to an RTEMS mailing list
0038  * or raise a bug report:
0039  *
0040  * https://www.rtems.org/bugs.html
0041  *
0042  * For information on updating and regenerating please refer to the How-To
0043  * section in the Software Requirements Engineering chapter of the
0044  * RTEMS Software Engineering manual.  The manual is provided as a part of
0045  * a release.  For development sources please refer to the online
0046  * documentation at:
0047  *
0048  * https://docs.rtems.org
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  * @defgroup ScoreTimecounterValGet spec:/score/timecounter/val/get
0066  *
0067  * @ingroup TestsuitesValidationTimecounter1
0068  *
0069  * @brief Tests directives to get a time value.
0070  *
0071  * This test case performs the following actions:
0072  *
0073  * - Install a timecounter which can be used to perform interrut tests for the
0074  *   get time directives.
0075  *
0076  *   - Try to interrupt the rtems_clock_get_realtime() directive to provoke a
0077  *     change in the timehand generation number.
0078  *
0079  *   - Try to interrupt the rtems_clock_get_realtime_bintime() directive to
0080  *     provoke a change in the timehand generation number.
0081  *
0082  *   - Try to interrupt the rtems_clock_get_realtime_timeval() directive to
0083  *     provoke a change in the timehand generation number.
0084  *
0085  *   - Try to interrupt the rtems_clock_get_monotonic() directive to provoke a
0086  *     change in the timehand generation number.
0087  *
0088  *   - Try to interrupt the rtems_clock_get_monotonic_bintime() directive to
0089  *     provoke a change in the timehand generation number.
0090  *
0091  *   - Try to interrupt the rtems_clock_get_monotonic_sbintime() directive to
0092  *     provoke a change in the timehand generation number.
0093  *
0094  *   - Try to interrupt the rtems_clock_get_monotonic_timeval() directive to
0095  *     provoke a change in the timehand generation number.
0096  *
0097  *   - Prepare for the coarse get time directives.
0098  *
0099  *   - Try to interrupt the rtems_clock_get_realtime_coarse() directive to
0100  *     provoke a change in the timehand generation number.
0101  *
0102  *   - Try to interrupt the rtems_clock_get_realtime_coarse_bintime() directive
0103  *     to provoke a change in the timehand generation number.
0104  *
0105  *   - Try to interrupt the rtems_clock_get_realtime_coarse_timeval() directive
0106  *     to provoke a change in the timehand generation number.
0107  *
0108  *   - Try to interrupt the rtems_clock_get_monotonic_coarse() directive to
0109  *     provoke a change in the timehand generation number.
0110  *
0111  *   - Try to interrupt the rtems_clock_get_monotonic_coarse_bintime()
0112  *     directive to provoke a change in the timehand generation number.
0113  *
0114  *   - Try to interrupt the rtems_clock_get_monotonic_coarse_timeval()
0115  *     directive to provoke a change in the timehand generation number.
0116  *
0117  *   - Try to interrupt the rtems_clock_get_boot_time() directive to provoke a
0118  *     change in the timehand generation number.
0119  *
0120  *   - Try to interrupt the rtems_clock_get_boot_time_bintime() directive to
0121  *     provoke a change in the timehand generation number.
0122  *
0123  *   - Try to interrupt the rtems_clock_get_boot_time_timeval() directive to
0124  *     provoke a change in the timehand generation number.
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    * Make sure that tc_windup() was called at least twice to increment the
0353    * generation number for * both timehands.
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  * @brief Install a timecounter which can be used to perform interrut tests for
0428  *   the get time directives.
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    * Try to interrupt the rtems_clock_get_realtime() directive to provoke a
0450    * change in the timehand generation number.
0451    */
0452   config.action = ActionRealtime;
0453   T_true( InterruptTest( &config, tc, 1 ) );
0454 
0455   /*
0456    * Try to interrupt the rtems_clock_get_realtime_bintime() directive to
0457    * provoke a change in the timehand generation number.
0458    */
0459   config.action = ActionRealtimeBintime;
0460   T_true( InterruptTest( &config, tc, 1 ) );
0461 
0462   /*
0463    * Try to interrupt the rtems_clock_get_realtime_timeval() directive to
0464    * provoke a change in the timehand generation number.
0465    */
0466   config.action = ActionRealtimeTimeval;
0467   T_true( InterruptTest( &config, tc, 1 ) );
0468 
0469   /*
0470    * Try to interrupt the rtems_clock_get_monotonic() directive to provoke a
0471    * change in the timehand generation number.
0472    */
0473   config.action = ActionMonotonic;
0474   T_true( InterruptTest( &config, tc, 1 ) );
0475 
0476   /*
0477    * Try to interrupt the rtems_clock_get_monotonic_bintime() directive to
0478    * provoke a change in the timehand generation number.
0479    */
0480   config.action = ActionMonotonicBintime;
0481   T_true( InterruptTest( &config, tc, 1 ) );
0482 
0483   /*
0484    * Try to interrupt the rtems_clock_get_monotonic_sbintime() directive to
0485    * provoke a change in the timehand generation number.
0486    */
0487   config.action = ActionMonotonicSbintime;
0488   T_true( InterruptTest( &config, tc, 1 ) );
0489 
0490   /*
0491    * Try to interrupt the rtems_clock_get_monotonic_timeval() directive to
0492    * provoke a change in the timehand generation number.
0493    */
0494   config.action = ActionMonotonicTimeval;
0495   T_true( InterruptTest( &config, tc, 1 ) );
0496 
0497   /*
0498    * Prepare for the coarse get time directives.
0499    */
0500   config.interrupt = InterruptCoarse;
0501 
0502   /*
0503    * Try to interrupt the rtems_clock_get_realtime_coarse() directive to
0504    * provoke a change in the timehand generation number.
0505    */
0506   config.action = ActionCoarseRealtime;
0507   T_true( InterruptTest( &config, tc, 10 ) );
0508 
0509   /*
0510    * Try to interrupt the rtems_clock_get_realtime_coarse_bintime() directive
0511    * to provoke a change in the timehand generation number.
0512    */
0513   config.action = ActionCoarseRealtimeBintime;
0514   T_true( InterruptTest( &config, tc, 10 ) );
0515 
0516   /*
0517    * Try to interrupt the rtems_clock_get_realtime_coarse_timeval() directive
0518    * to provoke a change in the timehand generation number.
0519    */
0520   config.action = ActionCoarseRealtimeTimeval;
0521   T_true( InterruptTest( &config, tc, 10 ) );
0522 
0523   /*
0524    * Try to interrupt the rtems_clock_get_monotonic_coarse() directive to
0525    * provoke a change in the timehand generation number.
0526    */
0527   config.action = ActionCoarseMonotonic;
0528   T_true( InterruptTest( &config, tc, 10 ) );
0529 
0530   /*
0531    * Try to interrupt the rtems_clock_get_monotonic_coarse_bintime() directive
0532    * to provoke a change in the timehand generation number.
0533    */
0534   config.action = ActionCoarseMonotonicBintime;
0535   T_true( InterruptTest( &config, tc, 10 ) );
0536 
0537   /*
0538    * Try to interrupt the rtems_clock_get_monotonic_coarse_timeval() directive
0539    * to provoke a change in the timehand generation number.
0540    */
0541   config.action = ActionCoarseMonotonicTimeval;
0542   T_true( InterruptTest( &config, tc, 10 ) );
0543 
0544   /*
0545    * Try to interrupt the rtems_clock_get_boot_time() directive to provoke a
0546    * change in the timehand generation number.
0547    */
0548   config.action = ActionBootTime;
0549   T_true( InterruptTest( &config, tc, 10 ) );
0550 
0551   /*
0552    * Try to interrupt the rtems_clock_get_boot_time_bintime() directive to
0553    * provoke a change in the timehand generation number.
0554    */
0555   config.action = ActionBootTimeBintime;
0556   T_true( InterruptTest( &config, tc, 10 ) );
0557 
0558   /*
0559    * Try to interrupt the rtems_clock_get_boot_time_timeval() directive to
0560    * provoke a change in the timehand generation number.
0561    */
0562   config.action = ActionBootTimeTimeval;
0563   T_true( InterruptTest( &config, tc, 10 ) );
0564 }
0565 
0566 /**
0567  * @fn void T_case_body_ScoreTimecounterValGet( void )
0568  */
0569 T_TEST_CASE( ScoreTimecounterValGet )
0570 {
0571   ScoreTimecounterValGet_Action_0();
0572 }
0573 
0574 /** @} */