intrpt.c



/*
 * intrpt.c
 *
 * ------------------------------------------------------------
 * A Kla2 Module
 * Copyright (c) 2003, David Clifton
 * All Rights Reserved
 * http://www.codelode.com
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice, website reference, this permission
 * notice, and the disclaimer of warranty below shall be included
 * in all copies, derivatives, or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * -------------------------------------------------------------
 *
 * data & methods for interrupt object
 *
 * NOTE 1:  It is important to use the Intrpt_disable,
 * Intrpt_enable, and/or Intrpt_restore routines to
 * prevent errors when disabling and enabling interrupts.
 * The kind of errors prevented are those in which a
 * routine disables interrupts, does a bit of mucking
 * about, and then enables interrupts again, unaware
 * that the calling routine has already disabled
 * interrupts, and expects them to be disabled when
 * the called routine returns.  One prevents this
 * kind of mess by using a call like:
 *
 *     intsav=Intrpt_disable();
 *
 * to disable interrupts when necessary, and a call like:
 *
 *     Intrpt_restore(intsav);
 *
 * to restore them when done mucking about.
 *
 * To unconditionally enable interrupts, one can
 * use the call:
 *
 *     Intrpt_enable();
 *
 * NOTE 2:
 * See also the notes and warning about current
 * interrupt state below.  Since this code is
 * intended to work with some processors which
 * do not push the status register on interrupts
 * and which cannot always be relied upon to 
 * give an accurate reading of the status
 * register, the user must set the interruptsDisabled
 * flag on entry to interrupts (call Intrpt_markDisabled()),
 * and clear that flag on or before exit from interrupts
 * (call Intrpt_markEnabled() or Intrpt_enable() on or
 * before exit).
 *
 * NOTE 3:
 * Calling Intrpt_enable() when interrupts are already
 * enabled will result in an error shutdown.  Calling
 * Intrpt_disable() when interrupts are already disabled
 * will result in an error shutdown.  This is intended 
 * to enforce a careful accounting for the use of each
 * interrupt disabling, restoring, or enabling routine.
 *
 * NOTE 4:
 * If you are familiar with the [reliable] characteristics
 * of your processor, you may want to rewrite this module
 * to make better use of its features.  You should know
 * however that it will not make that much difference
 * in performance.
 */
#include "types.h"
#include "err.h"
#include "intrpt.h"
/*
 * definitions to disable and enable interrupts unconditionally
 */
#define DISABLE_INTERRUPTS     // modify for each processor and board
#define ENABLE_INTERRUPTS    // modify for each processor and board
/*
 * definitions to signal when interrupts are disabled
 * for use in determining interrupt latency
 */
#define DISABLED_SIGNAL_ON   // modify for each processor and board
#define DISABLED_SIGNAL_OFF  // modify for each processor and board

/*
 * current interrupt state
 *
 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 *  WARNING:
 *   In order to make this interrupt management plan work
 *   interrupt routines should call Intrpt_markDisabled() on
 *   entry, and Intrpt_markEnabled() or enable interrupts
 *   prior to exit.
 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 */

static bool interruptsDisabled=TRUE;

/*----------------------------------------------------------------
 * Public method definitions
 * --------------------------------------------------------------- */
/*
 * Intrpt_init
 *
 *     Set up (if necessary) the interrupt state variable.
 *  Take any other action necessary to prepare for 
 *  interrupt processing.
 *  CAUTION:  Call this routine only when interrupts are
 *  disabled.  Otherwise, the interruptsDisabled flag could
 *  get out of synch.
 */
void Intrpt_init(void)
{

  /*
   * processor specific call to disable interrupts
   */
    DISABLE_INTERRUPTS;

  /*
   * set the interrupts disabled flag
   * assuming interrupts are disabled
   */
    interruptsDisabled=TRUE;
  /*
   * line below is present to help determine interrupt latency
   */
    DISABLED_SIGNAL_ON;
}
/*
 * Intrpt_disable
 *   
 *     Disable interrupts, and set the flag that
 *  documents this condition. Return a boolean
 *  indicator of the interrupt disabled state
 *  prior to setting the flag to TRUE.
 */
bool  Intrpt_disable(void)
{
    bool retval;

   /*
    * save the disabled state flag on entry
    */
    retval=interruptsDisabled;

   /*
    * processor specific call to disable interrupts
    */
    DISABLE_INTERRUPTS;
   /*
    * line below is present to help determine interrupt latency
    */
    DISABLED_SIGNAL_ON;
    /*
     * change disabled state to TRUE
     * and return previous state
     */
    interruptsDisabled=TRUE;

    return retval;
}
/*
 * Intrpt_restore
 *
 *    Restore interrupts to the state indicated
 * by the argument supplied.
 * CAUTION:  Care must be taken to call Intrpt_restoreInterrupts()
 * ONLY when interrupts are actually disabled.  Otherwise,
 * the interruptsDisabled flag may get out of synch with the
 * actual condition of the interrupts.
 */
void Intrpt_restore(bool target)
{
    if(interruptsDisabled) {

        if(!target) {

            interruptsDisabled=FALSE;
          /*
           * line below is present to help determine interrupt latency
           */
            DISABLED_SIGNAL_OFF;
          /*
           * processor specific call to enable interrupts
           */  
            ENABLE_INTERRUPTS;
                
        }
    } else {
        Err_shutdown(INTERRUPTS_NOT_DISABLED);
    }
}
/*
 * Intrpt_enable
 *
 *    This routine unconditionaly enables interrupts
 * and sets the interruptsDisabled flag to FALSE.
 * CAUTION:  Care must be taken to call Intrpt_enable()
 * ONLY when interrupts are actually disabled.  Otherwise,
 * the interruptsDisabled flag be get out of 
 * synchronization with the actual condition of
 * the interrupts.
 */ 
void Intrpt_enable(void)
{
    if(interruptsDisabled) {

     /*
      * set the disabled flag to indicate that
      * interrupts are enabled
      */
        interruptsDisabled=FALSE;
      /*
       * line below is present to help determine interrupt latency
       */
        DISABLED_SIGNAL_OFF;

      /*
       * processor specific call to enable interrupts
       */ 
        ENABLE_INTERRUPTS;
    
    } else {
        Err_shutdown(INTERRUPTS_NOT_DISABLED2);
    }
}
/*
 *  Intrpt_markDisabled
 */
void Intrpt_markDisabled(void)
{
    interruptsDisabled=TRUE;
  /*
   * line below is present to help determine interrupt latency
   */
    DISABLED_SIGNAL_ON;
}
/*
 *  Intrpt_markEnabled
 */
void Intrpt_markEnabled(void)
{
    interruptsDisabled=FALSE;
  /*
   * line below is present to help determine interrupt latency
   */
    DISABLED_SIGNAL_OFF;
}