Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RtemsIntrReqRaise
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 <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  * @defgroup RtemsIntrReqRaise spec:/rtems/intr/req/raise
0065  *
0066  * @ingroup TestsuitesValidationIntr
0067  *
0068  * @{
0069  */
0070 
0071 typedef enum {
0072   RtemsIntrReqRaise_Pre_Vector_Valid,
0073   RtemsIntrReqRaise_Pre_Vector_Invalid,
0074   RtemsIntrReqRaise_Pre_Vector_NA
0075 } RtemsIntrReqRaise_Pre_Vector;
0076 
0077 typedef enum {
0078   RtemsIntrReqRaise_Pre_CanRaise_Yes,
0079   RtemsIntrReqRaise_Pre_CanRaise_No,
0080   RtemsIntrReqRaise_Pre_CanRaise_NA
0081 } RtemsIntrReqRaise_Pre_CanRaise;
0082 
0083 typedef enum {
0084   RtemsIntrReqRaise_Post_Status_Ok,
0085   RtemsIntrReqRaise_Post_Status_InvId,
0086   RtemsIntrReqRaise_Post_Status_Unsat,
0087   RtemsIntrReqRaise_Post_Status_NA
0088 } RtemsIntrReqRaise_Post_Status;
0089 
0090 typedef enum {
0091   RtemsIntrReqRaise_Post_Pending_Yes,
0092   RtemsIntrReqRaise_Post_Pending_No,
0093   RtemsIntrReqRaise_Post_Pending_NA
0094 } RtemsIntrReqRaise_Post_Pending;
0095 
0096 typedef struct {
0097   uint8_t Skip : 1;
0098   uint8_t Pre_Vector_NA : 1;
0099   uint8_t Pre_CanRaise_NA : 1;
0100   uint8_t Post_Status : 2;
0101   uint8_t Post_Pending : 2;
0102 } RtemsIntrReqRaise_Entry;
0103 
0104 /**
0105  * @brief Test context for spec:/rtems/intr/req/raise test case.
0106  */
0107 typedef struct {
0108   /**
0109    * @brief This member contains the count of serviced interrupts.
0110    */
0111   volatile uint32_t interrupt_count;
0112 
0113   /**
0114    * @brief If this member is true, then the interrupt shall be cleared.
0115    */
0116   bool do_clear;
0117 
0118   /**
0119    * @brief This member contains the current vector number.
0120    */
0121   rtems_vector_number vector;
0122 
0123   /**
0124    * @brief If this member is true, then the ``vector`` parameter shall be
0125    *   valid.
0126    */
0127   bool valid_vector;
0128 
0129   /**
0130    * @brief This member contains the return value of the
0131    *   rtems_interrupt_raise() call.
0132    */
0133   rtems_status_code status;
0134 
0135   struct {
0136     /**
0137      * @brief This member defines the pre-condition indices for the next
0138      *   action.
0139      */
0140     size_t pci[ 2 ];
0141 
0142     /**
0143      * @brief This member defines the pre-condition states for the next action.
0144      */
0145     size_t pcs[ 2 ];
0146 
0147     /**
0148      * @brief If this member is true, then the test action loop is executed.
0149      */
0150     bool in_action_loop;
0151 
0152     /**
0153      * @brief This member contains the next transition map index.
0154      */
0155     size_t index;
0156 
0157     /**
0158      * @brief This member contains the current transition map entry.
0159      */
0160     RtemsIntrReqRaise_Entry entry;
0161 
0162     /**
0163      * @brief If this member is true, then the current transition variant
0164      *   should be skipped.
0165      */
0166     bool skip;
0167   } Map;
0168 } RtemsIntrReqRaise_Context;
0169 
0170 static RtemsIntrReqRaise_Context
0171   RtemsIntrReqRaise_Instance;
0172 
0173 static const char * const RtemsIntrReqRaise_PreDesc_Vector[] = {
0174   "Valid",
0175   "Invalid",
0176   "NA"
0177 };
0178 
0179 static const char * const RtemsIntrReqRaise_PreDesc_CanRaise[] = {
0180   "Yes",
0181   "No",
0182   "NA"
0183 };
0184 
0185 static const char * const * const RtemsIntrReqRaise_PreDesc[] = {
0186   RtemsIntrReqRaise_PreDesc_Vector,
0187   RtemsIntrReqRaise_PreDesc_CanRaise,
0188   NULL
0189 };
0190 
0191 typedef RtemsIntrReqRaise_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 EntryRoutine( void *arg )
0234 {
0235   Context *ctx;
0236   uint32_t count;
0237 
0238   (void) arg;
0239   ctx = T_fixture_context();
0240 
0241   count = ctx->interrupt_count;
0242   ctx->interrupt_count = count + 1;
0243 
0244   if ( ctx->do_clear ) {
0245     rtems_status_code sc;
0246 
0247     sc = rtems_interrupt_clear( ctx->vector );
0248     T_rsc_success( sc );
0249   }
0250 
0251   if ( count > 2 ) {
0252     /* Some interrupts are probably cased by a peripheral */
0253     Disable( ctx );
0254   }
0255 }
0256 
0257 static void CheckUnsatisfied( const Context *ctx )
0258 {
0259   rtems_status_code sc;
0260   bool              pending_before;
0261   bool              pending_after;
0262 
0263   pending_before = true;
0264   sc = rtems_interrupt_is_pending( ctx->vector, &pending_before );
0265   T_rsc_success( sc );
0266 
0267   sc = rtems_interrupt_raise( ctx->vector );
0268   T_rsc( sc, RTEMS_UNSATISFIED );
0269 
0270   pending_after = !pending_before;
0271   sc = rtems_interrupt_is_pending( ctx->vector, &pending_after );
0272   T_rsc_success( sc );
0273 
0274   T_eq( pending_before, pending_after );
0275 }
0276 
0277 static void CheckRaise(
0278   Context                          *ctx,
0279   const rtems_interrupt_attributes *attr,
0280   bool                              has_installed_entries
0281 )
0282 {
0283   rtems_status_code sc;
0284 
0285   if ( !attr->can_raise ) {
0286     CheckUnsatisfied( ctx );
0287   } else if ( has_installed_entries ) {
0288     /* We cannot test this vector, since it is used by a device driver */
0289   } else if ( !attr->is_maskable ) {
0290     /* We can only safely test maskable interrupts */
0291   } else if ( IsPending( ctx ) ) {
0292     /*
0293      * If there is already an interrupt pending, then it is probably raised
0294      * by a peripheral which we cannot control.
0295      */
0296   } else if (
0297     attr->can_disable && ( attr->can_clear || attr->cleared_by_acknowledge )
0298   ) {
0299     rtems_interrupt_entry entry;
0300     rtems_interrupt_level level;
0301 
0302     ctx->interrupt_count = 0;
0303     ctx->do_clear = attr->can_clear && !attr->cleared_by_acknowledge;
0304     rtems_interrupt_entry_initialize( &entry, EntryRoutine, ctx, "Info" );
0305     sc = rtems_interrupt_entry_install(
0306       ctx->vector,
0307       RTEMS_INTERRUPT_UNIQUE,
0308       &entry
0309     );
0310     T_rsc_success( sc );
0311 
0312     if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
0313       Disable( ctx );
0314       Raise( ctx );
0315 
0316       /*
0317        * Some interrupt controllers will signal a pending interrupt if it is
0318        * disabled (for example ARM GIC), others will not signal a pending
0319        * interrupt if it is disabled (for example Freescale/NXP MPIC).
0320        */
0321       (void) IsPending( ctx );
0322 
0323       sc = rtems_interrupt_vector_enable( ctx->vector );
0324       T_rsc_success( sc );
0325 
0326       while ( ctx->interrupt_count < 1 ) {
0327         /* Wait */
0328       }
0329 
0330       T_false( IsPending( ctx ) );
0331 
0332       rtems_interrupt_local_disable( level );
0333       Raise( ctx );
0334       T_true( IsPending( ctx ) );
0335       rtems_interrupt_local_enable( level );
0336 
0337       while ( ctx->interrupt_count < 2 ) {
0338         /* Wait */
0339       }
0340 
0341       T_false( IsPending( ctx ) );
0342     }
0343 
0344     sc = rtems_interrupt_entry_remove( ctx->vector, &entry );
0345     T_rsc_success( sc );
0346   }
0347 }
0348 
0349 static void RtemsIntrReqRaise_Pre_Vector_Prepare(
0350   RtemsIntrReqRaise_Context   *ctx,
0351   RtemsIntrReqRaise_Pre_Vector state
0352 )
0353 {
0354   switch ( state ) {
0355     case RtemsIntrReqRaise_Pre_Vector_Valid: {
0356       /*
0357        * While the ``vector`` parameter is associated with an interrupt vector.
0358        */
0359       ctx->valid_vector = true;
0360       break;
0361     }
0362 
0363     case RtemsIntrReqRaise_Pre_Vector_Invalid: {
0364       /*
0365        * While the ``vector`` parameter is not associated with an interrupt
0366        * vector.
0367        */
0368       ctx->valid_vector = false;
0369       break;
0370     }
0371 
0372     case RtemsIntrReqRaise_Pre_Vector_NA:
0373       break;
0374   }
0375 }
0376 
0377 static void RtemsIntrReqRaise_Pre_CanRaise_Prepare(
0378   RtemsIntrReqRaise_Context     *ctx,
0379   RtemsIntrReqRaise_Pre_CanRaise state
0380 )
0381 {
0382   switch ( state ) {
0383     case RtemsIntrReqRaise_Pre_CanRaise_Yes: {
0384       /*
0385        * While the interrupt vector associated with the ``vector`` parameter
0386        * can be raised.
0387        */
0388       /*
0389        * This pre-condition depends on the attributes of an interrupt vector,
0390        * see CheckRaise().
0391        */
0392       break;
0393     }
0394 
0395     case RtemsIntrReqRaise_Pre_CanRaise_No: {
0396       /*
0397        * While the interrupt vector associated with the ``vector`` parameter
0398        * cannot be raised.
0399        */
0400       /*
0401        * This pre-condition depends on the attributes of an interrupt vector,
0402        * see CheckRaise().
0403        */
0404       break;
0405     }
0406 
0407     case RtemsIntrReqRaise_Pre_CanRaise_NA:
0408       break;
0409   }
0410 }
0411 
0412 static void RtemsIntrReqRaise_Post_Status_Check(
0413   RtemsIntrReqRaise_Context    *ctx,
0414   RtemsIntrReqRaise_Post_Status state
0415 )
0416 {
0417   switch ( state ) {
0418     case RtemsIntrReqRaise_Post_Status_Ok: {
0419       /*
0420        * The return status of rtems_interrupt_raise() shall be
0421        * RTEMS_SUCCESSFUL.
0422        */
0423       /* Validation is done by CheckRaise() for each interrupt vector */
0424       break;
0425     }
0426 
0427     case RtemsIntrReqRaise_Post_Status_InvId: {
0428       /*
0429        * The return status of rtems_interrupt_raise() shall be
0430        * RTEMS_INVALID_ID.
0431        */
0432       T_rsc( ctx->status, RTEMS_INVALID_ID );
0433       break;
0434     }
0435 
0436     case RtemsIntrReqRaise_Post_Status_Unsat: {
0437       /*
0438        * The return status of rtems_interrupt_raise() shall be
0439        * RTEMS_UNSATISFIED.
0440        */
0441       /* Validation is done by CheckRaise() for each interrupt vector */
0442       break;
0443     }
0444 
0445     case RtemsIntrReqRaise_Post_Status_NA:
0446       break;
0447   }
0448 }
0449 
0450 static void RtemsIntrReqRaise_Post_Pending_Check(
0451   RtemsIntrReqRaise_Context     *ctx,
0452   RtemsIntrReqRaise_Post_Pending state
0453 )
0454 {
0455   switch ( state ) {
0456     case RtemsIntrReqRaise_Post_Pending_Yes: {
0457       /*
0458        * The interrupt associated with the interrupt vector specified by
0459        * ``vector`` shall be made pending by the rtems_interrupt_raise() call.
0460        */
0461       /* Validation is done by CheckRaise() for each interrupt vector */
0462       break;
0463     }
0464 
0465     case RtemsIntrReqRaise_Post_Pending_No: {
0466       /*
0467        * The interrupt associated with the interrupt vector specified by
0468        * ``vector`` shall not be made pending by the rtems_interrupt_raise()
0469        * call.
0470        */
0471       /* Validation is done by CheckRaise() for each interrupt vector */
0472       break;
0473     }
0474 
0475     case RtemsIntrReqRaise_Post_Pending_NA:
0476       break;
0477   }
0478 }
0479 
0480 static void RtemsIntrReqRaise_Action( RtemsIntrReqRaise_Context *ctx )
0481 {
0482   if ( ctx->valid_vector ) {
0483     for (
0484       ctx->vector = 0;
0485       ctx->vector < BSP_INTERRUPT_VECTOR_COUNT;
0486       ++ctx->vector
0487     ) {
0488       rtems_status_code          sc;
0489       rtems_interrupt_attributes attr;
0490       bool                       has_installed_entries;
0491 
0492       memset( &attr, 0, sizeof( attr ) );
0493       sc = rtems_interrupt_get_attributes( ctx->vector, &attr );
0494 
0495       if ( sc == RTEMS_INVALID_ID ) {
0496         continue;
0497       }
0498 
0499       T_rsc_success( sc );
0500 
0501       has_installed_entries = HasInterruptVectorEntriesInstalled( ctx->vector );
0502       CheckRaise( ctx, &attr, has_installed_entries );
0503     }
0504   } else {
0505     ctx->vector = BSP_INTERRUPT_VECTOR_COUNT;
0506     ctx->status = rtems_interrupt_raise( ctx->vector );
0507   }
0508 }
0509 
0510 static const RtemsIntrReqRaise_Entry
0511 RtemsIntrReqRaise_Entries[] = {
0512   { 0, 0, 1, RtemsIntrReqRaise_Post_Status_InvId,
0513     RtemsIntrReqRaise_Post_Pending_NA },
0514   { 0, 0, 0, RtemsIntrReqRaise_Post_Status_Ok,
0515     RtemsIntrReqRaise_Post_Pending_Yes },
0516   { 0, 0, 0, RtemsIntrReqRaise_Post_Status_Unsat,
0517     RtemsIntrReqRaise_Post_Pending_No }
0518 };
0519 
0520 static const uint8_t
0521 RtemsIntrReqRaise_Map[] = {
0522   1, 2, 0, 0
0523 };
0524 
0525 static size_t RtemsIntrReqRaise_Scope( void *arg, char *buf, size_t n )
0526 {
0527   RtemsIntrReqRaise_Context *ctx;
0528 
0529   ctx = arg;
0530 
0531   if ( ctx->Map.in_action_loop ) {
0532     return T_get_scope( RtemsIntrReqRaise_PreDesc, buf, n, ctx->Map.pcs );
0533   }
0534 
0535   return 0;
0536 }
0537 
0538 static T_fixture RtemsIntrReqRaise_Fixture = {
0539   .setup = NULL,
0540   .stop = NULL,
0541   .teardown = NULL,
0542   .scope = RtemsIntrReqRaise_Scope,
0543   .initial_context = &RtemsIntrReqRaise_Instance
0544 };
0545 
0546 static inline RtemsIntrReqRaise_Entry RtemsIntrReqRaise_PopEntry(
0547   RtemsIntrReqRaise_Context *ctx
0548 )
0549 {
0550   size_t index;
0551 
0552   index = ctx->Map.index;
0553   ctx->Map.index = index + 1;
0554   return RtemsIntrReqRaise_Entries[
0555     RtemsIntrReqRaise_Map[ index ]
0556   ];
0557 }
0558 
0559 static void RtemsIntrReqRaise_SetPreConditionStates(
0560   RtemsIntrReqRaise_Context *ctx
0561 )
0562 {
0563   ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
0564 
0565   if ( ctx->Map.entry.Pre_CanRaise_NA ) {
0566     ctx->Map.pcs[ 1 ] = RtemsIntrReqRaise_Pre_CanRaise_NA;
0567   } else {
0568     ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
0569   }
0570 }
0571 
0572 static void RtemsIntrReqRaise_TestVariant( RtemsIntrReqRaise_Context *ctx )
0573 {
0574   RtemsIntrReqRaise_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
0575   RtemsIntrReqRaise_Pre_CanRaise_Prepare( ctx, ctx->Map.pcs[ 1 ] );
0576   RtemsIntrReqRaise_Action( ctx );
0577   RtemsIntrReqRaise_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
0578   RtemsIntrReqRaise_Post_Pending_Check( ctx, ctx->Map.entry.Post_Pending );
0579 }
0580 
0581 /**
0582  * @fn void T_case_body_RtemsIntrReqRaise( void )
0583  */
0584 T_TEST_CASE_FIXTURE( RtemsIntrReqRaise, &RtemsIntrReqRaise_Fixture )
0585 {
0586   RtemsIntrReqRaise_Context *ctx;
0587 
0588   ctx = T_fixture_context();
0589   ctx->Map.in_action_loop = true;
0590   ctx->Map.index = 0;
0591 
0592   for (
0593     ctx->Map.pci[ 0 ] = RtemsIntrReqRaise_Pre_Vector_Valid;
0594     ctx->Map.pci[ 0 ] < RtemsIntrReqRaise_Pre_Vector_NA;
0595     ++ctx->Map.pci[ 0 ]
0596   ) {
0597     for (
0598       ctx->Map.pci[ 1 ] = RtemsIntrReqRaise_Pre_CanRaise_Yes;
0599       ctx->Map.pci[ 1 ] < RtemsIntrReqRaise_Pre_CanRaise_NA;
0600       ++ctx->Map.pci[ 1 ]
0601     ) {
0602       ctx->Map.entry = RtemsIntrReqRaise_PopEntry( ctx );
0603       RtemsIntrReqRaise_SetPreConditionStates( ctx );
0604       RtemsIntrReqRaise_TestVariant( ctx );
0605     }
0606   }
0607 }
0608 
0609 /** @} */