xref: /nrf52832-nimble/rt-thread/libcpu/xilinx/microblaze/trap.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * File      : trap.c
3  * This file is part of RT-Thread RTOS
4  * COPYRIGHT (C) 2006, RT-Thread Development Team
5  *
6  * The license and distribution terms for this file may be
7  * found in the file LICENSE in this distribution or at
8  * http://openlab.rt-thread.com/license/LICENSE
9  *
10  * Change Logs:
11  * Date           Author       Notes
12  * 2006-08-23     Bernard      first version
13  * 2011-12-17	  nl1031	   for MicroBlaze
14  *
15  */
16 
17 #include 	<rtthread.h>
18 #include 	"xparameters.h"
19 #include 	"xintc.h"
20 #include    "xintc_i.h"
21 #include    "xintc_l.h"
22 
23 
24 #define MAX_HANDLERS  XPAR_INTC_MAX_NUM_INTR_INPUTS
25 extern XIntc int_ctl; /* The instance of the Interrupt Controller */
26 
27 
28 extern rt_uint32_t rt_interrupt_nest;
29 
30 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
31 rt_uint32_t rt_thread_switch_interrupt_flag;
32 
33 
rt_hw_interrupt_handler(int vector)34 void rt_hw_interrupt_handler(int vector)
35 {
36 	rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
37 }
38 
39 /**
40  * This function will initialize hardware interrupt
41  */
rt_hw_interrupt_init()42 void rt_hw_interrupt_init()
43 {
44 	rt_base_t index;
45 
46 	XIntc_Config           *CfgPtr;
47 
48 
49     CfgPtr = &XIntc_ConfigTable[0];
50 
51 
52 	for (index = 0; index < MAX_HANDLERS; index ++)
53 	{
54 		CfgPtr->HandlerTable[index].Handler = (XInterruptHandler)rt_hw_interrupt_handler;
55 	}
56 
57 	/* init interrupt nest, and context in thread sp */
58 	rt_interrupt_nest = 0;
59 	rt_interrupt_from_thread = 0;
60 	rt_interrupt_to_thread = 0;
61 	rt_thread_switch_interrupt_flag = 0;
62 }
63 
64 /**
65  * This function will mask a interrupt.
66  * @param vector the interrupt number
67  */
rt_hw_interrupt_mask(int vector)68 void rt_hw_interrupt_mask(int vector)
69 {
70 	/* disable interrupt */
71 	XIntc_Disable(&int_ctl,vector);
72 }
73 
74 /**
75  * This function will un-mask a interrupt.
76  * @param vector the interrupt number
77  */
rt_hw_interrupt_umask(int vector)78 void rt_hw_interrupt_umask(int vector)
79 {
80 	XIntc_Enable(&int_ctl,vector);
81 }
82 
83 /**
84  * This function will install a interrupt service routine to a interrupt.
85  * @param vector the interrupt number
86  * @param new_handler the interrupt service routine to be installed
87  * @param old_handler the old interrupt service routine
88  */
rt_hw_interrupt_install(int vector,rt_isr_handler_t new_handler,rt_isr_handler_t * old_handler)89 void rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler)
90 {
91 	XIntc_Config           *CfgPtr;
92 
93     CfgPtr = &XIntc_ConfigTable[0];
94 
95 	if(vector >= 0 && vector < MAX_HANDLERS)
96 	{
97 		if (*old_handler != RT_NULL) *old_handler = (rt_isr_handler_t)CfgPtr->HandlerTable[vector].Handler;
98 		if (new_handler != RT_NULL) CfgPtr->HandlerTable[vector].Handler = (XInterruptHandler)new_handler;
99 	}
100 }
101 
102 /*****************************************************************************/
103 /** copy from XIntc_DeviceInterruptHandler in xintc_l.c nl1031
104 *
105 * This function is the primary interrupt handler for the driver. It must be
106 * connected to the interrupt source such that is called when an interrupt of
107 * the interrupt controller is active. It will resolve which interrupts are
108 * active and enabled and call the appropriate interrupt handler. It uses
109 * the AckBeforeService flag in the configuration data to determine when to
110 * acknowledge the interrupt. Highest priority interrupts are serviced first.
111 * The driver can be configured to service only the highest priority interrupt
112 * or all pending interrupts using the {XIntc_SetOptions()} function or
113 * the {XIntc_SetIntrSrvOption()} function.
114 *
115 * This function assumes that an interrupt vector table has been previously
116 * initialized.  It does not verify that entries in the table are valid before
117 * calling an interrupt handler.
118 *
119 *
120 * @return	None.
121 *
122 * @note
123 *
124 * The constant XPAR_INTC_MAX_NUM_INTR_INPUTS must be setup for this to compile.
125 * Interrupt IDs range from 0 - 31 and correspond to the interrupt input signals
126 * for the interrupt controller. XPAR_INTC_MAX_NUM_INTR_INPUTS specifies the
127 * highest numbered interrupt input signal that is used.
128 *
129 ******************************************************************************/
130 
131 
rt_hw_trap_irq(void)132 void rt_hw_trap_irq(void )
133 {
134 	u32 intr_status;
135 	u32 intr_mask = 1;
136 	int intr_number;
137 	volatile u32 reg;			/* used as bit bucket */
138 	XIntc_Config *cfg_ptr;
139 
140 
141 	/* Get the configuration data using the device ID */
142 	cfg_ptr = &XIntc_ConfigTable[0];
143 
144 	/* Get the interrupts that are waiting to be serviced */
145 	intr_status = XIntc_GetIntrStatus(XPAR_INTC_0_BASEADDR);
146 
147 	/* Service each interrupt that is active and enabled by checking each
148 	 * bit in the register from LSB to MSB which corresponds to an interrupt
149 	 * intput signal
150 	 */
151 	for (intr_number = 0; intr_number < XPAR_INTC_MAX_NUM_INTR_INPUTS; intr_number++)
152 	{
153 		if (intr_status & 1)
154 		{
155 			XIntc_VectorTableEntry *table_ptr;
156 
157 			/* If the interrupt has been setup to acknowledge it
158 			 * before servicing the interrupt, then ack it
159 			 */
160 			if (cfg_ptr->AckBeforeService & intr_mask)
161 			{
162 				XIntc_AckIntr(cfg_ptr->BaseAddress, intr_mask);
163 			}
164 
165 			/* The interrupt is active and enabled, call the
166 			 * interrupt handler that was setup with the specified
167 			 * parameter
168 			 */
169 			table_ptr = &(cfg_ptr->HandlerTable[intr_number]);
170 			table_ptr->Handler(table_ptr->CallBackRef);
171 
172 			/* If the interrupt has been setup to acknowledge it
173 			 * after it has been serviced then ack it
174 			 */
175 			if ((cfg_ptr->AckBeforeService & intr_mask) == 0)
176 			{
177 				XIntc_AckIntr(cfg_ptr->BaseAddress, intr_mask);
178 			}
179 
180 			/*
181 			 * Read the ISR again to handle architectures with posted write
182 			 * bus access issues.
183 			 */
184 			reg = XIntc_GetIntrStatus(cfg_ptr->BaseAddress);
185 
186 			/*
187 			 * If only the highest priority interrupt is to be
188 			 * serviced, exit loop and return after servicing
189 			 * the interrupt
190 			 */
191 			if (cfg_ptr->Options == XIN_SVC_SGL_ISR_OPTION)
192 			{
193 				return;
194 			}
195 		}
196 
197 		/* Move to the next interrupt to check */
198 		intr_mask <<= 1;
199 		intr_status >>= 1;
200 
201 		/* If there are no other bits set indicating that all interrupts
202 		 * have been serviced, then exit the loop
203 		 */
204 		if (intr_status == 0)
205 		{
206 			break;
207 		}
208 	}
209 }
210 
211 
212