📄 lh7a404_vic_driver.c
字号:
/***********************************************************************
* $Workfile: lh7a404_vic_driver.c $
* $Revision: 1.6 $
* $Author: WellsK $
* $Date: Apr 15 2004 15:47:36 $
*
* Project: LH7A404 vectored interrupt driver
*
* Description:
* This file contains driver support for the LH7A404 vectored
* interrupt driver.
*
* Notes:
* This driver requires that the CP15 MMU driver is correctly
* working.
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a404/source/lh7a404_vic_driver.c-arc $
*
* Rev 1.6 Apr 15 2004 15:47:36 WellsK
* Added IAR intrinsic functions instead of inline assembly.
* Updated interrupt handler code with basic IRQ handler.
*
* Rev 1.5 Apr 12 2004 16:57:12 WellsK
* Added support for IAR toolchain.
*
* Rev 1.4 Sep 08 2003 12:25:54 WellsK
* Corrected cache flush addresses.
*
* Rev 1.3 Sep 08 2003 09:33:20 WellsK
* Added support to locate the interrupt vector table anywhere.
*
* Rev 1.2 Sep 02 2003 15:21:18 WellsK
* Added support for relocated interrupt vectors (located in high
* memory at address 0xFFFF0000).
*
* Rev 1.1 Jul 01 2003 12:32:38 WellsK
* Added exclusion of IRQ handler for GNU toolset.
*
* Rev 1.0 Jun 30 2003 16:32:46 WellsK
* Initial revision.
*
*
***********************************************************************
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
* COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
***********************************************************************/
#include "abl_arm_arch.h"
#include "abl_arm922t_cp15_driver.h"
#include "lh7a404_vic_driver.h"
#ifdef __ICCARM__
#include "inarm.h"
#endif
#define VIC_FIRST_VIC1_INTERRUPT 0
#define VIC_LAST_VIC1_INTERRUPT 31
#define ARM_RESET_VEC 0
/***********************************************************************
* Interrupt driver package data
***********************************************************************/
/* External vector jump addresses - setting one of these addresses with
a new address of a function will cause the new function to be called
when the interrupt or exception occurs */
extern UNS_32 lh7a404_reset_vector;
extern UNS_32 vec_reset_handler;
extern UNS_32 vec_undefined_handler;
extern UNS_32 vec_swi_handler;
extern UNS_32 vec_prefetch_handler;
extern UNS_32 vec_abort_handler;
extern UNS_32 vec_irq_handler;
extern UNS_32 vec_fiq_handler;
/* Interrupt vectors for VIC */
static PFV vic_func_ptrs[VIC_END_OF_INTERRUPTS];
/* Pointer to logical interrupt vector area (writable) */
UNS_32 *vecarea;
#define cp15_force_cache_coherence(a,b)
/***********************************************************************
* Vectored Interrupt driver private functions
***********************************************************************/
#ifdef __ghs__
/* Inline assembly function to return the MMU control register (GHS) */
asm UNS_32 get_mmu_control(void)
{
MRC ARM922T_MMU_CP, 0, r0, ARM922T_MMU_REG_CONTROL, c0, 0
}
#endif
/***********************************************************************
*
* Function: vic_int_write_table
*
* Purpose: Writes the vector table and jump addresses to vector area
*
* Processing:
* Copy the shadowed image of the interrupt and exception vector
* table from memory to the vector jump area (usually at location
* 0x00000000). Force out any cached values to external memory.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Nothing
*
* Notes:
* Ideally, we would check the state of the V bit in the CP15
* coprocessor register 1 to determine the address of the where
* the vector area is located. If that bit was set, the vectors
* would be located at address 0xFFFF0000 instead of 0x00000000.
* This function assumes that the vector area is at 0x00000000.
*
**********************************************************************/
void vic_int_write_table(void)
{
UNS_32 *dst, *dstsave, *src;
INT_32 vecsize;
UNS_32 high_vector;
/* If vector address is automatic address, compute address */
dst = vecarea;
if ((UNS_32) dst == 0xFFFFFFFF)
{
/* Assume that vector table is located at low vector
(0x00000000) address */
dst = (UNS_32 *) ARM_RESET_VEC;
/* Check status of high vector bit in MMU control register and
set destination address of vector table to high vector
address if bit is set */
#ifdef __ICCARM__
high_vector = __MRC(15, 0, 1, 0, 0);
#endif
#ifdef __GNUC__
asm ("MRC p15, 0, %0, c1, c0, 0" : : "r" (high_vector));
#endif
#ifdef __ghs__
high_vector = get_mmu_control();
#endif
#ifdef __arm
__asm
{
MRC ARM922T_MMU_CP, 0, high_vector, \
ARM922T_MMU_REG_CONTROL, c0, 0
}
#endif
/* If high bit is set, use high vector addresses instead */
if ((high_vector & ARM922T_MMU_CONTROL_V) != 0)
{
dst = (UNS_32 *) 0xFFFF0000;
}
}
/* Copy vector block to interrupt vector area */
dstsave = dst;
for (src = (UNS_32 *) &lh7a404_reset_vector;
src <= (UNS_32 *) &vec_fiq_handler; src++)
{
*dst = *src;
dst++;
}
/* Write out cached vector table to memory */
vecsize = ((INT_32) &vec_fiq_handler -
(INT_32) &lh7a404_reset_vector) / 4;
cp15_force_cache_coherence(dstsave, (dstsave + vecsize));
}
/***********************************************************************
*
* Function: vic_check_and_install
*
* Purpose: Checks, updates, and installs a new vector
*
* Processing:
* If the interrupt source is in the range of the first VIC, then
* use the VIC1 base registers as the vic base pointer, else use
* the VIC2 base registers and adjust the source by 32 to align with
* the bits in VIC2. LLoop throuogh all the interrupt vector
* control words and verify that the source is not used in any
* of the enabled vector control words. If it is used, just
* update the vector control word with the new address that it
* is already used with, enable the vector, and return TRUE to the
* caller. If none of the vector control words are used with that
* source, then loop through the control words and find the first
* available unused control word. If one isn't available, return
* FALSE to the caller. Otherwise, update the vector control word
* with the new address, enable the vector, and return TRUE to the
* caller
*
* Parameters:
* source : Interrupt source of type VIC_INT_SOURCE_T
* itype : Must be VIC_IRQ, VIC_FIQ, or VIC_VECTORED
* func_ptr : Pointer to a void function
*
* Outputs: None
*
* Returns: TRUE if the vector was installed, otherwise FALSE
*
* Notes: None
*
**********************************************************************/
BOOL_32 vic_check_and_install(VIC_INT_SOURCE_T source,
VIC_INT_T itype,
PFV func_ptr)
{
VIC_REGS_T *vicp;
INT_32 idx;
BOOL_32 vicinst;
if ((source >= VIC_FIRST_VIC1_INTERRUPT) &&
(source <= VIC_LAST_VIC1_INTERRUPT))//lh7a404_vic_driver.c
{
/* Use VIC1 */
vicp = VIC1;
}
else
{
/* Use VIC2 */
vicp = VIC2;
/* Adjust source value to get bits for VIC2 */
source = source - VIC_FIRST_VIC2_INTERRUPT;
}
/* VIC vectored interrupt - first, make sure the requested
interrupt is not already installed */
vicinst = FALSE;
idx = 0;
while ((idx < 16) && (vicinst == FALSE))
{
/* Does this vector use this source? */
if ((vicp->vec_cntl[idx] & VIC_VEC_SEL_MSK) == (UNS_32) source)
{
/* It does, so just re-install the new vectored jump address
in this vector and make sure the vector is enabled */
vicp->vecaddrs[idx] = func_ptr;
vicp->vec_cntl[idx] |= VIC_VEC_EN;
/* The vector is installed */
vicinst = TRUE;
}
else
{
/* Check next vector */
idx++;
}
}
/* If the vector wasn't installed, install it in the first
available slot */
if (vicinst == FALSE)
{
idx = 0;
while ((idx < 16) && (vicinst == FALSE))
{
if ((vicp->vec_cntl[idx] & VIC_VEC_EN) == 0)
{
/* Free slot, use it */
vicp->vecaddrs[idx] = func_ptr;
vicp->vec_cntl[idx] = ((UNS_32) source | VIC_VEC_EN);
/* The vector is installed */
vicinst = TRUE;
}
else
{
/* Check next vector */
idx++;
}
}
}
return vicinst;
}
/***********************************************************************
* Vectored Interrupt driver public functions
***********************************************************************/
/***********************************************************************
*
* Function: vic_initialize
*
* Purpose: Initialize the vectored interrupt controller
*
* Processing:
* Prior to any processing, make sure the VIC protection is
* disabled by clearing the protection bit in the VIC protection
* enable register. Loop through all of the VIC1 and VIC2
* interrupt sources and set the default interrupt vector for
* that source to 0x00000000, disable the interrupt, and clear
* and pending software interrupts. For VICs 1 and 2, set all
* the interrupt types to IRQ, clear any pending vectored
* interrupts, set the non-vectored interrupt addresses to the
* vic1_irq_dispatcher function (for VIC1) and the
* vic2_irq_dispatcher (for VIC2). For VIC1 and VIC2, disable
* each vectored interrupt and set the default vectored interrupt
* address to the default IRQ handler (vec_irq_handler) for safety.
* Before exiting, write the ARM vector table and jump addresses
* to the ARM vector area with a call to vic_int_write_table.
*
* Parameters:
* vectbladdr: Pointer to interrupt vector area, or 0xFFFFFFFF to
* have driver determine address
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
void vic_initialize(UNS_32 vectbladdr)
{
VIC_INT_SOURCE_T source;
INT_32 idx;
/* Disable VIC protection mode */
VIC1->prot_en &= ~VIC_PROT_EN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -