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

📄 lh7a404_vic_driver.c

📁 在sharp 404开发板的串口测试代码
💻 C
📖 第 1 页 / 共 3 页
字号:

    /* For VIC1, set all interrupts as IRQ type, disabled, and
       cleared */
    for (source = VIC_FIRST_VIC1_INTERRUPT;
        source <= VIC_LAST_VIC1_INTERRUPT; source++)
    {
        /* Set all jump addresses to 0x00000000 */
        vic_func_ptrs[source] = (PFV) 0x00000000;

        /* Set interrupt to disabled */
        VIC1->intenclr = VIC_INT_SELECT((UNS_32)(source));

        /* Clear any pending software interrupts */
        VIC1->swint_clr = VIC_INT_SELECT((UNS_32)(source));
    }

    /* For VIC2, set all interrupts as IRQ type, disabled, and
       cleared */
    for (source = VIC_FIRST_VIC2_INTERRUPT;
        source <= VIC_LAST_VIC2_INTERRUPT; source++)
    {
        /* Set all jump addresses to 0x00000000 */
        vic_func_ptrs[source] = (PFV) 0x00000000;

        /* Set interrupt to disabled */
        VIC2->intenclr = VIC_INT_SELECT((UNS_32)(source -
            VIC_FIRST_VIC2_INTERRUPT));

        /* Clear any pending software interrupts */
        VIC2->swint_clr = VIC_INT_SELECT((UNS_32)(source -
            VIC_FIRST_VIC2_INTERRUPT));
    }

    /* All interrupt types are IRQ type */
    VIC1->intsel = 0x00000000;
    VIC2->intsel = 0x00000000;

    /* Clear any pending vectored interrupts */
    VIC1->vecaddr = 0x00000000;
    VIC2->vecaddr = 0x00000000;

    /* Set the default address for IRQs as the default handler */
    VIC1->nv_vecaddr = (PFV) &vic1_irq_dispatcher;
    VIC2->nv_vecaddr = (PFV) &vic2_irq_dispatcher;

    for (idx = 0; idx < 16; idx++)
    {
        /* Disable all vectored interrupts */
        VIC1->vec_cntl[idx] = 0x00000000;
        VIC2->vec_cntl[idx] = 0x00000000;

        /* Make all the default vectored handlers the default IRQ
           handler (safety) until they are correctly initialized */
        VIC1->vecaddrs[idx] = (PFV) &vec_irq_handler;
        VIC2->vecaddrs[idx] = (PFV) &vec_irq_handler;
    }

    /* Save user passed vector area pointer */
    vecarea = (UNS_32 *) vectbladdr;
    
    /* Put interrupt and exception code at ARM vector area */
    vic_int_write_table();
}

/***********************************************************************
 *
 * Function: vic_install_arm_handler
 *
 * Purpose: Install an new ARM interrupt or exception handler
 *
 * Processing:
 *     If the passed fiq_handler_ptr pointer is not 0x00000000, then
 *     set the handler jump address for the specific interrupt or
 *     exception to handler_ptr.  Recopy the vector table and vector
 *     branch instructions to the interrupt and exception area with a
 *     call to int_write_table.
 * 
 * Parameters:
 *     handler_id  : Must be an enumeration of type VECTOR_T
 *     handler_ptr : Pointer to new interrupt or exception handler
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes:
 *     For handler_id values of VIC1_IRQ_VEC and VIC2_IRQ_VEC, the
 *     handler addresses will be updated in the VIC1 and VIC2
 *     non-vectored address registers. These are used by the main ARM
 *     IRQ handler to determine the default IRQ jump addresses for
 *     VIC1 and VIC2.
 *
 **********************************************************************/
void vic_install_arm_handler(VECTOR_T handler_id,
                             PFV handler_ptr)
{
    /* Update address only if it is not NULL */
    if (handler_ptr != (PFV) 0x00000000)
    {
        switch (handler_id)
        {
            case RESET_VEC:
                vec_reset_handler = (UNS_32) handler_ptr;
                cp15_force_cache_coherence(
                    (UNS_32 *) &vec_reset_handler,
                    (UNS_32 *) &vec_reset_handler);
                break;

            case UNDEFINED_INST_VEC:
                vec_undefined_handler = (UNS_32) handler_ptr;
                cp15_force_cache_coherence(
                    (UNS_32 *) &vec_undefined_handler,
                    (UNS_32 *) &vec_undefined_handler);
                break;

            case SWI_VEC:
                vec_swi_handler = (UNS_32) handler_ptr;
                cp15_force_cache_coherence(
                    (UNS_32 *) &vec_swi_handler,
                    (UNS_32 *) &vec_swi_handler);
                break;

            case PREFETCH_ABORT_VEC:
                vec_prefetch_handler = (UNS_32) handler_ptr;
                cp15_force_cache_coherence(
                    (UNS_32 *) &vec_prefetch_handler,
                    (UNS_32 *) &vec_prefetch_handler);
                break;

            case DATA_ABORT_VEC:
                vec_abort_handler = (UNS_32) handler_ptr;
                cp15_force_cache_coherence(
                    (UNS_32 *) &vec_abort_handler,
                    (UNS_32 *) &vec_abort_handler);
                break;
    
            case IRQ_VEC:
                vec_irq_handler = (UNS_32) handler_ptr;
                cp15_force_cache_coherence(
                    (UNS_32 *) &vec_irq_handler,
                    (UNS_32 *) &vec_irq_handler);
                break;

            case FIQ_VEC:
                vec_fiq_handler = (UNS_32) handler_ptr;
                cp15_force_cache_coherence(
                    (UNS_32 *) &vec_fiq_handler,
                    (UNS_32 *) &vec_fiq_handler);
                break;

            case VIC1_IRQ_VEC:
                /* This is the vector that gets called from the first
                   vectored interrupt controller when not configured as
                   and FIQ or vectored interrupt */
                VIC1->nv_vecaddr = handler_ptr;
                break;

            case VIC2_IRQ_VEC:
                /* This is the vector that gets called from the second
                   vectored interrupt controller when not configured as
                   and FIQ or vectored interrupt */
                VIC2->nv_vecaddr = handler_ptr;
                break;

            default:
                break;
        }

        /* Update table in vector area */
        vic_int_write_table();
    }
}

/***********************************************************************
 *
 * Function: vic_install_handler
 *
 * Purpose: Install a function for a specific interrupt
 *
 * Processing:
 *     Save the function address for the interrupt source in the
 *     interrupt function jump table (used for IRQ interrupts only).
 *     If the interrupt type is VIC_IRQ, then clear the interrupt
 *     select bit for the interrupt source in the VIC1 or VIC2 select
 *     register to make it an IRQ interrupt type and return TRUE to the
 *     caller. If the interrupt type is VIC_FIQ, then set the interrupt
 *     select bit for the interrupt source in the VIC1 or VIC2 select
 *     register to make it an FIQ interrupt type and return TRUE to
 *     the caller. If the interrupt type is VIC_VECTORED, then call
 *     the vic_check_and_install function to check and install the
 *     vectored interrupt, using the return status from the function
 *     as the return status to the caller. If any interrupt type is
 *     passed, it is invalid and FALSE is returned 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 handler installation was good, otherwise FALSE
 *
 * Notes:
 *     This function will not install FIQ handlers. This interrupt
 *     driver design only allows 1 FIQ interrupt. Use the
 *     vic_install_arm_handler to install the FIQ interrupt, but use
 *     this function to change the interrupt to an FIQ type.
 *
 **********************************************************************/
BOOL_32 vic_install_handler(VIC_INT_SOURCE_T source,
                            VIC_INT_T itype,
                            PFV func_ptr)
{
    BOOL_32 installed = TRUE;

    /* Save a copy of the function pointer */
    vic_func_ptrs[source] = func_ptr;

    if (itype == VIC_IRQ)
    {
        if ((source >= VIC_FIRST_VIC1_INTERRUPT) &&
            (source <= VIC_LAST_VIC1_INTERRUPT))
        {
            /* Make the interrupt an IRQ type */
            VIC1->intsel &= ~VIC_INT_SELECT((UNS_32) source);
        }
        else
        {
            /* Make the interrupt an IRQ type */
            VIC2->intsel &= ~VIC_INT_SELECT((UNS_32) source -
                VIC_FIRST_VIC2_INTERRUPT);
        }
    }
    else if (itype == VIC_FIQ)
    {
        if ((source >= VIC_FIRST_VIC1_INTERRUPT) &&
            (source <= VIC_LAST_VIC1_INTERRUPT))
        {
            /* Make the interrupt an FIQ type */
            VIC1->intsel |= VIC_INT_SELECT((UNS_32) source);
        }
        else
        {
            /* Make the interrupt an FIQ type */
            VIC2->intsel |= VIC_INT_SELECT((UNS_32) source -
                VIC_FIRST_VIC2_INTERRUPT);
        }
    }
    else if (itype == VIC_VECTORED)
    {
        installed = vic_check_and_install(source, itype, func_ptr);
    }
    else
    {
        /* Invalid interrupt type */
        installed = FALSE;
    }

    return installed;
}

/***********************************************************************
 *
 * Function: vic_int_enable
 *
 * Purpose: Enable an interrupt
 *
 * Processing:
 *     If the interrupt source is in the range of the first VIC, then
 *     check the value of enable. If enable is TRUE, then enable the
 *     selected interrupt source by setting the appropriate enable bit
 *     in the VIC1 interrupt enable register. If enable is FALSE,
 *     disable the selected interrupt source by setting the appropriate
 *     disable bit in the VIC1 interrupt disable register. Otherwise
 *     (if the interrupt source is not in the range of the first VIC),
 *     perform the same logic to enable or disable the interrupt for
 *     the second VIC.
 * 
 * Parameters:
 *     source : Interrupt source of type VIC_INT_SOURCE_T
 *     enable : Must be TRUE to enable an interrupt or FALSE
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void vic_int_enable(VIC_INT_SOURCE_T source,
                    BOOL_32 enable)
{
    if ((source >= VIC_FIRST_VIC1_INTERRUPT) &&
        (source <= VIC_LAST_VIC1_INTERRUPT))
    {
        /* VIC1 interrupt */
        if (enable == TRUE)
        {
            /* Enable the interrupt */
            VIC1->inten = VIC_INT_SELECT((UNS_32)(source));
        }
        else
        {
            /* Disable the interrupt */
            VIC1->intenclr = VIC_INT_SELECT((UNS_32)(source));
        }
    }
    else
    {
        /* VIC2 interrupt */
        if (enable == TRUE)
        {
            /* Enable the interrupt */
            VIC2->inten = VIC_INT_SELECT((UNS_32)(source -
                VIC_FIRST_VIC2_INTERRUPT));
        }
        else
        {
            /* Disable the interrupt */
            VIC2->intenclr = VIC_INT_SELECT((UNS_32)(source -
                VIC_FIRST_VIC2_INTERRUPT));
        }
    }
}

/***********************************************************************
 *
 * Function: vic_int_pending
 *
 * Purpose: Check to see if an interrupt is pending
 *
 * Processing:
 *     If the interrupt source is in the range of the first VIC, then
 *     get the pending interrupt status from the IRQ status register
 *     for VIC1 and mask it with the inverted value of the VIC1
 *     interrupt select register. Get the pending interrupt status from
 *     the FIQ status register for VIC1 and mask it with the value of
 *     the VIC1 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.
 *
 *     If the interrupt source is in the range of the VIC2, then
 *     get the pending interrupt status from the IRQ status register

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -