interrupt.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * File : interrupt.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2011, 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://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2010-10-15 Bernard first version
  13. * 2010-10-15 lgnq modified for LS1B
  14. * 2013-03-29 aozima Modify the interrupt interface implementations.
  15. * 2015-07-06 chinesebear modified for loongson 1c
  16. */
  17. #include <rtthread.h>
  18. #include <rthw.h>
  19. #include "ls1c.h"
  20. #define MAX_INTR 32
  21. extern rt_uint32_t rt_interrupt_nest;
  22. rt_uint32_t rt_interrupt_from_thread;
  23. rt_uint32_t rt_interrupt_to_thread;
  24. rt_uint32_t rt_thread_switch_interrupt_flag;
  25. static struct rt_irq_desc irq_handle_table[MAX_INTR];
  26. void rt_interrupt_dispatch(void *ptreg);
  27. void rt_hw_timer_handler();
  28. static struct ls1c_intc_regs volatile *ls1c_hw0_icregs
  29. = (struct ls1c_intc_regs volatile *)(LS1C_INTREG_BASE);
  30. /**
  31. * @addtogroup Loongson LS1B
  32. */
  33. /*@{*/
  34. static void rt_hw_interrupt_handler(int vector, void *param)
  35. {
  36. rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
  37. }
  38. /**
  39. * This function will initialize hardware interrupt
  40. */
  41. void rt_hw_interrupt_init(void)
  42. {
  43. rt_int32_t idx;
  44. /* pci active low */
  45. ls1c_hw0_icregs->int_pol = -1; //must be done here 20110802 lgnq
  46. /* make all interrupts level triggered */
  47. (ls1c_hw0_icregs+0)->int_edge = 0x0000e000;
  48. /* mask all interrupts */
  49. (ls1c_hw0_icregs+0)->int_clr = 0xffffffff;
  50. rt_memset(irq_handle_table, 0x00, sizeof(irq_handle_table));
  51. for (idx = 0; idx < MAX_INTR; idx ++)
  52. {
  53. irq_handle_table[idx].handler = rt_hw_interrupt_handler;
  54. }
  55. /* init interrupt nest, and context in thread sp */
  56. rt_interrupt_nest = 0;
  57. rt_interrupt_from_thread = 0;
  58. rt_interrupt_to_thread = 0;
  59. rt_thread_switch_interrupt_flag = 0;
  60. }
  61. /**
  62. * This function will mask a interrupt.
  63. * @param vector the interrupt number
  64. */
  65. void rt_hw_interrupt_mask(int vector)
  66. {
  67. /* mask interrupt */
  68. (ls1c_hw0_icregs+(vector>>5))->int_en &= ~(1 << (vector&0x1f));
  69. }
  70. /**
  71. * This function will un-mask a interrupt.
  72. * @param vector the interrupt number
  73. */
  74. void rt_hw_interrupt_umask(int vector)
  75. {
  76. (ls1c_hw0_icregs+(vector>>5))->int_en |= (1 << (vector&0x1f));
  77. }
  78. /**
  79. * This function will install a interrupt service routine to a interrupt.
  80. * @param vector the interrupt number
  81. * @param new_handler the interrupt service routine to be installed
  82. * @param old_handler the old interrupt service routine
  83. */
  84. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  85. void *param, char *name)
  86. {
  87. rt_isr_handler_t old_handler = RT_NULL;
  88. if (vector >= 0 && vector < MAX_INTR)
  89. {
  90. old_handler = irq_handle_table[vector].handler;
  91. #ifdef RT_USING_INTERRUPT_INFO
  92. rt_strncpy(irq_handle_table[vector].name, name, RT_NAME_MAX);
  93. #endif /* RT_USING_INTERRUPT_INFO */
  94. irq_handle_table[vector].handler = handler;
  95. irq_handle_table[vector].param = param;
  96. }
  97. return old_handler;
  98. }
  99. void rt_interrupt_dispatch(void *ptreg)
  100. {
  101. int irq;
  102. void *param;
  103. rt_isr_handler_t irq_func;
  104. static rt_uint32_t status = 0;
  105. rt_uint32_t c0_status;
  106. rt_uint32_t c0_cause;
  107. volatile rt_uint32_t cause_im;
  108. volatile rt_uint32_t status_im;
  109. rt_uint32_t pending_im;
  110. /* check os timer */
  111. c0_status = read_c0_status();
  112. c0_cause = read_c0_cause();
  113. cause_im = c0_cause & ST0_IM;
  114. status_im = c0_status & ST0_IM;
  115. pending_im = cause_im & status_im;
  116. if (pending_im & CAUSEF_IP7)
  117. {
  118. rt_hw_timer_handler();
  119. }
  120. if (pending_im & CAUSEF_IP2)
  121. {
  122. /* the hardware interrupt */
  123. status = ls1c_hw0_icregs->int_isr;
  124. if (!status)
  125. return;
  126. for (irq = MAX_INTR; irq > 0; --irq)
  127. {
  128. if ((status & (1 << irq)))
  129. {
  130. status &= ~(1 << irq);
  131. irq_func = irq_handle_table[irq].handler;
  132. param = irq_handle_table[irq].param;
  133. /* do interrupt */
  134. irq_func(irq, param);
  135. #ifdef RT_USING_INTERRUPT_INFO
  136. irq_handle_table[irq].counter++;
  137. #endif /* RT_USING_INTERRUPT_INFO */
  138. /* ack interrupt */
  139. ls1c_hw0_icregs->int_clr |= (1 << irq);
  140. }
  141. }
  142. }
  143. else if (pending_im & CAUSEF_IP3)
  144. {
  145. rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  146. }
  147. else if (pending_im & CAUSEF_IP4)
  148. {
  149. rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  150. }
  151. else if (pending_im & CAUSEF_IP5)
  152. {
  153. rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  154. }
  155. else if (pending_im & CAUSEF_IP6)
  156. {
  157. rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
  158. }
  159. }
  160. /*@}*/