empty_project_28377D/device/driverlib/interrupt.c

424 lines
11 KiB
C

//###########################################################################
//
// FILE: interrupt.c
//
// 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.
// $
//###########################################################################
#include "interrupt.h"
//*****************************************************************************
//
//! \internal
//! Clears the IFR flag in the CPU.
//!
//! \param group specifies the interrupt group to be cleared.
//!
//! This function clears the IFR flag. This switch is needed because the
//! clearing of the IFR can only be done with a constant.
//
//*****************************************************************************
static void Interrupt_clearIFR(uint16_t group)
{
switch(group)
{
case 0x0001U:
IFR &= ~(uint16_t)0x0001U;
break;
case 0x0002U:
IFR &= ~(uint16_t)0x0002U;
break;
case 0x0004U:
IFR &= ~(uint16_t)0x0004U;
break;
case 0x0008U:
IFR &= ~(uint16_t)0x0008U;
break;
case 0x0010U:
IFR &= ~(uint16_t)0x0010U;
break;
case 0x0020U:
IFR &= ~(uint16_t)0x0020U;
break;
case 0x0040U:
IFR &= ~(uint16_t)0x0040U;
break;
case 0x0080U:
IFR &= ~(uint16_t)0x0080U;
break;
case 0x0100U:
IFR &= ~(uint16_t)0x0100U;
break;
case 0x0200U:
IFR &= ~(uint16_t)0x0200U;
break;
case 0x0400U:
IFR &= ~(uint16_t)0x0400U;
break;
case 0x0800U:
IFR &= ~(uint16_t)0x0800U;
break;
case 0x1000U:
IFR &= ~(uint16_t)0x1000U;
break;
case 0x2000U:
IFR &= ~(uint16_t)0x2000U;
break;
case 0x4000U:
IFR &= ~(uint16_t)0x4000U;
break;
case 0x8000U:
IFR &= ~(uint16_t)0x8000U;
break;
default:
//
// Invalid group mask.
//
ASSERT((bool)false);
break;
}
}
//*****************************************************************************
//
// Interrupt_initModule
//
//*****************************************************************************
void
Interrupt_initModule(void)
{
//
// Disable and clear all interrupts at the CPU
//
(void)Interrupt_disableGlobal();
IER = 0x0000U;
IFR = 0x0000U;
//
// Clear all PIEIER registers
//
HWREGH(PIECTRL_BASE + PIE_O_IER1) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER2) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER3) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER4) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER5) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER6) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER7) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER8) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER9) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER10) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER11) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IER12) = 0U;
//
// Clear all PIEIFR registers
//
HWREGH(PIECTRL_BASE + PIE_O_IFR1) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR2) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR3) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR4) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR5) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR6) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR7) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR8) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR9) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR10) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR11) = 0U;
HWREGH(PIECTRL_BASE + PIE_O_IFR12) = 0U;
//
// Enable vector fetching from PIE block
//
HWREGH(PIECTRL_BASE + PIE_O_CTRL) |= PIE_CTRL_ENPIE;
}
//*****************************************************************************
//
//! The default interrupt handler.
//!
//! \return None.
//
//*****************************************************************************
__interrupt void Interrupt_defaultHandler(void)
{
uint16_t pieVect;
uint16_t vectID;
//
// Calculate the vector ID. If the vector is in the lower PIE, it's the
// offset of the vector that was fetched (bits 7:1 of PIECTRL.PIEVECT)
// divided by two.
//
pieVect = HWREGH(PIECTRL_BASE + PIE_O_CTRL);
vectID = (pieVect & 0xFEU) >> 1U;
//
// If the vector is in the upper PIE, the vector ID is 128 or higher.
//
if(pieVect >= 0x0E00U)
{
vectID += 128U;
}
//
// Something has gone wrong. An interrupt without a proper registered
// handler function has occurred. To help you debug the issue, local
// variable vectID contains the vector ID of the interrupt that occurred.
//
ESTOP0;
for(;;)
{
;
}
}
//*****************************************************************************
//
//! The default illegal instruction trap interrupt handler.
//!
//! \return None.
//
//*****************************************************************************
__interrupt void Interrupt_illegalOperationHandler(void)
{
//
// Something has gone wrong. The CPU has tried to execute an illegal
// instruction, generating an illegal instruction trap (ITRAP).
//
ESTOP0;
for(;;)
{
;
}
}
//*****************************************************************************
//
//! The default non-maskable interrupt handler.
//!
//! \return None.
//
//*****************************************************************************
__interrupt void Interrupt_nmiHandler(void)
{
//
// A non-maskable interrupt has occurred, indicating that a hardware error
// has occurred in the system. You can use SysCtl_getNMIFlagStatus() to
// to read the NMIFLG register and determine what caused the NMI.
//
ESTOP0;
for(;;)
{
;
}
}
//*****************************************************************************
//
// Interrupt_initVectorTable
//
//*****************************************************************************
void
Interrupt_initVectorTable(void)
{
uint16_t i;
EALLOW;
//
// We skip the first three locations because they are initialized by Boot
// ROM with boot variables.
//
for(i = 3U; i < 224U; i++)
{
HWREG(PIEVECTTABLE_BASE + (2U * i)) =
(uint32_t)Interrupt_defaultHandler;
}
//
// NMI and ITRAP get their own handlers.
//
HWREG(PIEVECTTABLE_BASE + ((INT_NMI >> 16U) * 2U)) =
(uint32_t)Interrupt_nmiHandler;
HWREG(PIEVECTTABLE_BASE + ((INT_ILLEGAL >> 16U) * 2U)) =
(uint32_t)Interrupt_illegalOperationHandler;
EDIS;
}
//*****************************************************************************
//
//Interrupt_enable
//
//*****************************************************************************
void
Interrupt_enable(uint32_t interruptNumber)
{
bool intsDisabled;
uint16_t intGroup;
uint16_t groupMask;
uint16_t vectID;
vectID = (uint16_t)(interruptNumber >> 16U);
//
// Globally disable interrupts but save status
//
intsDisabled = Interrupt_disableGlobal();
//
// PIE Interrupts
//
if(vectID >= 0x20U)
{
intGroup = (uint16_t)(((interruptNumber & 0xFF00UL) >> 8U) - 1U);
groupMask = (uint16_t)1U << intGroup;
HWREGH((PIECTRL_BASE + PIE_O_IER1 + (intGroup * 2U))) |=
(uint16_t)1U << ((interruptNumber & 0xFFU) - 1U);
//
// Enable PIE Group Interrupt
//
IER |= groupMask;
}
//
// INT13, INT14, DLOGINT, & RTOSINT
//
else if((vectID >= 0x0DU) && (vectID <= 0x10U))
{
IER |= (uint16_t)1U << (vectID - 1U);
}
else
{
//
// Other interrupts
//
}
//
// Re-enable interrupts if they were enabled
//
if(!intsDisabled)
{
(void)Interrupt_enableGlobal();
}
}
//*****************************************************************************
//
// Interrupt_disable
//
//*****************************************************************************
void
Interrupt_disable(uint32_t interruptNumber)
{
bool intsDisabled;
uint16_t intGroup;
uint16_t groupMask;
uint16_t vectID;
vectID = (uint16_t)(interruptNumber >> 16U);
intsDisabled = Interrupt_disableGlobal();
//
// PIE Interrupts
//
if(vectID >= 0x20U)
{
intGroup = (uint16_t)(((interruptNumber & 0xFF00UL) >> 8U) - 1U);
groupMask = (uint16_t)1U << intGroup;
//
// Disable individual PIE interrupt
//
HWREGH((PIECTRL_BASE + PIE_O_IER1 + (intGroup * 2U))) &=
~(1U << ((interruptNumber & 0xFFUL) - 1U));
//
// Wait for any pending interrupts to get to the CPU
//
NOP;
NOP;
NOP;
NOP;
NOP;
Interrupt_clearIFR(groupMask);
//
// Acknowledge any interrupts
//
HWREGH(PIECTRL_BASE + PIE_O_ACK) = groupMask;
}
//
// INT13, INT14, DLOGINT, & RTOSINT
//
else if((vectID >= 0x0DU) && (vectID <= 0x10U))
{
IER &= ~((uint16_t)1U << (vectID - 1U));
//
// Wait for any pending interrupts to get to the CPU
//
NOP;
NOP;
NOP;
NOP;
NOP;
Interrupt_clearIFR((uint16_t)1U << (vectID - 1U));
}
else
{
//
// Other interrupts
//
}
//
// Re-enable interrupts if they were enabled
//
if(!intsDisabled)
{
(void)Interrupt_enableGlobal();
}
}