📄 lh7a400_int_driver.c
字号:
* Call this from int_init_irq_handler() only.
*
**********************************************************************/
#if defined(INTC_IRQ)
static void int_install_irq_dispatcher(void)
#else
void int_install_irq_dispatcher(__irq void (*fp)(void))
#endif
{
#if !defined(INTC_IRQ)
irq_dispatcher_addr = (UNS_32)fp;
#endif
*((volatile UNS_32 *)(ARM_IRQ_VEC - sizeof(UNS_32) ))
= irq_dispatcher_addr;
*((volatile UNS_32 *)ARM_IRQ_VEC) = irq_vec;
LH7A400_force_cache_coherence(
((UNS_32 *)(ARM_IRQ_VEC - sizeof(UNS_32) )),
((UNS_32 *)ARM_IRQ_VEC) );
}
/**********************************************************************
*
* Function: int_install_fiq_dispatcher
*
* Purpose:
* Copy the FIQ dispatcher into the FIQ excepton space
*
* Processing:
* Copy all FIQ-dispatcher related code into volatile memory in the
* FIQ exception space. This is the FIQ dispatcher itself, the
* FIQ priority encode array, and the array of handlers.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* This function requires that sufficient volatile memory starting
* at the FIQ exception vector location (0x1C) is available (about
* 64 bytes)
*
**********************************************************************/
static void int_install_fiq_dispatcher(void)
{
volatile UNS_32 * ptr, * ptr_ram;
ptr_ram = (UNS_32 *)(ARM_FIQ_VEC);
for (ptr = &LH7A400_FIQ_dispatcher;
ptr < &LH7A400_FIQ_disp_end;
ptr++,ptr_ram++)
*ptr_ram = *ptr;
LH7A400_force_cache_coherence((UNS_32 *)(ARM_FIQ_VEC),
(UNS_32 *)ptr_ram);
}
/**********************************************************************
*
* Function: int_init_irq_handler
*
* Purpose:
* Initialize the IRQ dispatcher and handler function arrays to a known
* state so that handlers may be subsequently installed. Set up the
* IRQ exception vector so that any IRQ exception will vector to
* the LH7A400_IRQ_handler fuction.
*
* Processing:
* Associate each source with no handler function handlers[source]=0 and
* with illegal priority priorities[source] = N_IRQ_HANDLERS. Make
* all priority encode tables priority_encode0..2[all combinations]=
* N_IRQ_HANDLERS.
*
* Parameters:
* force_init: This should be non-zero to force an initialization to
* reset all priority tables. Set this to zero for normal
* initialization sequence.
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* You must call this function before installing any IRQ handlers and
* before enabling IRQ interrupts.
* This function "remembers" previous initializations. To force an
* init regardless of previous initializations, set force_init to a
* non-zero value.
**********************************************************************/
void int_init_irq_handler(INT_32 force_init)
{
if ((0 == force_init) && initialized) return;
priority_init_driver(&irq_data, LH7A400_unhandled_handler);
INTC->enableclear = INTC_ALL_IRQS;
#if defined(INTC_IRQ)
/* install LH7A400_IRQ_dispatcher() at IRQ exception location */
int_install_irq_dispatcher();
#endif
initialized = 1;
}
/**********************************************************************
*
* Function: int_install_irq_handler
*
* Purpose:
* This function installs the IRQ handler for a particular interrupt
* source. The priority of the handler can be defined, with 0 being
* highest priority and 23 being the lowest.
*
* Processing:
* If the handler function is NULL, if the requested priority is out
* of range, if the source is out of range return N_IRQ_HANDLERS.
* Otherwise, install the handler function in the handler array at
* the priority index. If the old priority for the source is the same
* as the new priority, then we are just changing the handler function.
* Otherwise, we have to clear the handler for the source that previously
* had this priority from the priority encoder arrays and reassign the
* priority to the new source.
*
* Parameters:
* souce: the bit number of the IRQ source. See LH7A400_map.h
* priority: a number between 0 and 23. 23 is the lowest priority.
* hp: a pointer to a function that returns nothing and takes no
* arguments.
*
* Outputs: None
*
* Returns:
* The function returns the priority of the handler if the installation
* is successful, otherwise it returns N_IRQ_HANDLERS.
*
* Notes:
* It is important that the application ensures that every handler is
* assigned a unique priority. Otherwise, the most recently installed
* handler will be associated with the given priority and the previous
* handler will be lost, and may result in the interrupt for the
* corresponding source not being serviced.
*
* (*hp)() must clear the interrupt before it exits.
*
**********************************************************************/
INT_8 int_install_irq_handler(UNS_32 source,
UNS_32 priority,
void (*hp)(void))
{
if ((source > INTC_N_SOURCES_TOTAL) ||
(priority > INTC_N_SOURCES_TOTAL))
return -1;
else
return priority_install_handler(&irq_data,
(INT_8)(source - INTC_N_FIQ_HANDLERS),
(INT_8)priority,
hp,
LH7A400_unhandled_handler);
}
/**********************************************************************
*
* Function: int_remove_irq_handler
*
* Purpose:
* Remove the assoication between a priority and a source
*
* Processing:
* Use a sentinel search algorithm to determine the source from
* the priority. Set the handler function pointer to 0. Set the
* source priority to ILLEGAL_PRIORITY and rebuild the priority
* encode tables.
*
* Parameters: None
*
* Outputs: None
*
* Returns:
* The priority that was removed or ILLEGAL_PRIORITY if the priority
* was never installed
*
* Notes:
*
**********************************************************************/
INT_8 int_remove_irq_handler(UNS_32 priority)
{
if (priority > INTC_N_SOURCES_TOTAL)
return -1;
else
return priority_remove_handler(&irq_data,
(INT_8)priority,
LH7A400_unhandled_handler);
}
/**********************************************************************
*
* Function: int_enable_interrupt
*
* Purpose:
* Enable a source at the interrupt controller
*
* Processing:
* Set the bit in the interrupt controller's Enable register
*
* Parameters:
* source: bit number of the interrupt
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* Argument passed must be the IRQ number.
*
**********************************************************************/
void int_enable_interrupt(UNS_32 source)
{
INTC->enableset |= _BIT(source);
}
/**********************************************************************
*
* Function: int_disable_interrupt
*
* Purpose:
* Disable a source at the interrupt controller
*
* Processing:
* Set the bit in the interrupt controller's disable register
*
* Parameters:
* source: bit number of the interrupt
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* Argument passed must be the IRQ number.
*
**********************************************************************/
void int_disable_interrupt(UNS_32 source)
{
INTC->enableclear |= _BIT(source);
}
/**********************************************************************
*
* Function: int_enabled
*
* Purpose:
* Return 1 if an interrupt is enabled, otherwise, return 0
*
* Processing:
* compare the interrupt controller register to the 1 left shifted by
* the source parameter
*
* Parameters:
* source: the bit number of the interrupt
*
* Outputs: None
*
* Returns:
* Return the bit number if the interrupt is enabled,
* otherwise, return 0
*
* Notes:
* Argument passed must be the interrupt controller bit number.
* as defined in LH7A400_map.h for each interrupt source.
*
**********************************************************************/
UNS_32 int_enabled(UNS_32 source)
{
if (source > INTC_N_SOURCES_TOTAL)
return -1;
else
return (INTC->enableset & _BIT(source) != 0);
}
/**********************************************************************
*
* Function: int_pending
*
* Purpose:
* Return 1 if an interrupt is pending, otherwise, return 0
*
* Processing:
* compare the interrupt controller register to the 1 left shifted by
* the source parameter
*
* Parameters:
* source: the bit number of the interrupt
*
* Outputs: None
*
* Returns:
* Return the bit number if the interrupt is enabled,
* otherwise, return 0
*
* Notes:
* Argument passed must be the interrupt controller bit number.
* as defined in LH7A400_map.h for each interrupt source.
*
**********************************************************************/
UNS_32 int_pending(UNS_32 source)
{
if (source > INTC_N_SOURCES_TOTAL)
return -1;
else
return (INTC->status & _BIT(source) != 0);
}
/**********************************************************************
*
* Function: int_irq_priority
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -