123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- * File : trap.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://openlab.rt-thread.com/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2006-08-23 Bernard first version
- * 2011-12-17 nl1031 for MicroBlaze
- *
- */
- #include <rtthread.h>
- #include "xparameters.h"
- #include "xintc.h"
- #include "xintc_i.h"
- #include "xintc_l.h"
- #define MAX_HANDLERS XPAR_INTC_MAX_NUM_INTR_INPUTS
- extern XIntc int_ctl; /* The instance of the Interrupt Controller */
- extern rt_atomic_t rt_interrupt_nest;
- rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
- rt_uint32_t rt_thread_switch_interrupt_flag;
- void rt_hw_interrupt_handler(int vector)
- {
- rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
- }
- /**
- * This function will initialize hardware interrupt
- */
- void rt_hw_interrupt_init()
- {
- rt_base_t index;
- XIntc_Config *CfgPtr;
- CfgPtr = &XIntc_ConfigTable[0];
- for (index = 0; index < MAX_HANDLERS; index ++)
- {
- CfgPtr->HandlerTable[index].Handler = (XInterruptHandler)rt_hw_interrupt_handler;
- }
- /* init interrupt nest, and context in thread sp */
- rt_interrupt_nest = 0;
- rt_interrupt_from_thread = 0;
- rt_interrupt_to_thread = 0;
- rt_thread_switch_interrupt_flag = 0;
- }
- /**
- * This function will mask a interrupt.
- * @param vector the interrupt number
- */
- void rt_hw_interrupt_mask(int vector)
- {
- /* disable interrupt */
- XIntc_Disable(&int_ctl,vector);
- }
- /**
- * This function will un-mask a interrupt.
- * @param vector the interrupt number
- */
- void rt_hw_interrupt_umask(int vector)
- {
- XIntc_Enable(&int_ctl,vector);
- }
- /**
- * This function will install a interrupt service routine to a interrupt.
- * @param vector the interrupt number
- * @param new_handler the interrupt service routine to be installed
- * @param old_handler the old interrupt service routine
- */
- void rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler)
- {
- XIntc_Config *CfgPtr;
- CfgPtr = &XIntc_ConfigTable[0];
- if(vector >= 0 && vector < MAX_HANDLERS)
- {
- if (*old_handler != RT_NULL) *old_handler = (rt_isr_handler_t)CfgPtr->HandlerTable[vector].Handler;
- if (new_handler != RT_NULL) CfgPtr->HandlerTable[vector].Handler = (XInterruptHandler)new_handler;
- }
- }
- /*****************************************************************************/
- /** copy from XIntc_DeviceInterruptHandler in xintc_l.c nl1031
- *
- * This function is the primary interrupt handler for the driver. It must be
- * connected to the interrupt source such that is called when an interrupt of
- * the interrupt controller is active. It will resolve which interrupts are
- * active and enabled and call the appropriate interrupt handler. It uses
- * the AckBeforeService flag in the configuration data to determine when to
- * acknowledge the interrupt. Highest priority interrupts are serviced first.
- * The driver can be configured to service only the highest priority interrupt
- * or all pending interrupts using the {XIntc_SetOptions()} function or
- * the {XIntc_SetIntrSrvOption()} function.
- *
- * This function assumes that an interrupt vector table has been previously
- * initialized. It does not verify that entries in the table are valid before
- * calling an interrupt handler.
- *
- *
- * @return None.
- *
- * @note
- *
- * The constant XPAR_INTC_MAX_NUM_INTR_INPUTS must be setup for this to compile.
- * Interrupt IDs range from 0 - 31 and correspond to the interrupt input signals
- * for the interrupt controller. XPAR_INTC_MAX_NUM_INTR_INPUTS specifies the
- * highest numbered interrupt input signal that is used.
- *
- ******************************************************************************/
- void rt_hw_trap_irq(void )
- {
- u32 intr_status;
- u32 intr_mask = 1;
- int intr_number;
- volatile u32 reg; /* used as bit bucket */
- XIntc_Config *cfg_ptr;
- /* Get the configuration data using the device ID */
- cfg_ptr = &XIntc_ConfigTable[0];
- /* Get the interrupts that are waiting to be serviced */
- intr_status = XIntc_GetIntrStatus(XPAR_INTC_0_BASEADDR);
- /* Service each interrupt that is active and enabled by checking each
- * bit in the register from LSB to MSB which corresponds to an interrupt
- * intput signal
- */
- for (intr_number = 0; intr_number < XPAR_INTC_MAX_NUM_INTR_INPUTS; intr_number++)
- {
- if (intr_status & 1)
- {
- XIntc_VectorTableEntry *table_ptr;
- /* If the interrupt has been setup to acknowledge it
- * before servicing the interrupt, then ack it
- */
- if (cfg_ptr->AckBeforeService & intr_mask)
- {
- XIntc_AckIntr(cfg_ptr->BaseAddress, intr_mask);
- }
- /* The interrupt is active and enabled, call the
- * interrupt handler that was setup with the specified
- * parameter
- */
- table_ptr = &(cfg_ptr->HandlerTable[intr_number]);
- table_ptr->Handler(table_ptr->CallBackRef);
- /* If the interrupt has been setup to acknowledge it
- * after it has been serviced then ack it
- */
- if ((cfg_ptr->AckBeforeService & intr_mask) == 0)
- {
- XIntc_AckIntr(cfg_ptr->BaseAddress, intr_mask);
- }
- /*
- * Read the ISR again to handle architectures with posted write
- * bus access issues.
- */
- reg = XIntc_GetIntrStatus(cfg_ptr->BaseAddress);
- /*
- * If only the highest priority interrupt is to be
- * serviced, exit loop and return after servicing
- * the interrupt
- */
- if (cfg_ptr->Options == XIN_SVC_SGL_ISR_OPTION)
- {
- return;
- }
- }
- /* Move to the next interrupt to check */
- intr_mask <<= 1;
- intr_status >>= 1;
- /* If there are no other bits set indicating that all interrupts
- * have been serviced, then exit the loop
- */
- if (intr_status == 0)
- {
- break;
- }
- }
- }
|