⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lh7a404_vic_driver.c

📁 在sharp 404开发板的串口测试代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************
 * $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 + -