URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_LM3S811_IAR/] [LuminaryCode/] [interrupt.c] - Rev 581
Compare with Previous | Blame | View Log
//***************************************************************************** // // interrupt.c - Driver for the NVIC Interrupt Controller. // // Copyright (c) 2005,2006 Luminary Micro, Inc. All rights reserved. // // Software License Agreement // // Luminary Micro, Inc. (LMI) is supplying this software for use solely and // exclusively on LMI's Stellaris Family of microcontroller products. // // The software is owned by LMI and/or its suppliers, and is protected under // applicable copyright laws. All rights are reserved. Any use in violation // of the foregoing restrictions may subject the user to criminal sanctions // under applicable laws, as well as to civil liability for the breach of the // terms and conditions of this license. // // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 991 of the Stellaris Driver Library. // //***************************************************************************** //***************************************************************************** // //! \addtogroup interrupt_api //! @{ // //***************************************************************************** #include "../hw_ints.h" #include "../hw_nvic.h" #include "../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. // //***************************************************************************** #if defined(GROUP_pulpriority) || defined(BUILD_ALL) 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 }; #else extern const unsigned long g_pulPriority[]; #endif //***************************************************************************** // // This is a mapping between interrupt number and the register that contains // the priority encoding for that interrupt. // //***************************************************************************** #if defined(GROUP_pulregs) || defined(BUILD_ALL) const unsigned long g_pulRegs[12] = { 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 }; #else extern const unsigned long g_pulRegs[12]; #endif //***************************************************************************** // //! \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. // //***************************************************************************** #if defined(GROUP_defaulthandler) || defined(BUILD_ALL) void IntDefaultHandler(void) { // // Go into an infinite loop. // while(1) { } } #else extern void IntDefaultHandler(void); #endif //***************************************************************************** // // The processor vector table. // // This contains a list of the handlers for the various interrupt sources in // the system. The layout of this list is defined by the hardware; assertion // of an interrupt causes the processor to start executing directly at the // address given in the corresponding location in this list. // //***************************************************************************** #if defined(GROUP_vtable) || defined(BUILD_ALL) #ifdef ewarm __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) @ "VTABLE"; #else __attribute__((section("vtable"))) void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void); #endif #else extern void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void); #endif //***************************************************************************** // //! 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. //! //! \return None. // //***************************************************************************** #if defined(GROUP_masterenable) || defined(BUILD_ALL) || defined(DOXYGEN) void IntMasterEnable(void) { // // Enable processor interrupts. // CPUcpsie(); } #endif //***************************************************************************** // //! 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. //! //! \return None. // //***************************************************************************** #if defined(GROUP_masterdisable) || defined(BUILD_ALL) || defined(DOXYGEN) void IntMasterDisable(void) { // // Disable processor interrupts. // CPUcpsid(); } #endif //***************************************************************************** // //! 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. //! //! \note The use of this function (directly or indirectly via a peripheral //! driver interrupt register function) moves the interrupt vector table from //! flash to SRAM. Therefore, care must be taken when linking the application //! to ensure that the SRAM vector table is located at the beginning of SRAM; //! otherwise NVIC will not look in the correct portion of memory for the //! vector table (it requires the vector table be on a 1 kB memory alignment). //! Normally, the SRAM vector table is so placed via the use of linker scripts; //! some tool chains, such as the evaluation version of RV-MDK, do not support //! linker scripts and therefore will not produce a valid executable. See the //! discussion of compile-time versus run-time interrupt handler registration //! in the introduction to this chapter. //! //! \return None. // //***************************************************************************** #if defined(GROUP_register) || defined(BUILD_ALL) || defined(DOXYGEN) void IntRegister(unsigned long ulInterrupt, void (*pfnHandler)(void)) { unsigned long ulIdx; // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); // // Make sure that the RAM vector table is correctly aligned. // ASSERT(((unsigned long)g_pfnRAMVectors & 0x000003ff) == 0); // // See if the RAM vector table has been initialized. // if(HWREG(NVIC_VTABLE) != (unsigned long)g_pfnRAMVectors) { // // Copy the vector table from the beginning of FLASH to the RAM vector // table. // for(ulIdx = 0; ulIdx < NUM_INTERRUPTS; ulIdx++) { g_pfnRAMVectors[ulIdx] = (void (*)(void))HWREG(ulIdx * 4); } // // Point NVIC at the RAM vector table. // HWREG(NVIC_VTABLE) = (unsigned long)g_pfnRAMVectors; } // // Save the interrupt handler. // g_pfnRAMVectors[ulInterrupt] = pfnHandler; } #endif //***************************************************************************** // //! 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. // //***************************************************************************** #if defined(GROUP_unregister) || defined(BUILD_ALL) || defined(DOXYGEN) void IntUnregister(unsigned long ulInterrupt) { // // Check the arguments. // ASSERT(ulInterrupt < NUM_INTERRUPTS); // // Reset the interrupt handler. // g_pfnRAMVectors[ulInterrupt] = IntDefaultHandler; } #endif //***************************************************************************** // //! 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 Stellaris family it can range from 0 to 3. //! //! \return None. // //***************************************************************************** #if defined(GROUP_prioritygroupingset) || defined(BUILD_ALL) || \ defined(DOXYGEN) void IntPriorityGroupingSet(unsigned long ulBits) { // // Check the arguments. // ASSERT(ulBits < NUM_PRIORITY_BITS); // // Set the priority grouping. // HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pulPriority[ulBits]; } #endif //***************************************************************************** // //! 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. // //***************************************************************************** #if defined(GROUP_prioritygroupingget) || defined(BUILD_ALL) || \ defined(DOXYGEN) 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 < 8; ulLoop++) { // // Stop looping if this value matches. // if(ulValue == g_pulPriority[ulLoop]) { break; } } // // Return the number of priority bits. // return(ulLoop); } #endif //***************************************************************************** // //! 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 for the Stellaris family), 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. //! //! \return None. // //***************************************************************************** #if defined(GROUP_priorityset) || defined(BUILD_ALL) || defined(DOXYGEN) 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; } #endif //***************************************************************************** // //! 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. // //***************************************************************************** #if defined(GROUP_priorityget) || defined(BUILD_ALL) || defined(DOXYGEN) 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); } #endif //***************************************************************************** // //! 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. // //***************************************************************************** #if defined(GROUP_enable) || defined(BUILD_ALL) || defined(DOXYGEN) 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; } else if(ulInterrupt == FAULT_BUS) { // // Enable the bus fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS; } else if(ulInterrupt == FAULT_USAGE) { // // Enable the usage fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE; } else if(ulInterrupt == FAULT_SYSTICK) { // // Enable the System Tick interrupt. // HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN; } else if(ulInterrupt >= INT_GPIOA) { // // Enable the general interrupt. // HWREG(NVIC_EN0) = 1 << (ulInterrupt - INT_GPIOA); } } #endif //***************************************************************************** // //! 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. // //***************************************************************************** #if defined(GROUP_disable) || defined(BUILD_ALL) || defined(DOXYGEN) 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); } else if(ulInterrupt == FAULT_BUS) { // // Disable the bus fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS); } else if(ulInterrupt == FAULT_USAGE) { // // Disable the usage fault interrupt. // HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE); } else if(ulInterrupt == FAULT_SYSTICK) { // // Disable the System Tick interrupt. // HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN); } else if(ulInterrupt >= INT_GPIOA) { // // Disable the general interrupt. // HWREG(NVIC_DIS0) = 1 << (ulInterrupt - INT_GPIOA); } } #endif //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************