📄 lh7a404_vic_driver.c
字号:
* for VIC2 and mask it with the inverted value of the VIC2
* interrupt select register. Get the pending interrupt status from
* the FIQ status register for VIC2 and mask it with the value of
* the VIC2 interrupt select register. 'OR' the two masked values
* together to get a pending interrupt bitfield of enabled
* interrupts. Mask the 'OR'ed value with the bit fromt the
* interrupt source. If the resulting value is not zero, then
* return TRUE to the caller. Otherwise, return FALSE.
*
* Parameters:
* source : Interrupt source of type VIC_INT_SOURCE_T
*
* Outputs: None
*
* Returns: Returns TRUE if the interrupt is pending, otherwise FALSE.
*
* Notes:
* This will only report the pending status of IRQ or FIQ
* configured interrupts.
*
**********************************************************************/
BOOL_32 vic_int_pending(VIC_INT_SOURCE_T source)
{
UNS_32 status_irq, status_fiq, pstatus;
BOOL_32 pending = FALSE;
if ((source >= VIC_FIRST_VIC1_INTERRUPT) &&
(source <= VIC_LAST_VIC1_INTERRUPT))
{
status_irq = VIC1->irqstatus & ~(VIC1->intsel);
status_fiq = VIC1->fiqstatus & (VIC1->intsel);
pstatus = (status_fiq | status_irq) &
VIC_INT_SELECT((UNS_32)(source));
}
else
{
status_irq = VIC2->irqstatus & ~(VIC2->intsel);
status_fiq = VIC2->fiqstatus & (VIC2->intsel);
pstatus = (status_fiq | status_irq) &
VIC_INT_SELECT((UNS_32)(source - VIC_FIRST_VIC2_INTERRUPT));
}
/* Was the unmasked IRQ or FIQ interrupt pending? */
if (pstatus != 0)
{
/* Yes, it is pending */
pending = TRUE;
}
return pending;
}
/***********************************************************************
*
* Function: vic_int_enabled
*
* Purpose: Check to see if an interrupt is enabled
*
* Processing:
* If the interrupt source is in the range of the first VIC, then
* check the VIC1 interrupt enabled register masked by the enable
* bit for the passed interrupt source. If the bit is set, then
* return TRUE to the caller. Otherwise, check the VIC2 interrupt
* enabled register masked by the enable bit for the passed
* interrupt source, adjusted for the 2nd VIC bit sift. If the bit
* is set, then return TRUE to the caller. Otherwise, return FALSE
* to the caller.
*
* Parameters:
* source : Interrupt source of type VIC_INT_SOURCE_T
*
* Outputs: None
*
* Returns: Returns TRUE if the interrupt is enabled, otherwise FALSE.
*
* Notes: None
*
**********************************************************************/
BOOL_32 vic_int_enabled(VIC_INT_SOURCE_T source)
{
UNS_32 intreg;
BOOL_32 enabled = FALSE;
if ((source >= VIC_FIRST_VIC1_INTERRUPT) &&
(source <= VIC_LAST_VIC1_INTERRUPT))
{
intreg = VIC1->inten & VIC_INT_SELECT((UNS_32)source);
}
else
{
intreg = VIC2->inten & VIC_INT_SELECT((UNS_32)source -
VIC_FIRST_VIC2_INTERRUPT);
}
/* Was the interrupt enabled? */
if (intreg != 0)
{
/* Yes, it is enabled */
enabled = TRUE;
}
return enabled;
}
/***********************************************************************
*
* Function: vic_clear_int
*
* Purpose: Clears the vectored interrupt (called after a vectored
* interrupt)
*
* Processing:
* If the interrupt source is in the range of the first VIC, then
* clear the interrupt from the first VIC. Otherwise, clear the
* interrupt from the second VIC. The interrupt is cleared by
* reading the vectored address register.
*
* Parameters:
* source : Interrupt source of type VIC_INT_SOURCE_T
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void vic_clear_int(VIC_INT_SOURCE_T source)
{
if ((source >= VIC_FIRST_VIC1_INTERRUPT) &&
(source <= VIC_LAST_VIC1_INTERRUPT))
{
VIC1->vecaddr = 0x00000000;
}
else
{
VIC2->vecaddr = 0x00000000;
}
}
/***********************************************************************
*
* Function: vic_arm_irq_dispatcher
*
* Purpose: Default ARM core IRQ interrupt dispatcher
*
* Processing:
* This interrupt dispatch function is called when an IRQ interrupt
* is generated at the ARM core. The VIC vectored address register
* is read for both VICs. If they are the same, then the interrupt
* source was VIC2 and the handler address (also the VIC2 vectored
* address register) is used as the function address and called.
* The VIC(2) is then cleared and the interrupt is exited. If the
* addresses are not the same, then the interrupt source was VIC1
* and the handler address (also the VIC1 vectored address register)
* is used as the function address and called. The VIC(1) is then
* cleared and the interrupt is exited.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
***********************************************************************/
#define __arm
//#ifndef __GNUC__
//#ifndef __ICCARM__
//#ifdef __ghs__
//__interrupt void vic_arm_irq_dispatcher(void)
//#endif
//#ifdef __arm
//__irq void vic_arm_irq_dispatcher(void)
void vic_arm_irq_dispatcher(void)
//#endif
{
PFV vic_vecaddr;
/* Check VIC1 IRQ status - if it is 0, then there are no VIC1
interrupts pending. That means, go service VIC2 interrupts
instead. */
if (VIC1->irqstatus != 0)
{
/* Use VIC1 for the jump address */
vic_vecaddr = (PFV) VIC1->nv_vecaddr;
}
else
{
/* Use VIC2 for the jump address */
vic_vecaddr = (PFV) VIC2->nv_vecaddr;
}
/* Jump to interrupt handler */
vic_vecaddr();
}
//#endif
//#endif
/***********************************************************************
*
* Function: vic1_irq_dispatcher
*
* Purpose: Default IRQ interrupt dispatcher for VIC1
*
* Processing:
* This function is called by the vic_arm_irq_dispatcher function
* when a vectored interrupt is configured as a standard IRQ type
* interrupt and the interrupt source is VIC1. All interrupts for
* this VIC are checked against the interrupt status and verified
* that it is not masked. If it is pending and the interrupt
* function is not 0x00000000, then the interrupt function is
* called.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: This dispatcher does not support nesting or prioritization
*
***********************************************************************/
void vic1_irq_dispatcher(void)
{
UNS_32 selints;
VIC_INT_SOURCE_T source = VIC_FIRST_VIC1_INTERRUPT;
/* Get mask for valid IRQ interrupts */
selints = ~(VIC1->intsel);
/* Loop through all interrupts looking for the first active
interrupt */
while (source <= VIC_LAST_VIC1_INTERRUPT)
{
if ((VIC1->irqstatus & selints & VIC_INT_SELECT(source)) != 0)
{
if (vic_func_ptrs[source] != (PFV) 0x00000000)
{
/* Jump to interrupt handler */
vic_func_ptrs[source]();
}
/* Force loop exit */
source += VIC_LAST_VIC1_INTERRUPT;
}
else
{
source++;
}
}
}
/***********************************************************************
*
* Function: vic2_irq_dispatcher
*
* Purpose: Default IRQ interrupt dispatcher for VIC2
*
* Processing:
* This function is called by the vic_arm_irq_dispatcher function
* when a vectored interrupt is configured as a standard IRQ type
* interrupt and the interrupt source is VIC2. All interrupts for
* this VIC are checked against the interrupt status and verified
* that it is not masked. If it is pending and the interrupt
* function is not 0x00000000, then the interrupt function is
* called.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: This dispatcher does not support nesting or prioritization
*
***********************************************************************/
void vic2_irq_dispatcher(void)
{
UNS_32 selints;
// VIC_INT_SOURCE_T source = VIC_FIRST_VIC2_INTERRUPT;
static UNS_32 vic1,vic2,i,tmp;
VIC_INT_SOURCE_T source = VIC_UART2INTR;
vic1= (0x80008000); ///read status register
vic2= (0x8000a000);
for(i=0;i<32;i++)
{
tmp= vic2 & (0x1<<i);
if (tmp)
break;
};
source = i + 32;
/* Get mask for valid IRQ interrupts */
selints = ~(VIC2->intsel);
/* Loop through all interrupts looking for the first active
interrupt */
while (source <= VIC_LAST_VIC2_INTERRUPT)
{
if ((VIC2->irqstatus & selints &
VIC_INT_SELECT(source - VIC_FIRST_VIC2_INTERRUPT)) != 0)
{
if (vic_func_ptrs[source] != (PFV) 0x00000000)
{
/* Jump to interrupt handler */
vic_func_ptrs[source](); ///
}
/* Force loop exit */
source += VIC_LAST_VIC2_INTERRUPT;
}
else
{
source++;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -