/************************************************************************** * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file * * @date 09-Jan-2020 * @author Leonardo Baloa * * @brief TODO:Put a brief * **************************************************************************/ /** @file irqDispatch_c.c * @brief contains Second Level IRQ Dispatcher C routine * @date 5/13/2014 * @note */ #if defined(__TI_VIM_128CH__) //#include "HL_sys_common.h" //#include "HL_sys_vim.h" #include "sys_common.h" #include "sys_vim.h" #elif defined(__TI_VIM_96CH__) #include "sys_common.h" #include "sys_vim.h" #else #error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. #endif /** @typedef vimRAM_t * @brief Vim Ram Definition * * This type is used to access the VIM RAM. */ typedef volatile struct vimRam { t_isrFuncPTR ISR[VIM_CHANNELS + 1]; } vimRAM_t; /** @var vimRAM_t * const vimRAM * @brief vimRAM definition * * This variable is used to access the VIM RAM. */ static const vimRAM_t * const vimRAM = ((vimRAM_t *)0xFFF82000U); /** @var sint32 s32NestingLevel; * @brief Variable to store the current level of nesting * */ static sint32 s32NestingLevel = 0; /** @def MAX_NESTING_LEVEL * @brief Defines max nesting deep * */ #define MAX_NESTING_LEVEL 8 /** @fn void C_irqDispatch(void) * @brief Second Level IRQ Dispatcher C routine * @note This implementation is limited to the use of the first 96 interrupt priority's. * */ /* Ensure that the function is coded with ARM mode instructions. */ #pragma CODE_STATE(C_irqDispatch, 32); /* Inform the Compiler that the function is called externally, and thus should not be removed. */ #pragma FUNC_EXT_CALLED(C_irqDispatch); void C_irqDispatch(void) { /* TI C Step 1 */ uint32 u32IrqIndex = vimREG->IRQINDEX; /* Read IRQ Index Offset Vector */ /* TI C Step 2 */ t_isrFuncPTR irq_func_pnt = vimRAM->ISR[u32IrqIndex]; /* Read IRQ Interrupt Vector */ /** Note: * Do not use the IRQVECREG to readout the vector address, as this could change between Step 1 and 2. * As an alternative you could read out the vector from the constant table which was used to initialize the VIM RAM. * This method should be faster than reading the vector address from the VIM RAM, as Flash accesses are faster than peripheral accesses. */ /* IRQIVEC is zero if no interrupt is pending */ if (0U == u32IrqIndex) { /* Phantom Interrupt */ /** @todo * Add custom fault handler, if necessary. */ while(1); } else { /* Increment Nesting Level indicator */ s32NestingLevel++; /* If Nesting Level indicator is less than the max level, enable IRQ to allow further preemption */ if ((MAX_NESTING_LEVEL) > s32NestingLevel) { /* TI C Step 3 */ /* Save VIM REQENASET[0,1,2] Registers for later restore */ uint32 SaveREQMASKSET0 = vimREG->REQMASKSET0; uint32 SaveREQMASKSET1 = vimREG->REQMASKSET1; uint32 SaveREQMASKSET2 = vimREG->REQMASKSET2; #if defined(__TI_VIM_128CH__) uint32 SaveREQMASKSET3 = vimREG->REQMASKSET3; #endif /* TI C Step 4 */ /* Mask out lower priority IRQ's and the current IRQ itself, keep FIQ's enabled */ if (96U < u32IrqIndex) /* 96-...*/ { #if defined(__TI_VIM_128CH__) /* REG->REQMASKCLR0 = ( 0xFFFFFFFCU & (~vimREG->FIRQPR0)); Higher priority */ /* REG->REQMASKCLR1 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR1)); Higher priority */ /* REG->REQMASKCLR2 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR2)); Higher priority */ vimREG->REQMASKCLR3 = ((0xFFFFFFFFU << (u32IrqIndex - 97U)) & (~vimREG->FIRQPR3)); vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ #elif defined(__TI_VIM_96CH__) /** @todo * Add custom fault handler, if necessary. */ while (1); /* Fault */ #else #error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. #endif } else if (64U < u32IrqIndex) /* 64-96 */ { /* REG->REQMASKCLR0 = ( 0xFFFFFFFCU & (~vimREG->FIRQPR0)); Higher priority */ /* REG->REQMASKCLR1 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR1)); Higher priority */ vimREG->REQMASKCLR2 = ((0xFFFFFFFFU << (u32IrqIndex - 65U)) & (~vimREG->FIRQPR2)); #if defined(__TI_VIM_128CH__) vimREG->REQMASKCLR3 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR3)); vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ #elif defined(__TI_VIM_96CH__) vimREG->REQMASKCLR2; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ #else #error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. #endif } else if (32U < u32IrqIndex) /* 32-63 */ { /* REG->REQMASKCLR0 = ( 0xFFFFFFFCU & (~vimREG->FIRQPR0)); Higher priority */ vimREG->REQMASKCLR1 = ((0xFFFFFFFFU << (u32IrqIndex - 33U)) & (~vimREG->FIRQPR1)); vimREG->REQMASKCLR2 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR2)); #if defined(__TI_VIM_128CH__) vimREG->REQMASKCLR3 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR3)); vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ #elif defined(__TI_VIM_96CH__) vimREG->REQMASKCLR2; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ #else #error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. #endif } else if ( 2U < u32IrqIndex) /* 2-31 */ { vimREG->REQMASKCLR0 = ((0xFFFFFFFFU << (u32IrqIndex - 1U)) & (~vimREG->FIRQPR0)); vimREG->REQMASKCLR1 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR1)); vimREG->REQMASKCLR2 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR2)); #if defined(__TI_VIM_128CH__) vimREG->REQMASKCLR3 = ( 0xFFFFFFFFU & (~vimREG->FIRQPR3)); vimREG->REQMASKCLR3; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ #elif defined(__TI_VIM_96CH__) vimREG->REQMASKCLR2; /* Readback Mask to ensure that the previous write was finished before enabling interrupts again */ #else #error File irqDispatcher.c requires either __TI_VIM_96CH__ or __TI_VIM_128CH__ to be defined. #endif } else /* if (0U < u32IrqIndex) */ /* 0 and 1 */ { /* Vectors 0 and 1 are tied to FIQ and this code is thus dead for IRQ. */ /** @todo * Add custom fault handler, if necessary. */ while (1); /* Fault */ } /* TI C Step 5 */ _enable_IRQ(); /* Enable IRQ, to allow preemption of IRQ routine */ /* TI C Step 6 */ (*irq_func_pnt)(); /* Execute interrupt routine */ /* TI C Step 7 */ _disable_IRQ(); /* Disable IRQ, to protect the remainder of the dispatcher from preemption */ /* TI C Step 8 */ /* Restore VIM REQENASET[0,1,2] Registers */ vimREG->REQMASKSET0 = SaveREQMASKSET0; vimREG->REQMASKSET1 = SaveREQMASKSET1; vimREG->REQMASKSET2 = SaveREQMASKSET2; #if defined(__TI_VIM_128CH__) vimREG->REQMASKSET3 = SaveREQMASKSET3; #endif } else { /* Do not enable IRQ, because max nesting level was reached */ (*irq_func_pnt)(); /* Execute interrupt routine */ } if (0 < s32NestingLevel) { s32NestingLevel--; } } /* TI C Step 9 */ return; /* Return to First Level IRQ Dispatcher Assembly routine */ }