summaryrefslogblamecommitdiffstats
path: root/spec/rtems/intr/req/is-pending.yml
blob: a4759010a6ec9e9e70ebb3a733b16509d05d890b (plain) (tree)


























































































































































































































































































































































































                                                                                
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
copyrights:
- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
enabled-by: true
functional-type: action
links:
- role: interface-function
  uid: ../if/is-pending
post-conditions:
- name: Status
  states:
  - name: Ok
    test-code: |
      T_rsc_success( ctx->status );
    text: |
      The return status of ${../if/is-pending:/name} shall be
      ${../../status/if/successful:/name}.
  - name: InvAddr
    test-code: |
      T_rsc( ctx->status, RTEMS_INVALID_ADDRESS );
    text: |
      The return status of ${../if/is-pending:/name} shall be
      ${../../status/if/invalid-address:/name}.
  - name: InvId
    test-code: |
      T_rsc( ctx->status, RTEMS_INVALID_ID );
    text: |
      The return status of ${../if/is-pending:/name} shall be
      ${../../status/if/invalid-id:/name}.
  test-epilogue: null
  test-prologue: null
- name: IsPending
  states:
  - name: Nop
    test-code: |
      memset( &pending, 0xa5, sizeof( pending ) );
      T_eq_mem( &ctx->pending_obj, &pending, sizeof( pending ) );
    text: |
      Objects referenced by the ${../if/is-pending:/params[1]/name}
      parameter in past calls to ${../if/is-pending:/name} shall not be
      accessed by the ${../if/is-pending:/name} call.
  - name: 'Yes'
    test-code: |
      /* Validation is done by CheckIsPending() for each interrupt vector */
    text: |
      The value of the object referenced by the
      ${../if/is-pending:/params[1]/name} parameter shall be set to
      ${/c/if/true:/name}.
  - name: 'No'
    test-code: |
      /* Validation is done by CheckIsPending() for each interrupt vector */
    text: |
      The value of the object referenced by the
      ${../if/is-pending:/params[1]/name} parameter shall be set to
      ${/c/if/false:/name}.
  test-epilogue: null
  test-prologue: |
    bool pending;
pre-conditions:
- name: Vector
  states:
  - name: Valid
    test-code: |
      ctx->valid_vector = true;
    text: |
      While the ${../if/is-pending:/params[0]/name} parameter is
      associated with an interrupt vector.
  - name: Invalid
    test-code: |
      ctx->valid_vector = false;
    text: |
      While the ${../if/is-pending:/params[0]/name} parameter is
      not associated with an interrupt vector.
  test-epilogue: null
  test-prologue: null
- name: Pending
  states:
  - name: Obj
    test-code: |
      ctx->pending = &ctx->pending_obj;
    text: |
      While the ${../if/is-pending:/params[1]/name} parameter references an
      object of type ``bool``.
  - name: 'Null'
    test-code: |
      ctx->pending = NULL;
    text: |
      While the ${../if/is-pending:/params[1]/name} parameter is equal
      to ${/c/if/null:/name}.
  test-epilogue: null
  test-prologue: null
- name: IsPending
  states:
  - name: 'Yes'
    test-code: |
      /* Validation is done by CheckIsPending() for each interrupt vector */
    text: |
      While the interrupt associated with the interrupt vector specified by
      ${../if/is-pending:/params[0]/name} was pending for the processor
      executing the ${../if/is-pending:/name} call at some time point during
      the call.
  - name: 'No'
    test-code: |
      /* Validation is done by CheckIsPending() for each interrupt vector */
    text: |
      While the interrupt associated with the interrupt vector specified by
      ${../if/is-pending:/params[0]/name} was not pending for the processor
      executing the ${../if/is-pending:/name} call at some time point during
      the call.
  test-epilogue: null
  test-prologue: null
rationale: null
references: []
requirement-type: functional
skip-reasons: {}
test-action: |
  if ( ctx->valid_vector && ctx->pending != NULL ) {
    for (
      ctx->vector = 0;
      ctx->vector < BSP_INTERRUPT_VECTOR_COUNT;
      ++ctx->vector
    ) {
      rtems_status_code          sc;
      rtems_interrupt_attributes attr;
      bool                       has_installed_entries;

      memset( &attr, 0, sizeof( attr ) );
      sc = rtems_interrupt_get_attributes( ctx->vector, &attr );

      if ( sc == RTEMS_INVALID_ID ) {
        continue;
      }

      T_rsc_success( sc );

      has_installed_entries = HasInterruptVectorEntriesInstalled( ctx->vector );
      CheckIsPending( ctx, &attr, has_installed_entries );
    }
  } else {
    if ( ctx->valid_vector ) {
      ctx->vector = 0;
    } else {
      ctx->vector = BSP_INTERRUPT_VECTOR_COUNT;
    }

    memset( &ctx->pending_obj, 0xa5, sizeof( ctx->pending_obj ) );

    ctx->status = rtems_interrupt_is_pending( ctx->vector, ctx->pending );
  }
test-brief: null
test-cleanup: null
test-context:
- brief: |
    This member contains the count of serviced interrupts.
  description: null
  member: |
    volatile uint32_t interrupt_count
- brief: |
    If this member is true, then the interrupt shall be cleared.
  description: null
  member: |
    bool do_clear
- brief: |
    This member contains the current vector number.
  description: null
  member: |
    rtems_vector_number vector
- brief: |
    This member provides the ``bool`` object.
  description: null
  member: |
    bool pending_obj
- brief: |
    If this member is true, then the ${../if/is-pending:/params[0]/name}
    parameter shall be valid.
  description: null
  member: |
    bool valid_vector
- brief: |
    This member specifies if the ${../if/is-pending:/params[1]/name}
    parameter value.
  description: null
  member: |
    bool *pending;
- brief: |
    This member contains the return value of the ${../if/is-pending:/name}
    call.
  description: null
  member: |
    rtems_status_code status
test-context-support: null
test-description: null
test-header: null
test-includes:
- rtems/irq-extension.h
- bsp/irq-generic.h
- string.h
test-local-includes:
- tx-support.h
test-prepare: null
test-setup: null
test-stop: null
test-support: |
  typedef RtemsIntrReqIsPending_Context Context;

  static bool IsEnabled( const Context *ctx )
  {
    rtems_status_code sc;
    bool              enabled;

    enabled = false;
    sc = rtems_interrupt_vector_is_enabled( ctx->vector, &enabled );
    T_rsc_success( sc );

    return enabled;
  }

  static bool IsPending( const Context *ctx )
  {
    rtems_status_code sc;
    bool              pending;

    pending = false;
    sc = rtems_interrupt_is_pending( ctx->vector, &pending );
    T_rsc_success( sc );

    return pending;
  }

  static void Disable( const Context *ctx )
  {
    rtems_status_code sc;

    sc = rtems_interrupt_vector_disable( ctx->vector );
    T_rsc_success( sc );
  }

  static void Cause( const Context *ctx )
  {
    rtems_status_code sc;

    sc = rtems_interrupt_cause( ctx->vector );
    T_rsc_success( sc );
  }

  static void EntryRoutine( void *arg )
  {
    Context *ctx;
    uint32_t count;

    (void) arg;
    ctx = T_fixture_context();

    count = ctx->interrupt_count;
    ctx->interrupt_count = count + 1;

    if ( ctx->do_clear ) {
      rtems_status_code sc;

      sc = rtems_interrupt_clear( ctx->vector );
      T_rsc_success( sc );
    }

    if ( count > 2 ) {
      /* Some interrupts are probably cased by a peripheral */
      Disable( ctx );
    }
  }

  static void CheckIsPending(
    Context                          *ctx,
    const rtems_interrupt_attributes *attr,
    bool                              has_installed_entries
  )
  {
    rtems_status_code sc;

    if ( has_installed_entries ) {
      /*
       * We cannot test this vector thoroughly, since it is used by a device
       * driver.
       */
      T_false( IsPending( ctx ) );
    } else if ( !attr->is_maskable ) {
      /* We can only safely test maskable interrupts */
      T_false( IsPending( ctx ) );
    } else if (
      ( attr->always_enabled || attr->can_disable ) &&
      ( attr->can_clear || attr->cleared_by_acknowledge )
    ) {
      rtems_interrupt_entry entry;
      rtems_interrupt_level level;

      ctx->interrupt_count = 0;
      ctx->do_clear = attr->can_clear && !attr->cleared_by_acknowledge;
      rtems_interrupt_entry_initialize( &entry, EntryRoutine, ctx, "Info" );
      sc = rtems_interrupt_entry_install(
        ctx->vector,
        RTEMS_INTERRUPT_UNIQUE,
        &entry
      );
      T_rsc_success( sc );

      if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
        if ( attr->can_disable ) {
          Disable( ctx );
          Cause( ctx );
          T_true( IsPending( ctx ) );

          sc = rtems_interrupt_vector_enable( ctx->vector );
          T_rsc_success( sc );

          while ( ctx->interrupt_count < 1 ) {
            /* Wait */
          }
        } else {
          ++ctx->interrupt_count;
        }

        rtems_interrupt_local_disable( level );
        Cause( ctx );
        T_true( IsPending( ctx ) );
        rtems_interrupt_local_enable( level );

        while ( ctx->interrupt_count < 2 ) {
          /* Wait */
        }
      }

      sc = rtems_interrupt_entry_remove( ctx->vector, &entry );
      T_rsc_success( sc );
    }
  }
test-target: testsuites/validation/tc-intr-is-pending.c
test-teardown: null
text: ${.:text-template}
transition-map:
- enabled-by: true
  post-conditions:
    Status: Ok
    IsPending:
    - specified-by: IsPending
  pre-conditions:
    Vector:
    - Valid
    Pending:
    - Obj
    IsPending: all
- enabled-by: true
  post-conditions:
    Status: InvAddr
    IsPending: Nop
  pre-conditions:
    Vector:
    - Valid
    Pending:
    - 'Null'
    IsPending: all
- enabled-by: true
  post-conditions:
    Status: InvAddr
    IsPending: Nop
  pre-conditions:
    Vector:
    - Invalid
    Pending:
    - 'Null'
    IsPending: N/A
- enabled-by: true
  post-conditions:
    Status: InvId
    IsPending: Nop
  pre-conditions:
    Vector:
    - Invalid
    Pending:
    - Obj
    IsPending: N/A
type: requirement