trap.c 6.2 KB

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