1 /* 2 * File : cpu_intc.c 3 * This file is part of RT-Thread RTOS 4 * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Change Logs: 21 * Date Author Notes 22 * 2016/09/07 Urey the first version 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 28 #include <rtthread.h> 29 #include <rthw.h> 30 #include <board.h> 31 32 #include "../common/mips.h" 33 34 #define INTERRUPTS_MAX 64 35 36 extern rt_uint32_t rt_interrupt_nest; 37 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; 38 rt_uint32_t rt_thread_switch_interrupt_flag; 39 40 static struct rt_irq_desc isr_table[INTERRUPTS_MAX]; 41 42 static void rt_hw_interrupt_handler(int vector, void *param) 43 { 44 rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); 45 } 46 47 void rt_hw_interrupt_init(void) 48 { 49 rt_int32_t idx; 50 51 clear_c0_status(0xff04); /* clear ERL */ 52 set_c0_status(0x0400); /* set IP2 */ 53 54 55 rt_memset(isr_table, 0x00, sizeof(isr_table)); 56 for (idx = 0; idx < INTERRUPTS_MAX; idx ++) 57 { 58 isr_table[idx].handler = rt_hw_interrupt_handler; 59 } 60 61 /* init interrupt nest, and context in thread sp */ 62 rt_interrupt_nest = 0; 63 rt_interrupt_from_thread = 0; 64 rt_interrupt_to_thread = 0; 65 rt_thread_switch_interrupt_flag = 0; 66 67 /* enable cpu interrupt mask */ 68 set_c0_status(IE_IRQ0 | IE_IRQ1); 69 } 70 71 void rt_hw_interrupt_mask(int vector) 72 { 73 /* mask interrupt */ 74 __intc_mask_irq(vector); 75 } 76 77 void rt_hw_interrupt_umask(int vector) 78 { 79 __intc_unmask_irq(vector); 80 } 81 82 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, 83 void *param, const char *name) 84 { 85 rt_isr_handler_t old_handler = RT_NULL; 86 87 if(vector < INTERRUPTS_MAX) 88 { 89 old_handler = isr_table[vector].handler; 90 91 #ifdef RT_USING_INTERRUPT_INFO 92 rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); 93 #endif /* RT_USING_INTERRUPT_INFO */ 94 isr_table[vector].handler = handler; 95 isr_table[vector].param = param; 96 } 97 98 return old_handler; 99 } 100 101 rt_inline int fls(int x) 102 { 103 __asm__("clz %0, %1" : "=r" (x) : "r" (x)); 104 105 return 32 - x; 106 } 107 108 void rt_interrupt_dispatch(void *ptreg) 109 { 110 void *param; 111 rt_isr_handler_t irq_func; 112 113 int irq = 0, group; 114 rt_uint32_t intc_ipr0 = 0, intc_ipr1 = 0, vpu_pending = 0; 115 116 rt_uint32_t c0_status, c0_cause; 117 rt_uint32_t pending_im; 118 119 /* check os timer */ 120 c0_status = read_c0_status(); 121 c0_cause = read_c0_cause(); 122 123 pending_im = (c0_cause & ST0_IM) & (c0_status & ST0_IM); 124 125 if (pending_im & CAUSEF_IP3) 126 { 127 extern void rt_hw_ost_handler(void); 128 rt_hw_ost_handler(); 129 return; 130 } 131 if (pending_im & CAUSEF_IP2) 132 { 133 intc_ipr0 = REG_INTC_IPR(0); 134 intc_ipr1 = REG_INTC_IPR(1); 135 136 if (intc_ipr0) 137 { 138 irq = fls(intc_ipr0) - 1; 139 intc_ipr0 &= ~(1<<irq); 140 } 141 else if(intc_ipr1) 142 { 143 irq = fls(intc_ipr1) - 1; 144 intc_ipr1 &= ~(1<<irq); 145 irq += 32; 146 } 147 else 148 { 149 //VPU 150 } 151 152 if (irq >= INTERRUPTS_MAX) 153 rt_kprintf("max interrupt, irq=%d\n", irq); 154 155 /* do interrupt */ 156 irq_func = isr_table[irq].handler; 157 param = isr_table[irq].param; 158 (*irq_func)(irq, param); 159 160 #ifdef RT_USING_INTERRUPT_INFO 161 isr_table[irq].counter++; 162 #endif /* RT_USING_INTERRUPT_INFO */ 163 164 /* ack interrupt */ 165 __intc_ack_irq(irq); 166 } 167 168 if (pending_im & CAUSEF_IP0) 169 rt_kprintf("CAUSEF_IP0\n"); 170 if (pending_im & CAUSEF_IP1) 171 rt_kprintf("CAUSEF_IP1\n"); 172 if (pending_im & CAUSEF_IP4) 173 rt_kprintf("CAUSEF_IP4\n"); 174 if (pending_im & CAUSEF_IP5) 175 rt_kprintf("CAUSEF_IP5\n"); 176 if (pending_im & CAUSEF_IP6) 177 rt_kprintf("CAUSEF_IP6\n"); 178 if (pending_im & CAUSEF_IP7) 179 rt_kprintf("CAUSEF_IP7\n"); 180 } 181 182 #ifdef RT_USING_INTERRUPT_INFO 183 #include <finsh.h> 184 int list_irqs(void) 185 { 186 int index; 187 188 rt_kprintf("interrupt list:\n"); 189 rt_kprintf("----------------\n"); 190 rt_kprintf("name counter\n"); 191 for (index = 0; index < INTERRUPTS_MAX; index ++) 192 { 193 if (isr_table[index].handler != rt_hw_interrupt_handler) 194 { 195 rt_kprintf("%-*.*s %d\n", RT_NAME_MAX, RT_NAME_MAX, isr_table[index].name, isr_table[index].counter); 196 } 197 } 198 199 return 0; 200 } 201 MSH_CMD_EXPORT(list_irqs, list interrupt counter); 202 #endif 203 204 unsigned int spin_lock_irqsave(void) 205 { 206 register unsigned int t; 207 t = read_c0_status(); 208 write_c0_status((t & (~1))); 209 return (t); 210 } 211 212 void spin_unlock_irqrestore(unsigned int val) 213 { 214 write_c0_status(val); 215 } 216