alt_irq_handler.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /******************************************************************************
  2. * *
  3. * License Agreement *
  4. * *
  5. * Copyright (c) 2009 Altera Corporation, San Jose, California, USA. *
  6. * All rights reserved. *
  7. * *
  8. * Permission is hereby granted, free of charge, to any person obtaining a *
  9. * copy of this software and associated documentation files (the "Software"), *
  10. * to deal in the Software without restriction, including without limitation *
  11. * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  12. * and/or sell copies of the Software, and to permit persons to whom the *
  13. * Software is furnished to do so, subject to the following conditions: *
  14. * *
  15. * The above copyright notice and this permission notice shall be included in *
  16. * all copies or substantial portions of the Software. *
  17. * *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
  23. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
  24. * DEALINGS IN THE SOFTWARE. *
  25. * *
  26. * This agreement shall be governed in all respects by the laws of the State *
  27. * of California and by the laws of the United States of America. *
  28. * *
  29. * Altera does not recommend, suggest or require that this reference design *
  30. * file be used in conjunction or combination with any other product. *
  31. ******************************************************************************/
  32. #include <errno.h>
  33. #include "system.h"
  34. /*
  35. * This interrupt handler only works with an internal interrupt controller
  36. * (IIC). Processors with an external interrupt controller (EIC) use an
  37. * implementation provided by an EIC driver.
  38. */
  39. #ifndef ALT_CPU_EIC_PRESENT
  40. #include "sys/alt_irq.h"
  41. #include "os/alt_hooks.h"
  42. #include "alt_types.h"
  43. /*
  44. * A table describing each interrupt handler. The index into the array is the
  45. * interrupt id associated with the handler.
  46. *
  47. * When an interrupt occurs, the associated handler is called with
  48. * the argument stored in the context member.
  49. */
  50. struct ALT_IRQ_HANDLER
  51. {
  52. #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
  53. void (*handler)(void*);
  54. #else
  55. void (*handler)(void*, alt_u32);
  56. #endif
  57. void *context;
  58. } alt_irq[ALT_NIRQ];
  59. /*
  60. * alt_irq_handler() is called by the interrupt exception handler in order to
  61. * process any outstanding interrupts.
  62. *
  63. * It is defined here since it is linked in using weak linkage.
  64. * This means that if there is never a call to alt_irq_register() (above) then
  65. * this function will not get linked in to the executable. This is acceptable
  66. * since if no handler is ever registered, then an interrupt can never occur.
  67. *
  68. * If Nios II interrupt vector custom instruction exists, use it to accelerate
  69. * the dispatch of interrupt handlers. The Nios II interrupt vector custom
  70. * instruction is present if the macro ALT_CI_INTERRUPT_VECTOR defined.
  71. */
  72. void alt_irq_handler (void) __attribute__ ((section (".exceptions")));
  73. void alt_irq_handler (void)
  74. {
  75. #ifdef ALT_CI_INTERRUPT_VECTOR
  76. alt_32 offset;
  77. char* alt_irq_base = (char*)alt_irq;
  78. #else
  79. alt_u32 active;
  80. alt_u32 mask;
  81. alt_u32 i;
  82. #endif /* ALT_CI_INTERRUPT_VECTOR */
  83. /*
  84. * Notify the operating system that we are at interrupt level.
  85. */
  86. ALT_OS_INT_ENTER();
  87. #ifdef ALT_CI_INTERRUPT_VECTOR
  88. /*
  89. * Call the interrupt vector custom instruction using the
  90. * ALT_CI_INTERRUPT_VECTOR macro.
  91. * It returns the offset into the vector table of the lowest-valued pending
  92. * interrupt (corresponds to highest priority) or a negative value if none.
  93. * The custom instruction assumes that each table entry is eight bytes.
  94. */
  95. while ((offset = ALT_CI_INTERRUPT_VECTOR) >= 0) {
  96. struct ALT_IRQ_HANDLER* handler_entry =
  97. (struct ALT_IRQ_HANDLER*)(alt_irq_base + offset);
  98. #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
  99. handler_entry->handler(handler_entry->context);
  100. #else
  101. handler_entry->handler(handler_entry->context, offset >> 3);
  102. #endif
  103. }
  104. #else /* ALT_CI_INTERRUPT_VECTOR */
  105. /*
  106. * Obtain from the interrupt controller a bit list of pending interrupts,
  107. * and then process the highest priority interrupt. This process loops,
  108. * loading the active interrupt list on each pass until alt_irq_pending()
  109. * return zero.
  110. *
  111. * The maximum interrupt latency for the highest priority interrupt is
  112. * reduced by finding out which interrupts are pending as late as possible.
  113. * Consider the case where the high priority interupt is asserted during
  114. * the interrupt entry sequence for a lower priority interrupt to see why
  115. * this is the case.
  116. */
  117. active = alt_irq_pending ();
  118. do
  119. {
  120. i = 0;
  121. mask = 1;
  122. /*
  123. * Test each bit in turn looking for an active interrupt. Once one is
  124. * found, the interrupt handler asigned by a call to alt_irq_register() is
  125. * called to clear the interrupt condition.
  126. */
  127. do
  128. {
  129. if (active & mask)
  130. {
  131. #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
  132. alt_irq[i].handler(alt_irq[i].context);
  133. #else
  134. alt_irq[i].handler(alt_irq[i].context, i);
  135. #endif
  136. break;
  137. }
  138. mask <<= 1;
  139. i++;
  140. } while (1);
  141. active = alt_irq_pending ();
  142. } while (active);
  143. #endif /* ALT_CI_INTERRUPT_VECTOR */
  144. /*
  145. * Notify the operating system that interrupt processing is complete.
  146. */
  147. ALT_OS_INT_EXIT();
  148. }
  149. #endif /* ALT_CPU_EIC_PRESENT */