|
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;
}
|