770 lines
25 KiB
C
770 lines
25 KiB
C
//*****************************************************************************
|
|
//
|
|
// interrupt.c
|
|
//
|
|
// Driver for the NVIC Interrupt Controller.
|
|
//
|
|
// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
|
|
//
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
//
|
|
// Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
//
|
|
// Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the
|
|
// distribution.
|
|
//
|
|
// Neither the name of Texas Instruments Incorporated nor the names of
|
|
// its contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \addtogroup interrupt_api
|
|
//! @{
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include "inc/hw_ints.h"
|
|
#include "inc/hw_nvic.h"
|
|
#include "inc/hw_types.h"
|
|
#include "cpu.h"
|
|
#include "debug.h"
|
|
#include "interrupt.h"
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is a mapping between priority grouping encodings and the number of
|
|
// preemption priority bits.
|
|
//
|
|
//*****************************************************************************
|
|
static const unsigned long g_pulPriority[] =
|
|
{
|
|
NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6,
|
|
NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4, NVIC_APINT_PRIGROUP_5_3,
|
|
NVIC_APINT_PRIGROUP_6_2, NVIC_APINT_PRIGROUP_7_1
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is a mapping between interrupt number and the register that contains
|
|
// the priority encoding for that interrupt.
|
|
//
|
|
//*****************************************************************************
|
|
static const unsigned long g_pulRegs[] =
|
|
{
|
|
0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3, NVIC_PRI0, NVIC_PRI1,
|
|
NVIC_PRI2, NVIC_PRI3, NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7,
|
|
NVIC_PRI8, NVIC_PRI9, NVIC_PRI10, NVIC_PRI11, NVIC_PRI12, NVIC_PRI13,
|
|
NVIC_PRI14, NVIC_PRI15, NVIC_PRI16, NVIC_PRI17, NVIC_PRI18, NVIC_PRI19,
|
|
NVIC_PRI20, NVIC_PRI21, NVIC_PRI22, NVIC_PRI23, NVIC_PRI24, NVIC_PRI25,
|
|
NVIC_PRI26, NVIC_PRI27, NVIC_PRI28, NVIC_PRI29, NVIC_PRI30, NVIC_PRI31,
|
|
NVIC_PRI32, NVIC_PRI33, NVIC_PRI34, NVIC_PRI35, NVIC_PRI36, NVIC_PRI37,
|
|
NVIC_PRI38, NVIC_PRI39, NVIC_PRI40, NVIC_PRI41, NVIC_PRI42, NVIC_PRI43,
|
|
NVIC_PRI44, NVIC_PRI45, NVIC_PRI46, NVIC_PRI47, NVIC_PRI48
|
|
|
|
};
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is a mapping between interrupt number (for the peripheral interrupts
|
|
// only) and the register that contains the interrupt enable for that
|
|
// interrupt.
|
|
//
|
|
//*****************************************************************************
|
|
static const unsigned long g_pulEnRegs[] =
|
|
{
|
|
NVIC_EN0, NVIC_EN1, NVIC_EN2, NVIC_EN3, NVIC_EN4, NVIC_EN5
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is a mapping between interrupt number (for the peripheral interrupts
|
|
// only) and the register that contains the interrupt disable for that
|
|
// interrupt.
|
|
//
|
|
//*****************************************************************************
|
|
static const unsigned long g_pulDisRegs[] =
|
|
{
|
|
NVIC_DIS0, NVIC_DIS1, NVIC_DIS2, NVIC_DIS3, NVIC_DIS4, NVIC_DIS5
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is a mapping between interrupt number (for the peripheral interrupts
|
|
// only) and the register that contains the interrupt pend for that interrupt.
|
|
//
|
|
//*****************************************************************************
|
|
static const unsigned long g_pulPendRegs[] =
|
|
{
|
|
NVIC_PEND0, NVIC_PEND1, NVIC_PEND2, NVIC_PEND3, NVIC_PEND4, NVIC_PEND5
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// This is a mapping between interrupt number (for the peripheral interrupts
|
|
// only) and the register that contains the interrupt unpend for that
|
|
// interrupt.
|
|
//
|
|
//*****************************************************************************
|
|
static const unsigned long g_pulUnpendRegs[] =
|
|
{
|
|
NVIC_UNPEND0, NVIC_UNPEND1, NVIC_UNPEND2, NVIC_UNPEND3, NVIC_UNPEND4,
|
|
NVIC_UNPEND5
|
|
};
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//! The default interrupt handler.
|
|
//!
|
|
//! This is the default interrupt handler for all interrupts. It simply loops
|
|
//! forever so that the system state is preserved for observation by a
|
|
//! debugger. Since interrupts should be disabled before unregistering the
|
|
//! corresponding handler, this should never be called.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
static void
|
|
IntDefaultHandler(void)
|
|
{
|
|
//
|
|
// Go into an infinite loop.
|
|
//
|
|
while(1)
|
|
{
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Enables the processor interrupt.
|
|
//!
|
|
//! Allows the processor to respond to interrupts. This does not affect the
|
|
//! set of interrupts enabled in the interrupt controller; it just gates the
|
|
//! single interrupt from the controller to the processor.
|
|
//!
|
|
//! \note Previously, this function had no return value. As such, it was
|
|
//! possible to include <tt>interrupt.h</tt> and call this function without
|
|
//! having included <tt>hw_types.h</tt>. Now that the return is a
|
|
//! <tt>tBoolean</tt>, a compiler error will occur in this case. The solution
|
|
//! is to include <tt>hw_types.h</tt> before including <tt>interrupt.h</tt>.
|
|
//!
|
|
//! \return Returns \b true if interrupts were disabled when the function was
|
|
//! called or \b false if they were initially enabled.
|
|
//
|
|
//*****************************************************************************
|
|
tBoolean
|
|
IntMasterEnable(void)
|
|
{
|
|
//
|
|
// Enable processor interrupts.
|
|
//
|
|
return(CPUcpsie());
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Disables the processor interrupt.
|
|
//!
|
|
//! Prevents the processor from receiving interrupts. This does not affect the
|
|
//! set of interrupts enabled in the interrupt controller; it just gates the
|
|
//! single interrupt from the controller to the processor.
|
|
//!
|
|
//! \note Previously, this function had no return value. As such, it was
|
|
//! possible to include <tt>interrupt.h</tt> and call this function without
|
|
//! having included <tt>hw_types.h</tt>. Now that the return is a
|
|
//! <tt>tBoolean</tt>, a compiler error will occur in this case. The solution
|
|
//! is to include <tt>hw_types.h</tt> before including <tt>interrupt.h</tt>.
|
|
//!
|
|
//! \return Returns \b true if interrupts were already disabled when the
|
|
//! function was called or \b false if they were initially enabled.
|
|
//
|
|
//*****************************************************************************
|
|
tBoolean
|
|
IntMasterDisable(void)
|
|
{
|
|
//
|
|
// Disable processor interrupts.
|
|
//
|
|
return(CPUcpsid());
|
|
}
|
|
//*****************************************************************************
|
|
//
|
|
//! Sets the NVIC VTable base.
|
|
//!
|
|
//! \param ulVtableBase specifies the new base address of VTable
|
|
//!
|
|
//! This function is used to specify a new base address for the VTable.
|
|
//! This function must be called before using IntRegister() for registering
|
|
//! any interrupt handler.
|
|
//!
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntVTableBaseSet(unsigned long ulVtableBase)
|
|
{
|
|
HWREG(NVIC_VTABLE) = ulVtableBase;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Registers a function to be called when an interrupt occurs.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt in question.
|
|
//! \param pfnHandler is a pointer to the function to be called.
|
|
//!
|
|
//! This function is used to specify the handler function to be called when the
|
|
//! given interrupt is asserted to the processor. When the interrupt occurs,
|
|
//! if it is enabled (via IntEnable()), the handler function will be called in
|
|
//! interrupt context. Since the handler function can preempt other code, care
|
|
//! must be taken to protect memory or peripherals that are accessed by the
|
|
//! handler and other non-handler code.
|
|
//!
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntRegister(unsigned long ulInterrupt, void (*pfnHandler)(void))
|
|
{
|
|
unsigned long *ulNvicTbl;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulInterrupt < NUM_INTERRUPTS);
|
|
|
|
ulNvicTbl = (unsigned long *)HWREG(NVIC_VTABLE);
|
|
ulNvicTbl[ulInterrupt]= (unsigned long)pfnHandler;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Unregisters the function to be called when an interrupt occurs.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt in question.
|
|
//!
|
|
//! This function is used to indicate that no handler should be called when the
|
|
//! given interrupt is asserted to the processor. The interrupt source will be
|
|
//! automatically disabled (via IntDisable()) if necessary.
|
|
//!
|
|
//! \sa IntRegister() for important information about registering interrupt
|
|
//! handlers.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntUnregister(unsigned long ulInterrupt)
|
|
{
|
|
unsigned long *ulNvicTbl;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulInterrupt < NUM_INTERRUPTS);
|
|
|
|
ulNvicTbl = (unsigned long *)HWREG(NVIC_VTABLE);
|
|
ulNvicTbl[ulInterrupt]= (unsigned long)IntDefaultHandler;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sets the priority grouping of the interrupt controller.
|
|
//!
|
|
//! \param ulBits specifies the number of bits of preemptable priority.
|
|
//!
|
|
//! This function specifies the split between preemptable priority levels and
|
|
//! subpriority levels in the interrupt priority specification. The range of
|
|
//! the grouping values are dependent upon the hardware implementation; on
|
|
//! the CC3200 , three bits are available for hardware interrupt
|
|
//! prioritization and therefore priority grouping values of three through
|
|
//! seven have the same effect.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntPriorityGroupingSet(unsigned long ulBits)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBits < NUM_PRIORITY);
|
|
|
|
//
|
|
// Set the priority grouping.
|
|
//
|
|
HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pulPriority[ulBits];
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Gets the priority grouping of the interrupt controller.
|
|
//!
|
|
//! This function returns the split between preemptable priority levels and
|
|
//! subpriority levels in the interrupt priority specification.
|
|
//!
|
|
//! \return The number of bits of preemptable priority.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
IntPriorityGroupingGet(void)
|
|
{
|
|
unsigned long ulLoop, ulValue;
|
|
|
|
//
|
|
// Read the priority grouping.
|
|
//
|
|
ulValue = HWREG(NVIC_APINT) & NVIC_APINT_PRIGROUP_M;
|
|
|
|
//
|
|
// Loop through the priority grouping values.
|
|
//
|
|
for(ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++)
|
|
{
|
|
//
|
|
// Stop looping if this value matches.
|
|
//
|
|
if(ulValue == g_pulPriority[ulLoop])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the number of priority bits.
|
|
//
|
|
return(ulLoop);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sets the priority of an interrupt.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt in question.
|
|
//! \param ucPriority specifies the priority of the interrupt.
|
|
//!
|
|
//! This function is used to set the priority of an interrupt. When multiple
|
|
//! interrupts are asserted simultaneously, the ones with the highest priority
|
|
//! are processed before the lower priority interrupts. Smaller numbers
|
|
//! correspond to higher interrupt priorities; priority 0 is the highest
|
|
//! interrupt priority.
|
|
//!
|
|
//! The hardware priority mechanism will only look at the upper N bits of the
|
|
//! priority level (where N is 3), so any prioritization must be performed in
|
|
//! those bits. The remaining bits can be used to sub-prioritize the interrupt
|
|
//! sources, and may be used by the hardware priority mechanism on a future
|
|
//! part. This arrangement allows priorities to migrate to different NVIC
|
|
//! implementations without changing the gross prioritization of the
|
|
//! interrupts.
|
|
//!
|
|
//! The parameter \e ucPriority can be any one of the following
|
|
//! -\b INT_PRIORITY_LVL_0
|
|
//! -\b INT_PRIORITY_LVL_1
|
|
//! -\b INT_PRIORITY_LVL_2
|
|
//! -\b INT_PRIORITY_LVL_3
|
|
//! -\b INT_PRIORITY_LVL_4
|
|
//! -\b INT_PRIORITY_LVL_5
|
|
//! -\b INT_PRIORITY_LVL_6
|
|
//! -\b INT_PRIORITY_LVL_7
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority)
|
|
{
|
|
unsigned long ulTemp;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));
|
|
|
|
//
|
|
// Set the interrupt priority.
|
|
//
|
|
ulTemp = HWREG(g_pulRegs[ulInterrupt >> 2]);
|
|
ulTemp &= ~(0xFF << (8 * (ulInterrupt & 3)));
|
|
ulTemp |= ucPriority << (8 * (ulInterrupt & 3));
|
|
HWREG(g_pulRegs[ulInterrupt >> 2]) = ulTemp;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Gets the priority of an interrupt.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt in question.
|
|
//!
|
|
//! This function gets the priority of an interrupt. See IntPrioritySet() for
|
|
//! a definition of the priority value.
|
|
//!
|
|
//! \return Returns the interrupt priority, or -1 if an invalid interrupt was
|
|
//! specified.
|
|
//
|
|
//*****************************************************************************
|
|
long
|
|
IntPriorityGet(unsigned long ulInterrupt)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));
|
|
|
|
//
|
|
// Return the interrupt priority.
|
|
//
|
|
return((HWREG(g_pulRegs[ulInterrupt >> 2]) >> (8 * (ulInterrupt & 3))) &
|
|
0xFF);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Enables an interrupt.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt to be enabled.
|
|
//!
|
|
//! The specified interrupt is enabled in the interrupt controller. Other
|
|
//! enables for the interrupt (such as at the peripheral level) are unaffected
|
|
//! by this function.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntEnable(unsigned long ulInterrupt)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulInterrupt < NUM_INTERRUPTS);
|
|
|
|
//
|
|
// Determine the interrupt to enable.
|
|
//
|
|
if(ulInterrupt == FAULT_MPU)
|
|
{
|
|
//
|
|
// Enable the MemManage interrupt.
|
|
//
|
|
HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_MEM;
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_BUS)
|
|
{
|
|
//
|
|
// Enable the bus fault interrupt.
|
|
//
|
|
HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS;
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_USAGE)
|
|
{
|
|
//
|
|
// Enable the usage fault interrupt.
|
|
//
|
|
HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE;
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_SYSTICK)
|
|
{
|
|
//
|
|
// Enable the System Tick interrupt.
|
|
//
|
|
HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN;
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt >= 16)
|
|
{
|
|
//
|
|
// Enable the general interrupt.
|
|
//
|
|
HWREG(g_pulEnRegs[(ulInterrupt - 16) / 32]) =
|
|
1 << ((ulInterrupt - 16) & 31);
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Disables an interrupt.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt to be disabled.
|
|
//!
|
|
//! The specified interrupt is disabled in the interrupt controller. Other
|
|
//! enables for the interrupt (such as at the peripheral level) are unaffected
|
|
//! by this function.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntDisable(unsigned long ulInterrupt)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulInterrupt < NUM_INTERRUPTS);
|
|
|
|
//
|
|
// Determine the interrupt to disable.
|
|
//
|
|
if(ulInterrupt == FAULT_MPU)
|
|
{
|
|
//
|
|
// Disable the MemManage interrupt.
|
|
//
|
|
HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_MEM);
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_BUS)
|
|
{
|
|
//
|
|
// Disable the bus fault interrupt.
|
|
//
|
|
HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS);
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_USAGE)
|
|
{
|
|
//
|
|
// Disable the usage fault interrupt.
|
|
//
|
|
HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE);
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_SYSTICK)
|
|
{
|
|
//
|
|
// Disable the System Tick interrupt.
|
|
//
|
|
HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN);
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt >= 16)
|
|
{
|
|
//
|
|
// Disable the general interrupt.
|
|
//
|
|
HWREG(g_pulDisRegs[(ulInterrupt - 16) / 32]) =
|
|
1 << ((ulInterrupt - 16) & 31);
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Pends an interrupt.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt to be pended.
|
|
//!
|
|
//! The specified interrupt is pended in the interrupt controller. This will
|
|
//! cause the interrupt controller to execute the corresponding interrupt
|
|
//! handler at the next available time, based on the current interrupt state
|
|
//! priorities. For example, if called by a higher priority interrupt handler,
|
|
//! the specified interrupt handler will not be called until after the current
|
|
//! interrupt handler has completed execution. The interrupt must have been
|
|
//! enabled for it to be called.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntPendSet(unsigned long ulInterrupt)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulInterrupt < NUM_INTERRUPTS);
|
|
|
|
//
|
|
// Determine the interrupt to pend.
|
|
//
|
|
if(ulInterrupt == FAULT_NMI)
|
|
{
|
|
//
|
|
// Pend the NMI interrupt.
|
|
//
|
|
HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_NMI_SET;
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_PENDSV)
|
|
{
|
|
//
|
|
// Pend the PendSV interrupt.
|
|
//
|
|
HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PEND_SV;
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt == FAULT_SYSTICK)
|
|
{
|
|
//
|
|
// Pend the SysTick interrupt.
|
|
//
|
|
HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTSET;
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
else if(ulInterrupt >= 16)
|
|
{
|
|
//
|
|
// Pend the general interrupt.
|
|
//
|
|
HWREG(g_pulPendRegs[(ulInterrupt - 16) / 32]) =
|
|
1 << ((ulInterrupt - 16) & 31);
|
|
__asm(" dsb ");
|
|
__asm(" isb ");
|
|
}
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Unpends an interrupt.
|
|
//!
|
|
//! \param ulInterrupt specifies the interrupt to be unpended.
|
|
//!
|
|
//! The specified interrupt is unpended in the interrupt controller. This will
|
|
//! cause any previously generated interrupts that have not been handled yet
|
|
//! (due to higher priority interrupts or the interrupt no having been enabled
|
|
//! yet) to be discarded.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntPendClear(unsigned long ulInterrupt)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulInterrupt < NUM_INTERRUPTS);
|
|
|
|
//
|
|
// Determine the interrupt to unpend.
|
|
//
|
|
if(ulInterrupt == FAULT_PENDSV)
|
|
{
|
|
//
|
|
// Unpend the PendSV interrupt.
|
|
//
|
|
HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_UNPEND_SV;
|
|
}
|
|
else if(ulInterrupt == FAULT_SYSTICK)
|
|
{
|
|
//
|
|
// Unpend the SysTick interrupt.
|
|
//
|
|
HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTCLR;
|
|
}
|
|
else if(ulInterrupt >= 16)
|
|
{
|
|
//
|
|
// Unpend the general interrupt.
|
|
//
|
|
HWREG(g_pulUnpendRegs[(ulInterrupt - 16) / 32]) =
|
|
1 << ((ulInterrupt - 16) & 31);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sets the priority masking level
|
|
//!
|
|
//! \param ulPriorityMask is the priority level that will be masked.
|
|
//!
|
|
//! This function sets the interrupt priority masking level so that all
|
|
//! interrupts at the specified or lesser priority level is masked. This
|
|
//! can be used to globally disable a set of interrupts with priority below
|
|
//! a predetermined threshold. A value of 0 disables priority
|
|
//! masking.
|
|
//!
|
|
//! Smaller numbers correspond to higher interrupt priorities. So for example
|
|
//! a priority level mask of 4 will allow interrupts of priority level 0-3,
|
|
//! and interrupts with a numerical priority of 4 and greater will be blocked.
|
|
//!
|
|
//! The hardware priority mechanism will only look at the upper N bits of the
|
|
//! priority level (where N is 3), so any
|
|
//! prioritization must be performed in those bits.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
IntPriorityMaskSet(unsigned long ulPriorityMask)
|
|
{
|
|
CPUbasepriSet(ulPriorityMask);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Gets the priority masking level
|
|
//!
|
|
//! This function gets the current setting of the interrupt priority masking
|
|
//! level. The value returned is the priority level such that all interrupts
|
|
//! of that and lesser priority are masked. A value of 0 means that priority
|
|
//! masking is disabled.
|
|
//!
|
|
//! Smaller numbers correspond to higher interrupt priorities. So for example
|
|
//! a priority level mask of 4 will allow interrupts of priority level 0-3,
|
|
//! and interrupts with a numerical priority of 4 and greater will be blocked.
|
|
//!
|
|
//! The hardware priority mechanism will only look at the upper N bits of the
|
|
//! priority level (where N is 3), so any
|
|
//! prioritization must be performed in those bits.
|
|
//!
|
|
//! \return Returns the value of the interrupt priority level mask.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
IntPriorityMaskGet(void)
|
|
{
|
|
return(CPUbasepriGet());
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Close the Doxygen group.
|
|
//! @}
|
|
//
|
|
//*****************************************************************************
|