//########################################################################### // // FILE: interrupt.h // // TITLE: C28x Interrupt (PIE) driver. // //########################################################################### // $Copyright: // Copyright (C) 2022 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. // $ //########################################################################### #ifndef INTERRUPT_H #define INTERRUPT_H //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif #ifdef __TMS320C28XX__ //***************************************************************************** // //! \addtogroup interrupt_api Interrupt //! @{ // //***************************************************************************** #include #include #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_pie.h" #include "inc/hw_types.h" #include "cpu.h" #include "debug.h" #ifndef DOXYGEN_PDF_IGNORE //***************************************************************************** // // The following are values that can be passed to the Interrupt_enableInCPU() // and Interrupt_disableInCPU() functions as the cpuInterrupt parameter. // //***************************************************************************** #define INTERRUPT_CPU_INT1 0x1U //!< CPU Interrupt Number 1 #define INTERRUPT_CPU_INT2 0x2U //!< CPU Interrupt Number 2 #define INTERRUPT_CPU_INT3 0x4U //!< CPU Interrupt Number 3 #define INTERRUPT_CPU_INT4 0x8U //!< CPU Interrupt Number 4 #define INTERRUPT_CPU_INT5 0x10U //!< CPU Interrupt Number 5 #define INTERRUPT_CPU_INT6 0x20U //!< CPU Interrupt Number 6 #define INTERRUPT_CPU_INT7 0x40U //!< CPU Interrupt Number 7 #define INTERRUPT_CPU_INT8 0x80U //!< CPU Interrupt Number 8 #define INTERRUPT_CPU_INT9 0x100U //!< CPU Interrupt Number 9 #define INTERRUPT_CPU_INT10 0x200U //!< CPU Interrupt Number 10 #define INTERRUPT_CPU_INT11 0x400U //!< CPU Interrupt Number 11 #define INTERRUPT_CPU_INT12 0x800U //!< CPU Interrupt Number 12 #define INTERRUPT_CPU_INT13 0x1000U //!< CPU Interrupt Number 13 #define INTERRUPT_CPU_INT14 0x2000U //!< CPU Interrupt Number 14 #define INTERRUPT_CPU_DLOGINT 0x4000U //!< CPU Data Log Interrupt #define INTERRUPT_CPU_RTOSINT 0x8000U //!< CPU RTOS Interrupt //***************************************************************************** // // The following are values that can be passed to the Interrupt_clearACKGroup() // function as the group parameter. // //***************************************************************************** #define INTERRUPT_ACK_GROUP1 0x1U //!< Acknowledge PIE Interrupt Group 1 #define INTERRUPT_ACK_GROUP2 0x2U //!< Acknowledge PIE Interrupt Group 2 #define INTERRUPT_ACK_GROUP3 0x4U //!< Acknowledge PIE Interrupt Group 3 #define INTERRUPT_ACK_GROUP4 0x8U //!< Acknowledge PIE Interrupt Group 4 #define INTERRUPT_ACK_GROUP5 0x10U //!< Acknowledge PIE Interrupt Group 5 #define INTERRUPT_ACK_GROUP6 0x20U //!< Acknowledge PIE Interrupt Group 6 #define INTERRUPT_ACK_GROUP7 0x40U //!< Acknowledge PIE Interrupt Group 7 #define INTERRUPT_ACK_GROUP8 0x80U //!< Acknowledge PIE Interrupt Group 8 #define INTERRUPT_ACK_GROUP9 0x100U //!< Acknowledge PIE Interrupt Group 9 #define INTERRUPT_ACK_GROUP10 0x200U //!< Acknowledge PIE Interrupt Group 10 #define INTERRUPT_ACK_GROUP11 0x400U //!< Acknowledge PIE Interrupt Group 11 #define INTERRUPT_ACK_GROUP12 0x800U //!< Acknowledge PIE Interrupt Group 12 #endif //***************************************************************************** // // Prototypes for the APIs. // //***************************************************************************** //***************************************************************************** // //! \internal //! The default interrupt handler. //! //! This is the default interrupt handler. The Interrupt_initVectorTable() //! function sets all vectors to this function. Also, when an interrupt is //! unregistered using the Interrupt_unregister() function, this handler takes //! its place. This should never be called during normal operation. //! //! The ESTOP0 statement is for debug purposes only. Remove and replace with an //! appropriate error handling routine for your program. //! //! \return None. // //***************************************************************************** extern void Interrupt_defaultHandler(void); //***************************************************************************** // //! \internal //! The default illegal instruction trap interrupt handler. //! //! This is the default interrupt handler for an illegal instruction trap //! (ITRAP). The Interrupt_initVectorTable() function sets the appropriate //! vector to this function. This should never be called during normal //! operation. //! //! The ESTOP0 statement is for debug purposes only. Remove and replace with //! an appropriate error handling routine for your program. //! //! \return None. // //***************************************************************************** extern void Interrupt_illegalOperationHandler(void); //***************************************************************************** // //! \internal //! The default non-maskable interrupt handler. //! //! This is the default interrupt handler for a non-maskable interrupt (NMI). //! The Interrupt_initVectorTable() function sets the appropriate vector to //! this function. This should never be called during normal operation. //! //! The ESTOP0 statement is for debug purposes only. Remove and replace with an //! appropriate error handling routine for your program. //! //! \return None. // //***************************************************************************** extern void Interrupt_nmiHandler(void); //***************************************************************************** // //! Allows the CPU to process interrupts. //! //! This function clears the global interrupt mask bit (INTM) in the CPU, //! allowing the processor to respond to interrupts. //! //! \return Returns \b true if interrupts were disabled when the function was //! called or \b false if they were initially enabled. // //***************************************************************************** static inline bool Interrupt_enableGlobal(void) { // // Enable processor interrupts. // return(((__enable_interrupts() & 0x1U) != 0U) ? true : false); } //***************************************************************************** // //! Stops the CPU from processing interrupts. //! //! This function sets the global interrupt mask bit (INTM) in the CPU, //! preventing the processor from receiving maskable interrupts. //! //! \return Returns \b true if interrupts were already disabled when the //! function was called or \b false if they were initially enabled. // //***************************************************************************** static inline bool Interrupt_disableGlobal(void) { // // Disable processor interrupts. // return(((__disable_interrupts() & 0x1U) != 0U) ? true : false); } //***************************************************************************** // //! Registers a function to be called when an interrupt occurs. //! //! \param interruptNumber specifies the interrupt in question. //! \param handler 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 Interrupt_enable()), 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. //! //! The available \e interruptNumber values are supplied in //! inc/hw_ints.h. //! //! \note This function assumes that the PIE has been enabled. See //! Interrupt_initModule(). //! //! \return None. // //***************************************************************************** static inline void Interrupt_register(uint32_t interruptNumber, void (*handler)(void)) { uint32_t address; // // Calculate appropriate address for the interrupt number // address = (uint32_t)PIEVECTTABLE_BASE + (((interruptNumber & 0xFFFF0000U) >> 16U) * 2U); // // Copy ISR address into PIE table // EALLOW; HWREG(address) = (uint32_t)handler; EDIS; } //***************************************************************************** // //! Unregisters the function to be called when an interrupt occurs. //! //! \param interruptNumber specifies the interrupt in question. //! //! This function is used to indicate that a default handler //! Interrupt_defaultHandler() should be called when the given interrupt is //! asserted to the processor. Call Interrupt_disable() to disable //! the interrupt before calling this function. //! //! The available \e interruptNumber values are supplied in //! inc/hw_ints.h. //! //! \sa Interrupt_register() for important information about registering //! interrupt handlers. //! //! \return None. // //***************************************************************************** static inline void Interrupt_unregister(uint32_t interruptNumber) { uint32_t address; // // Calculate appropriate address for the interrupt number // address = (uint32_t)PIEVECTTABLE_BASE + (((interruptNumber & 0xFFFF0000U) >> 16U) * 2U); // // Copy default ISR address into PIE table // EALLOW; HWREG(address) = (uint32_t)Interrupt_defaultHandler; EDIS; } //***************************************************************************** // //! Enables CPU interrupt channels //! //! \param cpuInterrupt specifies the CPU interrupts to be enabled. //! //! This function enables the specified interrupts in the CPU. The //! \e cpuInterrupt parameter is a logical OR of the values //! \b INTERRUPT_CPU_INTx where x is the interrupt number between 1 and 14, //! \b INTERRUPT_CPU_DLOGINT, and \b INTERRUPT_CPU_RTOSINT. //! //! \note Note that interrupts 1-12 correspond to the PIE groups with those //! same numbers. //! //! \return None. // //***************************************************************************** static inline void Interrupt_enableInCPU(uint16_t cpuInterrupt) { // // Set the interrupt bits in the CPU. // IER |= cpuInterrupt; } //***************************************************************************** // //! Disables CPU interrupt channels //! //! \param cpuInterrupt specifies the CPU interrupts to be disabled. //! //! This function disables the specified interrupts in the CPU. The //! \e cpuInterrupt parameter is a logical OR of the values //! \b INTERRUPT_CPU_INTx where x is the interrupt number between 1 and 14, //! \b INTERRUPT_CPU_DLOGINT, and \b INTERRUPT_CPU_RTOSINT. //! //! \note Note that interrupts 1-12 correspond to the PIE groups with those //! same numbers. //! //! \return None. // //***************************************************************************** static inline void Interrupt_disableInCPU(uint16_t cpuInterrupt) { // // Clear the interrupt bits in the CPU. // IER &= ~cpuInterrupt; } //***************************************************************************** // //! Acknowledges PIE Interrupt Group //! //! \param group specifies the interrupt group to be acknowledged. //! //! The specified interrupt group is acknowledged and clears any interrupt //! flag within that respective group. //! //! The \e group parameter must be a logical OR of the following: //! \b INTERRUPT_ACK_GROUP1, \b INTERRUPT_ACK_GROUP2, \b INTERRUPT_ACK_GROUP3 //! \b INTERRUPT_ACK_GROUP4, \b INTERRUPT_ACK_GROUP5, \b INTERRUPT_ACK_GROUP6 //! \b INTERRUPT_ACK_GROUP7, \b INTERRUPT_ACK_GROUP8, \b INTERRUPT_ACK_GROUP9 //! \b INTERRUPT_ACK_GROUP10, \b INTERRUPT_ACK_GROUP11, //! \b INTERRUPT_ACK_GROUP12. //! //! \return None. // //***************************************************************************** static inline void Interrupt_clearACKGroup(uint16_t group) { // // Set interrupt group acknowledge bits // HWREGH(PIECTRL_BASE + PIE_O_ACK) = group; } //***************************************************************************** // //! Enables the PIE block. //! //! This function enables the vector fetching for the peripheral interrupts by //! enabling the PIE block. //! //! \return None. // //***************************************************************************** static inline void Interrupt_enablePIE(void) { HWREGH(PIECTRL_BASE + PIE_O_CTRL) |= PIE_CTRL_ENPIE; } //***************************************************************************** // //! Disables the PIE block. //! //! This function disables the vector fetching for the peripheral interrupts by //! disabling the PIE block. PIEACK, PIEIFR, and PIEIER registers can be //! accessed even when the PIE block is disabled. //! //! \return None. // //***************************************************************************** static inline void Interrupt_disablePIE(void) { HWREGH(PIECTRL_BASE + PIE_O_CTRL) &= ~PIE_CTRL_ENPIE; } //***************************************************************************** // //! Initializes the PIE control registers by setting them to a known state. //! //! This function initializes the PIE control registers. After globally //! disabling interrupts and enabling the PIE, it clears all of the PIE //! interrupt enable bits and interrupt flags. //! //! \return None. // //***************************************************************************** extern void Interrupt_initModule(void); //***************************************************************************** // //! Initializes the PIE vector table by setting all vectors to a default //! handler function. //! //! \return None. // //***************************************************************************** extern void Interrupt_initVectorTable(void); //***************************************************************************** // //! Enables an interrupt. //! //! \param interruptNumber 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. //! //! The available \e interruptNumber values are supplied in //! inc/hw_ints.h. //! //! \return None. // //***************************************************************************** extern void Interrupt_enable(uint32_t interruptNumber); //***************************************************************************** // //! Disables an interrupt. //! //! \param interruptNumber 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. //! //! The available \e interruptNumber values are supplied in //! inc/hw_ints.h. //! //! \return None. // //***************************************************************************** extern void Interrupt_disable(uint32_t interruptNumber); //***************************************************************************** // // Extern compiler intrinsic prototypes. See compiler User's Guide for details. // //***************************************************************************** extern uint16_t __disable_interrupts(void); extern uint16_t __enable_interrupts(void); //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** #endif // #ifdef __TMS320C28XX__ //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // INTERRUPT_H