📄 intr.c
字号:
//
BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
{
BOOL rc = TRUE;
UINT32 i, bit_pos;
INTERRUPT_SOURCE_T lirq;
INTC_REGS_T *pIntc;
OALMSG((OAL_INTR&&OAL_FUNC), (L"+OALIntrEnableIrqs\r\n"));
// Enable each IRQ
for (i = 0; i < count; i++)
{
// Out of range?
if (pIrqs[i] <= OAL_INTR_IRQ_LAST)
{
lirq = lp32xx_ierqsupp[pIrqs[i]].lpc32xx_irq_num;
if (lirq == VIRTINTR)
{
// Interrupt is virtual, call virtual interrupt handler
rc = IntrEnableVirtual((OAL_TO_HW_IRQ_T *) &pIrqs[i], TRUE);
}
else if (int_get_controller(lirq, &pIntc, &bit_pos) == TRUE)
{
// Get the interrupt controller for the given interrupt source
pIntc->er |= _BIT(bit_pos);
}
}
else
{
rc = FALSE;
}
}
OALMSG((OAL_INTR&&OAL_FUNC), (L"-OALIntrEnableIrqs(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// OALIntrDisableIrqs
//
// Disable one or more LPC32XX IRQs.
//
VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs)
{
INTERRUPT_SOURCE_T lirq;
INTC_REGS_T *pIntc;
UINT32 i, bit_pos = 0;
OALMSG((OAL_INTR&&OAL_FUNC), (L"+OALIntrDisableIrqs(%d, 0x%08x)\r\n",
count, pIrqs));
// Disable each IRQ
for (i = 0; i < count; i++) {
// Out of range?
if (pIrqs[i] <= OAL_INTR_IRQ_LAST)
{
lirq = lp32xx_ierqsupp[pIrqs[i]].lpc32xx_irq_num;
if (lirq == VIRTINTR)
{
// Interrupt is virtual, call virtual interrupt handler
IntrEnableVirtual((OAL_TO_HW_IRQ_T *) &pIrqs[i], FALSE);
}
else if (int_get_controller(lirq, &pIntc, &bit_pos) == TRUE)
{
// Get the interrupt controller for the give interrupt source
pIntc->er &= ~_BIT(bit_pos);
}
}
}
OALMSG((OAL_INTR&&OAL_FUNC), (L"-OALIntrDisableIrqs\r\n"));
}
//------------------------------------------------------------------------------
//
// IntrDoneVirtual
//
// Used for clearing and re-enabling virtual interrupts (DMA).
//
static BOOL IntrDoneVirtual(OAL_TO_HW_IRQ_T *pIrqHw)
{
UINT32 dmaChan, msk;
BOOL rc = FALSE;
// For now, these only apply to DMA
if ((pIrqHw->oal_intr_irq_num >= OAL_INTR_DMACH_0) &&
(pIrqHw->oal_intr_irq_num <= OAL_INTR_DMACH_6))
{
// Get DMA channel
dmaChan = (UINT32) pIrqHw->oal_intr_irq_num - OAL_INTR_DMACH_0;
// Only works when DMA channel has been enabled
msk = _BIT(dmaChan);
// Clear latched TC and ERR interrupt flags
pDMARegs->int_tc_clear = msk;
pDMARegs->int_err_clear = msk;
// Re-enable channel
pDMARegs->dma_chan[dmaChan].config_ch |= (DMAC_CHAN_ITC | DMAC_CHAN_IE);
rc = TRUE;
}
return rc;
}
//------------------------------------------------------------------------------
//
// OALIntrDoneIrqs
//
// Re-enable obe or more LPC32xx IRQs.
//
VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
INTERRUPT_SOURCE_T lirq;
INTC_REGS_T *pIntc;
UINT32 i, bit_pos = 0;
OALMSG((OAL_INTR&&OAL_FUNC), (
L"+OALIntrDoneIrqs(%d, 0x%08x)\r\n", count, pIrqs));
for (i = 0; i < count; i++) {
// Out of range?
if (pIrqs[i] <= OAL_INTR_IRQ_LAST)
{
lirq = lp32xx_ierqsupp[pIrqs[i]].lpc32xx_irq_num;
if (lirq == VIRTINTR)
{
// Interrupt is virtual, call virtual interrupt handler
IntrDoneVirtual((OAL_TO_HW_IRQ_T *) &pIrqs[i]);
}
else
{
// Get the interrupt controller for the give interrupt source
if (int_get_controller(lirq, &pIntc, &bit_pos) == TRUE)
{
// Clear pending interrupt
pIntc->rsr = _BIT(bit_pos);
// Re-enable interrupt
pIntc->er |= _BIT(bit_pos);
}
}
}
}
OALMSG((OAL_INTR&&OAL_FUNC), (L"-OALIntrDoneIrqs\r\n"));
}
//------------------------------------------------------------------------------
//
// OALIntrRequestIrqs
//
// This function returns IRQs for CPU/SoC devices based on their
// physical address.
//
BOOL OALIntrRequestIrqs(DEVICE_LOCATION *pDevLoc, UINT32 *pCount, UINT32 *pIrqs)
{
BOOL rc = FALSE;
OALMSG((OAL_INTR&&OAL_FUNC), (L"+OALIntrRequestIrqs\r\n"));
// This shouldn't happen
if (*pCount < 1) goto cleanUp;
switch (pDevLoc->IfcType) {
case Internal:
switch ((ULONG)pDevLoc->PhysicalLoc) {
case ETHERNET_BASE:
*pCount = 1;
pIrqs[0] = OAL_INTR_IRQ_ETHERNET;
rc = TRUE;
break;
}
break;
}
OALMSG((OAL_INTR&&OAL_FUNC&&OAL_VERBOSE), (
L"+OALIntrRequestIrqs(0x%x->%d/%d/0x%x/%d, 0x%x, 0x%x)\r\n",
pDevLoc, pDevLoc->IfcType, pDevLoc->BusNumber, pDevLoc->LogicalLoc,
pDevLoc->Pin, pCount, pIrqs[0]
));
cleanUp:
OALMSG((OAL_INTR&&OAL_FUNC), (L"-OALIntrRequestIrqs(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// OEMInterruptHandler
//
// Handles the LPC32XX interrupts and generates the correct sysIntr values.
//
ULONG OEMInterruptHandler(ULONG ra)
{
DWORD dirq;
INTERRUPT_SOURCE_T intsrc;
INTC_REGS_T *pIntc;
UINT32 sts, sysIntr = SYSINTR_NOP, bit_pos = 0;
// Read MIC status masking off IRQ bits
sts = pMIC->sr & ~(_BIT(IRQ_SUB1IRQ) | _BIT(IRQ_SUB2IRQ) |
_BIT(IRQ_SUB1FIQ) | _BIT(IRQ_SUB2FIQ));
// Interrupt on MIC?
if (sts != 0)
{
// Find first active interrupt
bit_pos = (INTERRUPT_SOURCE_T) findfirstbit(sts);
intsrc = bit_pos;
pIntc = pMIC;
}
else if (pSIC1->sr != 0)
{
// Find first active interrupt
bit_pos = (INTERRUPT_SOURCE_T) findfirstbit(pSIC1->sr);
intsrc = bit_pos + IRQ_SIC1_BASE;
pIntc = pSIC1;
}
else if (pSIC2->sr != 0)
{
// Find first active interrupt
bit_pos = (INTERRUPT_SOURCE_T) findfirstbit(pSIC2->sr);
intsrc = bit_pos + IRQ_SIC2_BASE;
pIntc = pSIC2;
}
else
{
// This should never happen
return SYSINTR_NOP;
}
// Get BSP IRQ mapped to this hardware IRQ
sts = lp32xxToBSPIRQ [intsrc];
if ((sts == OAL_INTR_IRQ_UNDEFINED) && (intsrc != IRQ_DMA))
{
// Unmapped interrupt, disable interrupt
pIntc->er &= ~_BIT(bit_pos);
return SYSINTR_NOP;
}
// Is this the system timer interrupt?
if (sts == OAL_INTR_IRQ_TICK)
{
sysIntr = OALTimerIntrHandler();
}
#ifdef IMGPROFILFER
#if IMGPROFILFER==1
else if (sts == OAL_INTR_IRQ_PROFILER)
{
// Disable profiler interrupt
pIntc->er &= ~_BIT(bit_pos);
// Call profiler interrupt
if (g_pProfilerISR != NULL)
{
sysIntr = g_pProfilerISR(ra);
}
}
#endif
#endif
else if (intsrc == IRQ_DMA)
{
// DMA interrupt requires remapping to a virtual channel
// INTR value
dma_get_int_ch(&dirq);
IntrEnableVirtual((OAL_TO_HW_IRQ_T *) &lp32xx_ierqsupp[dirq], FALSE);
sysIntr = OALIntrTranslateIrq(dirq);
}
else
{
// Mapped interrupt, return SYSINTR value for the interrupt
sysIntr = OALIntrTranslateIrq(sts);
// Disable interrupt
pIntc->er &= ~_BIT(bit_pos);
}
return sysIntr;
}
//------------------------------------------------------------------------------
//
// OEMInterruptHandlerFIQ
//
// Stub function for ARM FIQ handler
//
void OEMInterruptHandlerFIQ()
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -